diff --git a/src/config.zig b/src/config.zig index 7d9c377..9f0425c 100644 --- a/src/config.zig +++ b/src/config.zig @@ -11,6 +11,7 @@ enable_terminal_color_scheme: bool = builtin.os.tag != .windows, highlight_current_line: bool = true, highlight_current_line_gutter: bool = true, highlight_columns: []const u8 = "", +highlight_columns_alpha: u8 = 224, whitespace_mode: []const u8 = "none", inline_diagnostics: bool = true, animation_min_lag: usize = 0, //milliseconds diff --git a/src/renderer/vaxis/Cell.zig b/src/renderer/vaxis/Cell.zig index f32be7a..4ef154b 100644 --- a/src/renderer/vaxis/Cell.zig +++ b/src/renderer/vaxis/Cell.zig @@ -76,10 +76,18 @@ pub fn columns(self: *const Cell) usize { } pub fn dim(self: *Cell, alpha: u8) void { - self.cell.style.fg = apply_alpha_value(self.cell.style.fg, alpha); + self.dim_fg(alpha); + self.dim_bg(alpha); +} + +pub fn dim_bg(self: *Cell, alpha: u8) void { self.cell.style.bg = apply_alpha_value(self.cell.style.bg, alpha); } +pub fn dim_fg(self: *Cell, alpha: u8) void { + self.cell.style.fg = apply_alpha_value(self.cell.style.fg, alpha); +} + fn apply_alpha_value(c: vaxis.Cell.Color, a: u8) vaxis.Cell.Color { var rgb = if (c == .rgb) c.rgb else return c; rgb[0] = @intCast((@as(u32, @intCast(rgb[0])) * a) / 256); diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 1ced292..ceb6c1d 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -915,7 +915,6 @@ pub const Editor = struct { match_idx: usize = 0, theme: *const Widget.Theme, hl_row: ?usize, - hl_cols: []const usize, leading: bool = true, cell_map: CellMap, @@ -967,8 +966,6 @@ pub const Editor = struct { 9 => .tab, else => .character, }; - for (ctx.hl_cols) |hl_col| if (hl_col == ctx.buf_col) - self_.render_column_highlight_cell(ctx.theme, c); if (ctx.hl_row) |hl_row| if (hl_row == ctx.buf_row) self_.render_line_highlight_cell(ctx.theme, c); self_.render_matches(&ctx.match_idx, ctx.theme, c); @@ -993,8 +990,6 @@ pub const Editor = struct { if (ctx.x >= view.cols) break; var cell_ = n.cell_init(); const c_ = &cell_; - for (ctx.hl_cols) |hl_col| if (hl_col == ctx.buf_col) - self_.render_column_highlight_cell(ctx.theme, c); if (ctx.hl_row) |hl_row| if (hl_row == ctx.buf_row) self_.render_line_highlight_cell(ctx.theme, c_); self_.render_matches(&ctx.match_idx, ctx.theme, c_); @@ -1012,16 +1007,12 @@ pub const Editor = struct { if (leaf.eol) { if (ctx.buf_col >= view.col) { var c = ctx.self.render_eol(n); - for (ctx.hl_cols) |hl_col| if (hl_col == ctx.buf_col) - self_.render_column_highlight_cell(ctx.theme, &c); if (ctx.hl_row) |hl_row| if (hl_row == ctx.buf_row) self_.render_line_highlight_cell(ctx.theme, &c); self_.render_matches(&ctx.match_idx, ctx.theme, &c); self_.render_selections(ctx.theme, &c); _ = n.putc(&c) catch {}; var term_cell = render_terminator(n, ctx.theme); - for (ctx.hl_cols) |hl_col| if (hl_col == ctx.buf_col + 1) - self_.render_column_highlight_cell(ctx.theme, &term_cell); if (ctx.hl_row) |hl_row| if (hl_row == ctx.buf_row) self_.render_line_highlight_cell(ctx.theme, &term_cell); _ = n.putc(&term_cell) catch {}; @@ -1046,25 +1037,11 @@ pub const Editor = struct { break :blk null; break :blk self.get_primary().cursor.row; } else null; - const highlight_columns = tui.config().highlight_columns; - var highlight_columns_buf: [6]usize = undefined; - const hl_cols: []const usize = if (highlight_columns.len > 0) blk: { - var idx: usize = 0; - var it = std.mem.splitScalar(u8, highlight_columns, ' '); - while (it.next()) |arg| { - var col = std.fmt.parseInt(usize, arg, 10) catch 1; - if (col > 0) col -= 1; - highlight_columns_buf[idx] = col; - idx += 1; - } - break :blk highlight_columns_buf[0..idx]; - } else &.{}; var ctx_: ctx = .{ .self = self, .buf_row = self.view.row, .theme = theme, .hl_row = hl_row, - .hl_cols = hl_cols, .cell_map = CellMap.init(self.allocator, self.view.rows, self.view.cols) catch @panic("OOM"), }; defer ctx_.cell_map.deinit(self.allocator); @@ -1076,18 +1053,17 @@ pub const Editor = struct { self.plane.set_base_style(theme.editor); self.plane.erase(); - for (hl_cols) |hl_col| - self.render_column_highlight(hl_col, theme) catch {}; if (hl_row) |_| self.render_line_highlight(&self.get_primary().cursor, theme) catch {}; self.plane.home(); _ = root.walk_from_line_begin_const(self.view.row, ctx.walker, &ctx_, self.metrics) catch {}; } self.render_syntax(theme, cache, root) catch {}; - self.render_cursors(theme, ctx_.cell_map) catch {}; self.render_whitespace_map(theme, ctx_.cell_map) catch {}; if (tui.config().inline_diagnostics) self.render_diagnostics(theme, hl_row, ctx_.cell_map) catch {}; + self.render_column_highlights() catch {}; + self.render_cursors(theme, ctx_.cell_map) catch {}; } fn render_cursors(self: *Self, theme: *const Widget.Theme, cell_map: CellMap) !void { @@ -1156,13 +1132,20 @@ pub const Editor = struct { cell_map.set_yx(y, x, .{ .cursor = true, .cell_type = cell_type }); } - fn render_column_highlight(self: *Self, col: usize, theme: *const Widget.Theme) !void { - for (0..self.view.rows) |row| { - self.plane.cursor_move_yx(@intCast(row), @intCast(col)) catch return; - var cell = self.plane.cell_init(); - _ = self.plane.at_cursor_cell(&cell) catch return; - self.render_column_highlight_cell(theme, &cell); - _ = self.plane.putc(&cell) catch {}; + fn render_column_highlights(self: *Self) !void { + const frame = tracy.initZone(@src(), .{ .name = "column highlights" }); + defer frame.deinit(); + const hl_cols: []const u16 = tui.highlight_columns(); + const alpha: u8 = tui.config().highlight_columns_alpha; + for (hl_cols) |hl_col| { + for (0..self.view.rows) |row| for (0..self.view.cols) |col| + if (hl_col > 0 and hl_col <= col) { + self.plane.cursor_move_yx(@intCast(row), @intCast(col)) catch return; + var cell = self.plane.cell_init(); + _ = self.plane.at_cursor_cell(&cell) catch return; + cell.dim_bg(alpha); + _ = self.plane.putc(&cell) catch {}; + }; } } @@ -1271,10 +1254,6 @@ pub const Editor = struct { cell.set_style_bg(if (match.style) |style| style else theme.editor_match); } - inline fn render_column_highlight_cell(_: *const Self, theme: *const Widget.Theme, cell: *Cell) void { - cell.set_style_bg(theme.editor_line_highlight); - } - inline fn render_line_highlight_cell(_: *const Self, theme: *const Widget.Theme, cell: *Cell) void { cell.set_style_bg(theme.editor_line_highlight); } diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 4229f0c..26324f7 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -23,6 +23,7 @@ const Allocator = std.mem.Allocator; allocator: Allocator, rdr_: renderer, config_: @import("config"), +highlight_columns_: [3]u16, frame_time: usize, // in microseconds frame_clock: tp.metronome, frame_clock_running: bool = false, @@ -123,6 +124,7 @@ fn init(allocator: Allocator) InitError!*Self { self.* = .{ .allocator = allocator, .config_ = conf, + .highlight_columns_ = @splat(0), .rdr_ = try renderer.init(allocator, self, tp.env.get().is("no-alternate"), dispatch_initialized), .frame_time = frame_time, .frame_clock = frame_clock, @@ -142,6 +144,16 @@ fn init(allocator: Allocator) InitError!*Self { instance_ = self; defer instance_ = null; + if (conf.highlight_columns.len > 0) { + var it = std.mem.splitScalar(u8, conf.highlight_columns, ' '); + var idx: usize = 0; + while (it.next()) |arg| { + if (idx >= self.highlight_columns_.len) break; + self.highlight_columns_[idx] = std.fmt.parseInt(u16, arg, 10) catch 0; + idx += 1; + } + } + self.default_cursor = std.meta.stringToEnum(keybind.CursorShape, conf.default_cursor) orelse .default; self.config_.default_cursor = @tagName(self.default_cursor); self.rdr_.handler_ctx = self; @@ -1091,6 +1103,10 @@ pub fn config() *const @import("config") { return ¤t().config_; } +pub fn highlight_columns() []const u16 { + return ¤t().highlight_columns_; +} + pub fn config_mut() *@import("config") { return ¤t().config_; }