From b215aec75bf768c9146a9934d9d24633b91bd74e Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sat, 1 Jun 2024 00:12:44 +0900 Subject: [PATCH] widgets: add LineNumbers widget The LineNumbers widget draws vertical list of numbers. This can be used as a line number bar for a text editor for example. --- src/widgets.zig | 1 + src/widgets/LineNumbers.zig | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/widgets/LineNumbers.zig diff --git a/src/widgets.zig b/src/widgets.zig index 8773fbf..5239b6e 100644 --- a/src/widgets.zig +++ b/src/widgets.zig @@ -7,3 +7,4 @@ pub const Table = @import("widgets/Table.zig"); pub const TextInput = @import("widgets/TextInput.zig"); pub const nvim = @import("widgets/nvim.zig"); pub const ScrollView = @import("widgets/ScrollView.zig"); +pub const LineNumbers = @import("widgets/LineNumbers.zig"); diff --git a/src/widgets/LineNumbers.zig b/src/widgets/LineNumbers.zig new file mode 100644 index 0000000..d076f12 --- /dev/null +++ b/src/widgets/LineNumbers.zig @@ -0,0 +1,54 @@ +const std = @import("std"); +const vaxis = @import("../main.zig"); + +const digits = "0123456789"; + +num_lines: usize = std.math.maxInt(usize), +highlighted_line: usize = 0, +style: vaxis.Style = .{ .dim = true }, +highlighted_style: vaxis.Style = .{ .dim = true, .bg = .{ .index = 0 } }, + +pub fn extractDigit(v: usize, n: usize) usize { + return (v / (std.math.powi(usize, 10, n) catch unreachable)) % 10; +} + +pub fn numDigits(v: usize) usize { + return switch (v) { + 0...9 => 1, + 10...99 => 2, + 100...999 => 3, + 1000...9999 => 4, + 10000...99999 => 5, + 100000...999999 => 6, + 1000000...9999999 => 7, + 10000000...99999999 => 8, + else => 0, + }; +} + +pub fn draw(self: @This(), win: vaxis.Window, y_scroll: usize) void { + for (1 + y_scroll..self.num_lines) |line| { + if (line - 1 >= y_scroll +| win.height) { + break; + } + const highlighted = line == self.highlighted_line; + const num_digits = numDigits(line); + for (0..num_digits) |i| { + const digit = extractDigit(line, i); + win.writeCell(win.width -| (i + 2), line -| (y_scroll +| 1), .{ + .char = .{ + .width = 1, + .grapheme = digits[digit .. digit + 1], + }, + .style = if (highlighted) self.highlighted_style else self.style, + }); + } + if (highlighted) { + for (num_digits + 1..win.width) |i| { + win.writeCell(i, line -| (y_scroll +| 1), .{ + .style = if (highlighted) self.highlighted_style else self.style, + }); + } + } + } +}