Color syntax spans with newed palette
This commit is contained in:
+85
-2
@@ -344,6 +344,8 @@ pub const Client = struct {
|
||||
const gutter_digits = @max(@as(usize, 2), decimalDigits(total_lines));
|
||||
const gutter_width = @min(self.viewport.width, gutter_digits + 2);
|
||||
const content_width = if (self.viewport.width > gutter_width) self.viewport.width - gutter_width else 0;
|
||||
const syntax_spans = syntax_mod.spansAlloc(allocator, "zig", snap.bytes) catch try allocator.alloc(syntax_mod.Span, 0);
|
||||
defer allocator.free(syntax_spans);
|
||||
const first_visible_line = firstVisibleLineForCursor(cursor_line, max_body_lines);
|
||||
var visible_line_index: usize = 0;
|
||||
var body_lines_used: usize = 0;
|
||||
@@ -370,6 +372,7 @@ pub const Client = struct {
|
||||
self.search_matches.items,
|
||||
self.search_query.len,
|
||||
if (self.search_matches.items.len == 0) null else self.search_matches.items[self.search_index],
|
||||
syntax_spans,
|
||||
);
|
||||
body_lines_used += 1;
|
||||
line_start_byte += line.len + 1;
|
||||
@@ -2578,6 +2581,11 @@ const ansi_cursor = "\x1b[38;2;25;22;33;48;2;230;230;230m";
|
||||
const ansi_selection = "\x1b[38;2;230;230;230;48;2;55;65;92m";
|
||||
const ansi_search = "\x1b[38;2;25;22;33;48;2;231;168;78m";
|
||||
const ansi_search_active = "\x1b[38;2;25;22;33;48;2;235;119;84m";
|
||||
const ansi_syntax_keyword = "\x1b[38;2;235;119;84;48;2;25;22;33m";
|
||||
const ansi_syntax_builtin = "\x1b[38;2;121;155;224;48;2;25;22;33m";
|
||||
const ansi_syntax_string = "\x1b[38;2;116;196;171;48;2;25;22;33m";
|
||||
const ansi_syntax_comment = "\x1b[38;2;103;93;122;48;2;25;22;33m";
|
||||
const ansi_syntax_number = "\x1b[38;2;231;168;78;48;2;25;22;33m";
|
||||
const ansi_status = "\x1b[38;2;25;22;33;48;2;235;119;84m";
|
||||
|
||||
fn appendEditorLine(
|
||||
@@ -2595,6 +2603,7 @@ fn appendEditorLine(
|
||||
search_matches: []const usize,
|
||||
search_len: usize,
|
||||
active_search: ?usize,
|
||||
syntax_spans: []const syntax_mod.Span,
|
||||
) !void {
|
||||
const line_start = out.items.len;
|
||||
try appendLineNumber(allocator, out, line_no, gutter_digits);
|
||||
@@ -2608,7 +2617,7 @@ fn appendEditorLine(
|
||||
0;
|
||||
if (is_cursor_line) try out.appendSlice(allocator, ansi_current_line);
|
||||
try out.appendSlice(allocator, ansi_text);
|
||||
try appendEditorCells(allocator, out, line, line_start_byte, content_width, is_cursor_line, cursor_col, cursor_byte, selection, horizontal_scroll, search_matches, search_len, active_search);
|
||||
try appendEditorCells(allocator, out, line, line_start_byte, content_width, is_cursor_line, cursor_col, cursor_byte, selection, horizontal_scroll, search_matches, search_len, active_search, syntax_spans);
|
||||
try padStyledLineToWidth(allocator, out, out.items[line_start..], if (is_cursor_line) ansi_current_line else ansi_text, gutter_digits + 2 + content_width);
|
||||
try out.appendSlice(allocator, ansi_reset);
|
||||
try out.append(allocator, '\n');
|
||||
@@ -2653,6 +2662,7 @@ fn appendEditorCells(
|
||||
search_matches: []const usize,
|
||||
search_len: usize,
|
||||
active_search: ?usize,
|
||||
syntax_spans: []const syntax_mod.Span,
|
||||
) !void {
|
||||
var i: usize = 0;
|
||||
var source_col: usize = 0;
|
||||
@@ -2676,6 +2686,7 @@ fn appendEditorCells(
|
||||
const is_cursor_cell = is_cursor_line and !drew_cursor and cursor_byte == absolute_start;
|
||||
const is_selected_cell = isSelectedByteRange(selection, absolute_start, absolute_end);
|
||||
const search_style = searchStyle(search_matches, search_len, active_search, absolute_start, absolute_end);
|
||||
const syntax_style = syntaxStyle(syntax_spans, absolute_start, absolute_end);
|
||||
if (is_cursor_cell) {
|
||||
try out.appendSlice(allocator, ansi_cursor);
|
||||
drew_cursor = true;
|
||||
@@ -2683,9 +2694,11 @@ fn appendEditorCells(
|
||||
try out.appendSlice(allocator, ansi_selection);
|
||||
} else if (search_style) |style| {
|
||||
try out.appendSlice(allocator, style);
|
||||
} else if (syntax_style) |style| {
|
||||
try out.appendSlice(allocator, style);
|
||||
}
|
||||
try out.appendSlice(allocator, bytes[i..end]);
|
||||
if (is_cursor_cell or is_selected_cell or search_style != null) {
|
||||
if (is_cursor_cell or is_selected_cell or search_style != null or syntax_style != null) {
|
||||
try out.appendSlice(allocator, ansi_reset);
|
||||
if (is_cursor_line) try out.appendSlice(allocator, ansi_current_line);
|
||||
try out.appendSlice(allocator, ansi_text);
|
||||
@@ -2723,6 +2736,23 @@ fn searchStyle(matches: []const usize, query_len: usize, active_match: ?usize, s
|
||||
return null;
|
||||
}
|
||||
|
||||
fn syntaxStyle(spans: []const syntax_mod.Span, start: usize, end: usize) ?[]const u8 {
|
||||
for (spans) |span| {
|
||||
if (start < span.end and end > span.start) return syntaxStyleForClass(span.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn syntaxStyleForClass(class: syntax_mod.Class) []const u8 {
|
||||
return switch (class) {
|
||||
.keyword => ansi_syntax_keyword,
|
||||
.builtin => ansi_syntax_builtin,
|
||||
.string => ansi_syntax_string,
|
||||
.comment => ansi_syntax_comment,
|
||||
.number => ansi_syntax_number,
|
||||
};
|
||||
}
|
||||
|
||||
fn padStyledLineToWidth(allocator: std.mem.Allocator, out: *std.ArrayList(u8), rendered_line: []const u8, style: []const u8, width: usize) !void {
|
||||
var cells = visibleCellWidth(rendered_line);
|
||||
if (cells >= width) return;
|
||||
@@ -5467,3 +5497,56 @@ test "regular: search matches distinguish active match from other matches" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_search_active) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_search) != null);
|
||||
}
|
||||
|
||||
test "regular: syntax classes use newed highlight colors" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer client.deinit();
|
||||
|
||||
try client.handleTraceLine("open fn main() void { return \"std\"; // hi }");
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_syntax_keyword) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_syntax_builtin) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_syntax_string) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_syntax_comment) != null);
|
||||
}
|
||||
|
||||
test "regular: search and selection override syntax colors" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 64, .height = 6 });
|
||||
defer client.deinit();
|
||||
|
||||
try client.handleTraceLine("open const alpha = 1; const beta = 2;");
|
||||
try client.handleInput("/");
|
||||
try client.handleInput("c");
|
||||
try client.handleInput("o");
|
||||
try client.handleInput("n");
|
||||
try client.handleInput("s");
|
||||
try client.handleInput("t");
|
||||
try client.handleInput("\n");
|
||||
{
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_search_active) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_search) != null);
|
||||
}
|
||||
|
||||
try client.handleInput("s");
|
||||
try client.handleInput("w");
|
||||
{
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_selection) != null);
|
||||
}
|
||||
}
|
||||
|
||||
test "regular: plain text without syntax spans stays normal themed text" {
|
||||
var client = try Client.init(std.testing.allocator, .{ .width = 48, .height = 5 });
|
||||
defer client.deinit();
|
||||
|
||||
try client.handleTraceLine("open alpha beta gamma");
|
||||
const frame = try client.render(std.testing.allocator);
|
||||
defer std.testing.allocator.free(frame);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_text) != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, frame, ansi_syntax_keyword) == null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user