feat: add line number styles

This commit is contained in:
CJ van den Berg 2025-02-05 22:27:58 +01:00
parent 79799b248e
commit 8964a361a7
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
4 changed files with 88 additions and 8 deletions

View file

@ -5,6 +5,7 @@ theme: []const u8 = "default",
input_mode: []const u8 = "flow",
gutter_line_numbers: bool = true,
gutter_line_numbers_relative: bool = false,
gutter_line_numbers_style: LineNumberStyle = .ascii,
gutter_symbols: bool = true,
enable_terminal_cursor: bool = true,
enable_terminal_color_scheme: bool = builtin.os.tag != .windows,
@ -25,3 +26,10 @@ bottom_bar: []const u8 = "mode file log selection diagnostics keybind linenumber
lsp_request_timeout: usize = 10,
include_files: []const u8 = "",
pub const LineNumberStyle = enum {
ascii,
digital,
subscript,
superscript,
};

View file

@ -99,6 +99,7 @@
["alt+down", "pull_down"],
["alt+enter", "insert_line"],
["alt+f10", "gutter_mode_next"],
["alt+shift+f10", "gutter_style_next"],
["alt+f12", "goto_declaration"],
["alt+shift+p", "open_command_palette"],
["alt+shift+d", "dupe_up"],

View file

