this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

widgets: add CodeView widget

CodeView widget allows viewing code in a more visually pleasing manner.
It combines LineNumbers widget to provide line numbers on the side.
The CodeView widget allows you to optionally highlight a specific line
and show indentation guidelines.

It is not intended to be a fully fledged editor, but rather for showing
code snippets to a user.

While it is not a fully fledged editor, this widget's code can give you
a good starting point.

authored by

Jari Vetoniemi and committed by
Tim Culverhouse
ee113c42 84b4821d

+113
+1
src/widgets.zig
··· 9 9 pub const ScrollView = @import("widgets/ScrollView.zig"); 10 10 pub const LineNumbers = @import("widgets/LineNumbers.zig"); 11 11 pub const TextView = @import("widgets/TextView.zig"); 12 + pub const CodeView = @import("widgets/CodeView.zig");
+112
src/widgets/CodeView.zig
··· 1 + const std = @import("std"); 2 + const vaxis = @import("../main.zig"); 3 + const ScrollView = vaxis.widgets.ScrollView; 4 + const LineNumbers = vaxis.widgets.LineNumbers; 5 + 6 + pub const DrawOptions = struct { 7 + highlighted_line: usize = 0, 8 + draw_line_numbers: bool = true, 9 + indentation: usize = 0, 10 + }; 11 + 12 + pub const Buffer = vaxis.widgets.TextView.Buffer; 13 + 14 + scroll_view: ScrollView = .{ .vertical_scrollbar = null }, 15 + highlighted_style: vaxis.Style = .{ .bg = .{ .index = 0 } }, 16 + indentation_cell: vaxis.Cell = .{ 17 + .char = .{ 18 + .grapheme = "┆", 19 + .width = 1, 20 + }, 21 + .style = .{ .dim = true }, 22 + }, 23 + 24 + pub fn input(self: *@This(), key: vaxis.Key) void { 25 + self.scroll_view.input(key); 26 + } 27 + 28 + pub fn draw(self: *@This(), win: vaxis.Window, buffer: Buffer, opts: DrawOptions) void { 29 + const pad_left: usize = if (opts.draw_line_numbers) LineNumbers.numDigits(buffer.rows) +| 1 else 0; 30 + self.scroll_view.draw(win, .{ 31 + .cols = buffer.cols + pad_left, 32 + .rows = buffer.rows, 33 + }); 34 + if (opts.draw_line_numbers) { 35 + var nl: LineNumbers = .{ 36 + .highlighted_line = opts.highlighted_line, 37 + .num_lines = buffer.rows +| 1, 38 + }; 39 + nl.draw(win.child(.{ 40 + .x_off = 0, 41 + .y_off = 0, 42 + .width = .{ .limit = pad_left }, 43 + .height = .{ .limit = win.height }, 44 + }), self.scroll_view.scroll.y); 45 + } 46 + self.drawCode(win.child(.{ .x_off = pad_left }), buffer, opts); 47 + } 48 + 49 + fn drawCode(self: *@This(), win: vaxis.Window, buffer: Buffer, opts: DrawOptions) void { 50 + const Pos = struct { x: usize = 0, y: usize = 0 }; 51 + var pos: Pos = .{}; 52 + var byte_index: usize = 0; 53 + var is_indentation = true; 54 + const bounds = self.scroll_view.bounds(win); 55 + for (buffer.grapheme.items(.len), buffer.grapheme.items(.offset), 0..) |g_len, g_offset, index| { 56 + if (bounds.above(pos.y)) { 57 + break; 58 + } 59 + 60 + const cluster = buffer.content.items[g_offset..][0..g_len]; 61 + defer byte_index += cluster.len; 62 + 63 + if (std.mem.eql(u8, cluster, "\n")) { 64 + if (index == buffer.grapheme.len - 1) { 65 + break; 66 + } 67 + pos.y += 1; 68 + pos.x = 0; 69 + is_indentation = true; 70 + continue; 71 + } else if (bounds.below(pos.y)) { 72 + continue; 73 + } 74 + 75 + const highlighted_line = pos.y +| 1 == opts.highlighted_line; 76 + var style: vaxis.Style = if (highlighted_line) self.highlighted_style else .{}; 77 + 78 + if (buffer.style_map.get(byte_index)) |meta| { 79 + const tmp = style.bg; 80 + style = buffer.style_list.items[meta]; 81 + style.bg = tmp; 82 + } 83 + 84 + const width = win.gwidth(cluster); 85 + defer pos.x +|= width; 86 + 87 + if (!bounds.colInside(pos.x)) { 88 + continue; 89 + } 90 + 91 + if (opts.indentation > 0 and !std.mem.eql(u8, cluster, " ")) { 92 + is_indentation = false; 93 + } 94 + 95 + if (is_indentation and opts.indentation > 0 and pos.x % opts.indentation == 0) { 96 + var cell = self.indentation_cell; 97 + cell.style.bg = style.bg; 98 + self.scroll_view.writeCell(win, pos.x, pos.y, cell); 99 + } else { 100 + self.scroll_view.writeCell(win, pos.x, pos.y, .{ 101 + .char = .{ .grapheme = cluster, .width = width }, 102 + .style = style, 103 + }); 104 + } 105 + 106 + if (highlighted_line) { 107 + for (pos.x +| width..bounds.x2) |x| { 108 + self.scroll_view.writeCell(win, x, pos.y, .{ .style = style }); 109 + } 110 + } 111 + } 112 + }