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();
|
||||
|
||||
try container.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
.size = .{
|
||||
.grow = .horizontal,
|
||||
.dim = .{ .y = 10 },
|
||||
@@ -164,7 +164,7 @@ pub fn main() !void {
|
||||
}, input_field.element()));
|
||||
|
||||
const nested_container: App.Container = try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
}, spinner.element());
|
||||
try container.append(nested_container);
|
||||
|
||||
|
||||
@@ -58,13 +58,13 @@ pub fn main() !void {
|
||||
},
|
||||
}, .{});
|
||||
try box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
}, .{}));
|
||||
try box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
}, .{}));
|
||||
try box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
}, .{}));
|
||||
defer box.deinit();
|
||||
|
||||
@@ -93,7 +93,7 @@ pub fn main() !void {
|
||||
.direction = .vertical,
|
||||
},
|
||||
.border = .{
|
||||
.color = .light_blue,
|
||||
.color = .lightblue,
|
||||
.sides = .all,
|
||||
},
|
||||
}, .{});
|
||||
|
||||
@@ -102,7 +102,7 @@ pub fn main() !void {
|
||||
}, quit_text.element());
|
||||
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 app.start();
|
||||
|
||||
@@ -72,7 +72,7 @@ pub fn main() !void {
|
||||
var renderer = zterm.Renderer.Buffered.init(allocator);
|
||||
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();
|
||||
|
||||
var mouse_draw: MouseDraw = .{};
|
||||
@@ -89,7 +89,7 @@ pub fn main() !void {
|
||||
defer container.deinit();
|
||||
|
||||
try container.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
.size = .{
|
||||
.grow = .horizontal,
|
||||
.dim = .{ .y = 1 },
|
||||
@@ -101,7 +101,7 @@ pub fn main() !void {
|
||||
.sides = .all,
|
||||
.color = .black,
|
||||
},
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
.layout = .{
|
||||
.separator = .{
|
||||
.enabled = true,
|
||||
@@ -110,10 +110,10 @@ pub fn main() !void {
|
||||
},
|
||||
}, .{});
|
||||
try nested_container.append(try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
}, mouse_draw.element()));
|
||||
try nested_container.append(try .init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_grey },
|
||||
.rectangle = .{ .fill = .lightgrey },
|
||||
}, second_mouse_draw.element()));
|
||||
try container.append(nested_container);
|
||||
|
||||
|
||||
@@ -89,19 +89,19 @@ pub fn main() !void {
|
||||
},
|
||||
}, .{});
|
||||
try top_box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
.size = .{
|
||||
.dim = .{ .y = 30 },
|
||||
},
|
||||
}, .{}));
|
||||
try top_box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
.size = .{
|
||||
.dim = .{ .y = 5 },
|
||||
},
|
||||
}, element));
|
||||
try top_box.append(try App.Container.init(allocator, .{
|
||||
.rectangle = .{ .fill = .light_green },
|
||||
.rectangle = .{ .fill = .lightgreen },
|
||||
.size = .{
|
||||
.dim = .{ .y = 2 },
|
||||
},
|
||||
|
||||
@@ -93,6 +93,7 @@ pub fn App(comptime M: type, comptime E: type) type {
|
||||
if (this.termios) |termios| {
|
||||
try terminal.disableMouseSupport();
|
||||
try terminal.showCursor();
|
||||
try terminal.resetCursorColor();
|
||||
try terminal.restoreScreen();
|
||||
try terminal.disableRawMode(&termios);
|
||||
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 {
|
||||
terminal.disableMouseSupport() catch {};
|
||||
terminal.showCursor() catch {};
|
||||
terminal.resetCursorColor() catch {};
|
||||
terminal.restoreScreen() catch {};
|
||||
terminal.disableRawMode(&.{
|
||||
.iflag = .{},
|
||||
|
||||
@@ -25,7 +25,7 @@ test "ascii styled text" {
|
||||
.{ .cp = 'Y', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } },
|
||||
.{ .cp = 'v', .style = .{ .emphasis = &.{ .bold, .underline } } },
|
||||
.{ .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);
|
||||
@@ -45,7 +45,7 @@ test "utf-8 styled text" {
|
||||
.{ .cp = '╭', .style = .{ .fg = .green, .bg = .grey, .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);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
pub const Color = enum(u8) {
|
||||
default = 0,
|
||||
black = 16,
|
||||
light_red = 1,
|
||||
light_green,
|
||||
light_yellow,
|
||||
light_blue,
|
||||
light_magenta,
|
||||
light_cyan,
|
||||
light_grey,
|
||||
lightred = 1,
|
||||
lightgreen,
|
||||
lightyellow,
|
||||
lightblue,
|
||||
lightmagenta,
|
||||
lightcyan,
|
||||
lightgrey,
|
||||
grey,
|
||||
red,
|
||||
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_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 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_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.
|
||||
pub const Configuration = packed struct {
|
||||
color: Color,
|
||||
cursor: Color,
|
||||
|
||||
pub fn init(color: Color) @This() {
|
||||
return .{ .color = color };
|
||||
pub fn init(color: Color, cursor: Color) @This() {
|
||||
return .{
|
||||
.color = color,
|
||||
.cursor = cursor,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -680,10 +684,13 @@ pub fn Input(Model: type, Event: type, Queue: type) fn (meta.FieldEnum(Event)) t
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.input.items.len < cells.len)
|
||||
cells[this.input.items.len - this.cursor_offset].style.cursor = true
|
||||
else
|
||||
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_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_color = this.configuration.cursor;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1615,7 +1622,7 @@ test "input element" {
|
||||
};
|
||||
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();
|
||||
|
||||
const input_container: Container(Model, Event) = try .init(allocator, .{
|
||||
|
||||
@@ -104,6 +104,7 @@ pub const Buffered = struct {
|
||||
.x = @truncate(col),
|
||||
.y = @truncate(row),
|
||||
};
|
||||
try cvs.style.set_cursor_color(&writer);
|
||||
}
|
||||
|
||||
if (cs.eql(cvs)) continue;
|
||||
|
||||
@@ -12,6 +12,7 @@ fg: Color = .default,
|
||||
bg: Color = .default,
|
||||
ul: Color = .default,
|
||||
cursor: bool = false,
|
||||
cursor_color: Color = .default,
|
||||
ul_style: Underline = .off,
|
||||
emphasis: []const Emphasis,
|
||||
|
||||
@@ -40,6 +41,14 @@ pub fn eql(this: Style, other: Style) bool {
|
||||
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 {
|
||||
var buffer: [4]u8 = undefined;
|
||||
const bytes = try unicode.utf8Encode(cp, &buffer);
|
||||
@@ -72,4 +81,5 @@ const unicode = std.unicode;
|
||||
const meta = std.meta;
|
||||
const assert = std.debug.assert;
|
||||
const Color = @import("color.zig").Color;
|
||||
const ctlseqs = @import("ctlseqs.zig");
|
||||
const Style = @This();
|
||||
|
||||
@@ -42,6 +42,10 @@ pub fn showCursor() !void {
|
||||
_ = 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 {
|
||||
_ = try posix.write(posix.STDIN_FILENO, ctlseqs.home);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user