@ -17,6 +17,7 @@ const Widget = @import("Widget.zig");
const MessageFilter = @import("MessageFilter.zig");
const tui = @import("tui.zig");
const ed = @import("editor.zig");
const LineNumberStyle = @import("config").LineNumberStyle;
allocator: Allocator,
plane: Plane,
@ -28,6 +29,7 @@ row: u32 = 1,
line: usize = 0,
linenum: bool,
relative: bool,
render_style: LineNumberStyle,
highlight: bool,
symbols: bool,
width: usize = 4,
@ -48,6 +50,7 @@ pub fn create(allocator: Allocator, parent: Widget, event_source: Widget, editor
.parent = parent,
.linenum = tui.config().gutter_line_numbers,
.relative = tui.config().gutter_line_numbers_relative,
.render_style = tui.config().gutter_line_numbers_style,
.highlight = tui.config().highlight_current_line_gutter,
.symbols = tui.config().gutter_symbols,
.editor = editor,
@ -94,6 +97,8 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.primary_click(y);
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON2), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.middle_click();
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON3), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.secondary_click();
if (try m.match(.{ "D", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
@ -108,9 +113,8 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
fn update_width(self: *Self) void {
if (!self.linenum) return;
var buf: [31]u8 = undefined;
const tmp = std.fmt.bufPrint(&buf, "{d}", .{self.lines}) catch return;
self.width = if (self.relative and tmp.len > 4) 4 else @max(tmp.len, 2);
const width = int_width(self.lines);
self.width = if (self.relative and width > 4) 4 else @max(width, 2);
self.width += if (self.symbols) 3 else 1;
}
@ -164,7 +168,6 @@ pub fn render_linear(self: *Self, theme: *const Widget.Theme) void {
var linenum = self.row + 1;
var rows = self.rows;
var diff_symbols = self.diff_symbols.items;
var buf: [31:0]u8 = undefined;
while (rows > 0) : (rows -= 1) {
if (linenum > self.lines) return;
if (linenum == self.line + 1) {
@ -174,7 +177,8 @@ pub fn render_linear(self: *Self, theme: *const Widget.Theme) void {
self.plane.set_style(.{ .fg = theme.editor_gutter.fg });
self.plane.off_styles(styles.bold);
}
_ = self.plane.print_aligned_right(@intCast(pos), "{s}", .{std.fmt.bufPrintZ(&buf, "{d} ", .{linenum}) catch return}) catch {};
try self.plane.cursor_move_yx(@intCast(pos), 0);
try self.print_digits(linenum, self.render_style);
if (self.highlight and linenum == self.line + 1)
self.render_line_highlight(pos, theme);
self.render_diff_symbols(&diff_symbols, pos, linenum, theme);
@ -191,13 +195,17 @@ pub fn render_relative(self: *Self, theme: *const Widget.Theme) void {
var abs_linenum = self.row + 1;
var rows = self.rows;
var diff_symbols = self.diff_symbols.items;
var buf: [31:0]u8 = undefined;
while (rows > 0) : (rows -= 1) {
if (pos > self.lines - @as(u32, @intCast(row))) return;
self.plane.set_style(if (linenum == 0) theme.editor_gutter_active else theme.editor_gutter);
const val = @abs(if (linenum == 0) line else linenum);
const fmt = std.fmt.bufPrintZ(&buf, "{d} ", .{val}) catch return;
_ = self.plane.print_aligned_right(@intCast(pos), "{s}", .{if (fmt.len > 6) "==> " else fmt}) catch {};
try self.plane.cursor_move_yx(@intCast(pos), 0);
if (val > 999999)
_ = self.plane.print_aligned_right(@intCast(pos), "==> ", .{}) catch {}
else
self.print_digits(val, self.render_style) catch {};
if (self.highlight and linenum == 0)
self.render_line_highlight(pos, theme);
self.render_diff_symbols(&diff_symbols, pos, abs_linenum, theme);
@ -297,6 +305,11 @@ fn secondary_click(_: *Self) error{Exit}!bool {
return true;
}
fn middle_click(_: *Self) error{Exit}!bool {
try command.executeName("gutter_style_next", .{});
return true;
}
fn mouse_click_button4(_: *Self) error{Exit}!bool {
try command.executeName("scroll_up_pageup", .{});
return true;
@ -400,3 +413,45 @@ pub fn filter_receive(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.E
}
return false;
}
fn int_width(n_: usize) usize {
var n = n_;
var size: usize = 1;
while (true) {
n /= 10;
if (n == 0) return size;
size += 1;
}
}
fn print_digits(self: *Self, n_: anytype, style_: LineNumberStyle) !void {
var n = n_;
var buf: [12][]const u8 = undefined;
var digits: std.ArrayListUnmanaged([]const u8) = .initBuffer(&buf);
while (true) {
digits.addOneAssumeCapacity().* = get_digit(n % 10, style_);
n /= 10;
if (n == 0) break;
}
std.mem.reverse([]const u8, digits.items);
try self.plane.cursor_move_yx(@intCast(self.plane.cursor_y()), @intCast(self.width - digits.items.len - 1));
for (digits.items) |digit| _ = try self.plane.putstr(digit);
}
pub fn print_digit(plane: *Plane, n: anytype, style_: LineNumberStyle) !void {
_ = try plane.putstr(get_digit(n, style_));
}
fn get_digit(n: anytype, style_: LineNumberStyle) []const u8 {
return switch (style_) {
.ascii => digits_ascii[n],
.digital => digits_digtl[n],
.subscript => digits_subsc[n],
.superscript => digits_super[n],
};
}
const digits_ascii: [10][]const u8 = .{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
const digits_digtl: [10][]const u8 = .{ "🯰", "🯱", "🯲", "🯳", "🯴", "🯵", "🯶", "🯷", "🯸", "🯹" };
const digits_subsc: [10][]const u8 = .{ "", "", "", "", "", "", "", "", "", "" };
const digits_super: [10][]const u8 = .{ "", "¹", "²", "³", "", "", "", "", "", "" };

View file

@ -579,6 +579,22 @@ const cmds = struct {
}
pub const gutter_mode_next_meta: Meta = .{ .description = "Next gutter mode" };
pub fn gutter_style_next(self: *Self, _: Ctx) Result {
const config = tui.config_mut();
config.gutter_line_numbers_style = switch (config.gutter_line_numbers_style) {
.ascii => .digital,
.digital => .subscript,
.subscript => .superscript,
.superscript => .ascii,
};
try tui.save_config();
if (self.widgets.get("editor_gutter")) |gutter_widget| {
const gutter = gutter_widget.dynamic_cast(@import("editor_gutter.zig")) orelse return;
gutter.render_style = config.gutter_line_numbers_style;
}
}
pub const gutter_style_next_meta: Meta = .{ .description = "Next line number style" };
pub fn goto_next_file_or_diagnostic(self: *Self, ctx: Ctx) Result {
if (self.is_panel_view_showing(filelist_view)) {
switch (self.file_list_type) {