feat(terminal/osc12): define cursor color through style of cell that describes the cursor position
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 1m33s
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 1m33s
The `.default` color will reset the cursor color to the terminal's default color
This commit is contained in:
@@ -156,7 +156,7 @@ pub fn main() !void {
|
|||||||
defer container.deinit();
|
defer container.deinit();
|
||||||
|
|
||||||
try container.append(try App.Container.init(allocator, .{
|
try container.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
.size = .{
|
.size = .{
|
||||||
.grow = .horizontal,
|
.grow = .horizontal,
|
||||||
.dim = .{ .y = 10 },
|
.dim = .{ .y = 10 },
|
||||||
@@ -164,7 +164,7 @@ pub fn main() !void {
|
|||||||
}, input_field.element()));
|
}, input_field.element()));
|
||||||
|
|
||||||
const nested_container: App.Container = try .init(allocator, .{
|
const nested_container: App.Container = try .init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
}, spinner.element());
|
}, spinner.element());
|
||||||
try container.append(nested_container);
|
try container.append(nested_container);
|
||||||
|
|
||||||
|
|||||||
@@ -58,13 +58,13 @@ pub fn main() !void {
|
|||||||
},
|
},
|
||||||
}, .{});
|
}, .{});
|
||||||
try box.append(try App.Container.init(allocator, .{
|
try box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
}, .{}));
|
}, .{}));
|
||||||
try box.append(try App.Container.init(allocator, .{
|
try box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
}, .{}));
|
}, .{}));
|
||||||
try box.append(try App.Container.init(allocator, .{
|
try box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
}, .{}));
|
}, .{}));
|
||||||
defer box.deinit();
|
defer box.deinit();
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ pub fn main() !void {
|
|||||||
.direction = .vertical,
|
.direction = .vertical,
|
||||||
},
|
},
|
||||||
.border = .{
|
.border = .{
|
||||||
.color = .light_blue,
|
.color = .lightblue,
|
||||||
.sides = .all,
|
.sides = .all,
|
||||||
},
|
},
|
||||||
}, .{});
|
}, .{});
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ pub fn main() !void {
|
|||||||
}, quit_text.element());
|
}, quit_text.element());
|
||||||
defer container.deinit();
|
defer container.deinit();
|
||||||
|
|
||||||
try container.append(try App.Container.init(allocator, .{ .rectangle = .{ .fill = .light_grey } }, element));
|
try container.append(try App.Container.init(allocator, .{ .rectangle = .{ .fill = .lightgrey } }, element));
|
||||||
try container.append(try App.Container.init(allocator, .{ .rectangle = .{ .fill = .black } }, button.element()));
|
try container.append(try App.Container.init(allocator, .{ .rectangle = .{ .fill = .black } }, button.element()));
|
||||||
|
|
||||||
try app.start();
|
try app.start();
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ pub fn main() !void {
|
|||||||
var renderer = zterm.Renderer.Buffered.init(allocator);
|
var renderer = zterm.Renderer.Buffered.init(allocator);
|
||||||
defer renderer.deinit();
|
defer renderer.deinit();
|
||||||
|
|
||||||
var input_field: App.Input(.accept) = .init(allocator, &app.queue, .init(.black));
|
var input_field: App.Input(.accept) = .init(allocator, &app.queue, .init(.black, .blue));
|
||||||
defer input_field.deinit();
|
defer input_field.deinit();
|
||||||
|
|
||||||
var mouse_draw: MouseDraw = .{};
|
var mouse_draw: MouseDraw = .{};
|
||||||
@@ -89,7 +89,7 @@ pub fn main() !void {
|
|||||||
defer container.deinit();
|
defer container.deinit();
|
||||||
|
|
||||||
try container.append(try App.Container.init(allocator, .{
|
try container.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
.size = .{
|
.size = .{
|
||||||
.grow = .horizontal,
|
.grow = .horizontal,
|
||||||
.dim = .{ .y = 1 },
|
.dim = .{ .y = 1 },
|
||||||
@@ -101,7 +101,7 @@ pub fn main() !void {
|
|||||||
.sides = .all,
|
.sides = .all,
|
||||||
.color = .black,
|
.color = .black,
|
||||||
},
|
},
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
.layout = .{
|
.layout = .{
|
||||||
.separator = .{
|
.separator = .{
|
||||||
.enabled = true,
|
.enabled = true,
|
||||||
@@ -110,10 +110,10 @@ pub fn main() !void {
|
|||||||
},
|
},
|
||||||
}, .{});
|
}, .{});
|
||||||
try nested_container.append(try .init(allocator, .{
|
try nested_container.append(try .init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
}, mouse_draw.element()));
|
}, mouse_draw.element()));
|
||||||
try nested_container.append(try .init(allocator, .{
|
try nested_container.append(try .init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_grey },
|
.rectangle = .{ .fill = .lightgrey },
|
||||||
}, second_mouse_draw.element()));
|
}, second_mouse_draw.element()));
|
||||||
try container.append(nested_container);
|
try container.append(nested_container);
|
||||||
|
|
||||||
|
|||||||
@@ -89,19 +89,19 @@ pub fn main() !void {
|
|||||||
},
|
},
|
||||||
}, .{});
|
}, .{});
|
||||||
try top_box.append(try App.Container.init(allocator, .{
|
try top_box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
.size = .{
|
.size = .{
|
||||||
.dim = .{ .y = 30 },
|
.dim = .{ .y = 30 },
|
||||||
},
|
},
|
||||||
}, .{}));
|
}, .{}));
|
||||||
try top_box.append(try App.Container.init(allocator, .{
|
try top_box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
.size = .{
|
.size = .{
|
||||||
.dim = .{ .y = 5 },
|
.dim = .{ .y = 5 },
|
||||||
},
|
},
|
||||||
}, element));
|
}, element));
|
||||||
try top_box.append(try App.Container.init(allocator, .{
|
try top_box.append(try App.Container.init(allocator, .{
|
||||||
.rectangle = .{ .fill = .light_green },
|
.rectangle = .{ .fill = .lightgreen },
|
||||||
.size = .{
|
.size = .{
|
||||||
.dim = .{ .y = 2 },
|
.dim = .{ .y = 2 },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ pub fn App(comptime M: type, comptime E: type) type {
|
|||||||
if (this.termios) |termios| {
|
if (this.termios) |termios| {
|
||||||
try terminal.disableMouseSupport();
|
try terminal.disableMouseSupport();
|
||||||
try terminal.showCursor();
|
try terminal.showCursor();
|
||||||
|
try terminal.resetCursorColor();
|
||||||
try terminal.restoreScreen();
|
try terminal.restoreScreen();
|
||||||
try terminal.disableRawMode(&termios);
|
try terminal.disableRawMode(&termios);
|
||||||
try terminal.exitAltScreen();
|
try terminal.exitAltScreen();
|
||||||
@@ -426,6 +427,7 @@ pub fn App(comptime M: type, comptime E: type) type {
|
|||||||
pub fn panic_handler(msg: []const u8, _: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
|
pub fn panic_handler(msg: []const u8, _: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
|
||||||
terminal.disableMouseSupport() catch {};
|
terminal.disableMouseSupport() catch {};
|
||||||
terminal.showCursor() catch {};
|
terminal.showCursor() catch {};
|
||||||
|
terminal.resetCursorColor() catch {};
|
||||||
terminal.restoreScreen() catch {};
|
terminal.restoreScreen() catch {};
|
||||||
terminal.disableRawMode(&.{
|
terminal.disableRawMode(&.{
|
||||||
.iflag = .{},
|
.iflag = .{},
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ test "ascii styled text" {
|
|||||||
.{ .cp = 'Y', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } },
|
.{ .cp = 'Y', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } },
|
||||||
.{ .cp = 'v', .style = .{ .emphasis = &.{ .bold, .underline } } },
|
.{ .cp = 'v', .style = .{ .emphasis = &.{ .bold, .underline } } },
|
||||||
.{ .cp = 'e', .style = .{ .emphasis = &.{.italic} } },
|
.{ .cp = 'e', .style = .{ .emphasis = &.{.italic} } },
|
||||||
.{ .cp = 's', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
.{ .cp = 's', .style = .{ .fg = .lightgreen, .bg = .black, .emphasis = &.{.underline} } },
|
||||||
};
|
};
|
||||||
|
|
||||||
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
||||||
@@ -45,7 +45,7 @@ test "utf-8 styled text" {
|
|||||||
.{ .cp = '╭', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } },
|
.{ .cp = '╭', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } },
|
||||||
.{ .cp = '─', .style = .{ .emphasis = &.{} } },
|
.{ .cp = '─', .style = .{ .emphasis = &.{} } },
|
||||||
.{ .cp = '┄', .style = .{ .emphasis = &.{} } },
|
.{ .cp = '┄', .style = .{ .emphasis = &.{} } },
|
||||||
.{ .cp = '┘', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } },
|
.{ .cp = '┘', .style = .{ .fg = .lightgreen, .bg = .black, .emphasis = &.{.underline} } },
|
||||||
};
|
};
|
||||||
|
|
||||||
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
var writer = std.Io.Writer.Allocating.init(std.testing.allocator);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
pub const Color = enum(u8) {
|
pub const Color = enum(u8) {
|
||||||
default = 0,
|
default = 0,
|
||||||
black = 16,
|
black = 16,
|
||||||
light_red = 1,
|
lightred = 1,
|
||||||
light_green,
|
lightgreen,
|
||||||
light_yellow,
|
lightyellow,
|
||||||
light_blue,
|
lightblue,
|
||||||
light_magenta,
|
lightmagenta,
|
||||||
light_cyan,
|
lightcyan,
|
||||||
light_grey,
|
lightgrey,
|
||||||
grey,
|
grey,
|
||||||
red,
|
red,
|
||||||
green,
|
green,
|
||||||
|
|||||||
@@ -139,5 +139,6 @@ pub const osc10_reset = "\x1b]110\x1b\\"; // reset fg to terminal default
|
|||||||
pub const osc11_query = "\x1b]11;?\x1b\\"; // bg
|
pub const osc11_query = "\x1b]11;?\x1b\\"; // bg
|
||||||
pub const osc11_set = "\x1b]11;rgb:{x:0>2}{x:0>2}/{x:0>2}{x:0>2}/{x:0>2}{x:0>2}\x1b\\"; // set default terminal bg
|
pub const osc11_set = "\x1b]11;rgb:{x:0>2}{x:0>2}/{x:0>2}{x:0>2}/{x:0>2}{x:0>2}\x1b\\"; // set default terminal bg
|
||||||
pub const osc11_reset = "\x1b]111\x1b\\"; // reset bg to terminal default
|
pub const osc11_reset = "\x1b]111\x1b\\"; // reset bg to terminal default
|
||||||
|
pub const osc12_set = "\x1b]12;{s}\x1b\\"; // set the cursor color through the name of the 8 base colors!
|
||||||
pub const osc12_query = "\x1b]12;?\x1b\\"; // cursor color
|
pub const osc12_query = "\x1b]12;?\x1b\\"; // cursor color
|
||||||
pub const osc12_reset = "\x1b]112\x1b\\"; // reset cursor to terminal default
|
pub const osc12_reset = "\x1b]112\x1b\\"; // reset cursor to terminal default
|
||||||
|
|||||||
@@ -519,9 +519,13 @@ pub fn Input(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) t
|
|||||||
/// Configuration for InputField's.
|
/// Configuration for InputField's.
|
||||||
pub const Configuration = packed struct {
|
pub const Configuration = packed struct {
|
||||||
color: Color,
|
color: Color,
|
||||||
|
cursor: Color,
|
||||||
|
|
||||||
pub fn init(color: Color) @This() {
|
pub fn init(color: Color, cursor: Color) @This() {
|
||||||
return .{ .color = color };
|
return .{
|
||||||
|
.color = color,
|
||||||
|
.cursor = cursor,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -680,10 +684,13 @@ pub fn Input(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) t
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.input.items.len < cells.len)
|
if (this.input.items.len < cells.len) {
|
||||||
cells[this.input.items.len - this.cursor_offset].style.cursor = true
|
cells[this.input.items.len - this.cursor_offset].style.cursor = true;
|
||||||
else
|
cells[this.input.items.len - this.cursor_offset].style.cursor_color = this.configuration.cursor;
|
||||||
|
} else {
|
||||||
cells[this.input.items.len - offset - this.cursor_offset].style.cursor = true;
|
cells[this.input.items.len - offset - this.cursor_offset].style.cursor = true;
|
||||||
|
cells[this.input.items.len - offset - this.cursor_offset].style.cursor_color = this.configuration.cursor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1615,7 +1622,7 @@ test "input element" {
|
|||||||
};
|
};
|
||||||
var queue: Queue = .{};
|
var queue: Queue = .{};
|
||||||
|
|
||||||
var input_element: Input(Model, Event, Queue)(.accept) = .init(allocator, &queue, .init(.black));
|
var input_element: Input(Model, Event, Queue)(.accept) = .init(allocator, &queue, .init(.black, .default));
|
||||||
defer input_element.deinit();
|
defer input_element.deinit();
|
||||||
|
|
||||||
const input_container: Container(Model, Event) = try .init(allocator, .{
|
const input_container: Container(Model, Event) = try .init(allocator, .{
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ pub const Buffered = struct {
|
|||||||
.x = @truncate(col),
|
.x = @truncate(col),
|
||||||
.y = @truncate(row),
|
.y = @truncate(row),
|
||||||
};
|
};
|
||||||
|
try cvs.style.set_cursor_color(&writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs.eql(cvs)) continue;
|
if (cs.eql(cvs)) continue;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ fg: Color = .default,
|
|||||||
bg: Color = .default,
|
bg: Color = .default,
|
||||||
ul: Color = .default,
|
ul: Color = .default,
|
||||||
cursor: bool = false,
|
cursor: bool = false,
|
||||||
|
cursor_color: Color = .default,
|
||||||
ul_style: Underline = .off,
|
ul_style: Underline = .off,
|
||||||
emphasis: []const Emphasis,
|
emphasis: []const Emphasis,
|
||||||
|
|
||||||
@@ -40,6 +41,14 @@ pub fn eql(this: Style, other: Style) bool {
|
|||||||
return meta.eql(this, other);
|
return meta.eql(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cursor_color(this: Style, writer: *std.Io.Writer) !void {
|
||||||
|
if (!this.cursor) return;
|
||||||
|
switch (this.cursor_color) {
|
||||||
|
.default => try writer.print(ctlseqs.osc12_reset, .{}),
|
||||||
|
else => try writer.print(ctlseqs.osc12_set, .{@tagName(this.cursor_color)}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn value(this: Style, writer: *std.Io.Writer, cp: u21) !void {
|
pub fn value(this: Style, writer: *std.Io.Writer, cp: u21) !void {
|
||||||
var buffer: [4]u8 = undefined;
|
var buffer: [4]u8 = undefined;
|
||||||
const bytes = try unicode.utf8Encode(cp, &buffer);
|
const bytes = try unicode.utf8Encode(cp, &buffer);
|
||||||
@@ -72,4 +81,5 @@ const unicode = std.unicode;
|
|||||||
const meta = std.meta;
|
const meta = std.meta;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Color = @import("color.zig").Color;
|
const Color = @import("color.zig").Color;
|
||||||
|
const ctlseqs = @import("ctlseqs.zig");
|
||||||
const Style = @This();
|
const Style = @This();
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ pub fn showCursor() !void {
|
|||||||
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.show_cursor);
|
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.show_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resetCursorColor() !void {
|
||||||
|
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.osc12_reset);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setCursorPositionHome() !void {
|
pub fn setCursorPositionHome() !void {
|
||||||
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.home);
|
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.home);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user