summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.zig149
1 files changed, 138 insertions, 11 deletions
diff --git a/main.zig b/main.zig
index d2d9a7af..5ac51a42 100644
--- a/main.zig
+++ b/main.zig
@@ -174,6 +174,61 @@ fn loadFile(
rendered_lines.* = splitLines(lines, text);
}
+fn ghostColor(color: ghostty_vt.Style.Color) vaxis.Color {
+ return switch (color) {
+ .none => .default,
+ .palette => |idx| .{ .index = idx },
+ .rgb => |rgb| .{ .rgb = .{ rgb.r, rgb.g, rgb.b } },
+ };
+}
+
+fn cellStyle(cell_info: ghostty_vt.PageList.Cell) vaxis.Style {
+ const style = cell_info.style();
+ var vstyle: vaxis.Style = .{};
+ vstyle.fg = ghostColor(style.fg_color);
+ vstyle.bg = ghostColor(style.bg_color);
+ vstyle.bold = style.flags.bold;
+ vstyle.dim = style.flags.faint;
+ vstyle.italic = style.flags.italic;
+ vstyle.blink = style.flags.blink;
+ vstyle.reverse = style.flags.inverse;
+ vstyle.invisible = style.flags.invisible;
+ vstyle.strikethrough = style.flags.strikethrough;
+ vstyle.ul_style = switch (style.flags.underline) {
+ .none => .off,
+ .single => .single,
+ .double => .double,
+ .curly => .curly,
+ .dotted => .dotted,
+ .dashed => .dashed,
+ };
+
+ switch (cell_info.cell.content_tag) {
+ .bg_color_palette => vstyle.bg = .{ .index = cell_info.cell.content.color_palette.data },
+ .bg_color_rgb => {
+ const rgb = cell_info.cell.content.color_rgb;
+ vstyle.bg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } };
+ },
+ else => {},
+ }
+
+ return vstyle;
+}
+
+fn appendCp(buf: *[MAX_LINE_LEN]u8, len: *usize, cp: u21) void {
+ if (cp == 0) {
+ if (len.* < buf.len) {
+ buf[len.*] = ' ';
+ len.* += 1;
+ }
+ return;
+ }
+
+ if (len.* + 4 > buf.len) return;
+ const n = std.unicode.utf8Encode(cp, buf[len.*..]) catch return;
+ len.* += n;
+}
+
const nrows = 64;
const ncols = 100;
@@ -192,6 +247,7 @@ pub fn main(init: std.process.Init) !void {
var tty_buf: [0x10000]u8 = undefined;
var display_lines: [2][MAX_LINES][MAX_LINE_LEN]u8 = undefined;
+ var tty_render_lines: [MAX_LINES][MAX_LINE_LEN]u8 = undefined;
var rendered_lines = [_]usize{ 0, 0 };
var line_nums: [MAX_LINES][8]u8 = undefined;
var file_scroll: usize = 0;
@@ -242,6 +298,10 @@ pub fn main(init: std.process.Init) !void {
defer _ = pty_reader.cancel(io) catch {};
defer pty_master.close(io);
+ var mouse_seen = false;
+ var mouse_row: i16 = 0;
+ var mouse_col: i16 = 0;
+
while (true) {
const event = try loop.nextEvent();
const win = vx.window();
@@ -249,6 +309,10 @@ pub fn main(init: std.process.Init) !void {
const right_x: i16 = @intCast(left_outer_width);
switch (event) {
.mouse => |mouse| {
+ mouse_seen = true;
+ mouse_row = mouse.row;
+ mouse_col = mouse.col;
+
const mouse_on_left = mouse.col < right_x;
if (mouse.button == .wheel_down) {
@@ -271,12 +335,14 @@ pub fn main(init: std.process.Init) !void {
var selected_word: ?[]const u8 = null;
if (mouse_on_left) {
- const line_idx = @as(usize, @intCast(@max(mouse.row, 0))) + file_scroll;
- if (line_idx < rendered_lines[FILE_PANE] and mouse.col >= 5) {
- const len = std.mem.findSentinel(u8, 0, @ptrCast(&display_lines[FILE_PANE][line_idx]));
- const selected_col: usize = @intCast(mouse.col - 5);
- const selected_line = display_lines[FILE_PANE][line_idx][0..len];
- selected_word = extractWord(selected_line, selected_col);
+ if (mouse.row > 0 and mouse.col >= 5) {
+ const line_idx = @as(usize, @intCast(mouse.row - 1)) + file_scroll;
+ if (line_idx < rendered_lines[FILE_PANE]) {
+ const len = std.mem.findSentinel(u8, 0, @ptrCast(&display_lines[FILE_PANE][line_idx]));
+ const selected_col: usize = @intCast(mouse.col - 5);
+ const selected_line = display_lines[FILE_PANE][line_idx][0..len];
+ selected_word = extractWord(selected_line, selected_col);
+ }
}
} else {
const line_idx: usize = @intCast(@max(mouse.row, 0));
@@ -421,14 +487,75 @@ pub fn main(init: std.process.Init) !void {
}
i = 0;
- while (i < win_term.height and i < rendered_lines[TTY_PANE]) : (i += 1) {
- const len = std.mem.findSentinel(u8, 0, @ptrCast(&display_lines[TTY_PANE][i]));
- _ = win_term.printSegment(.{ .text = display_lines[TTY_PANE][i][0..len] }, .{
- .row_offset = @intCast(i),
+ while (i < win_term.height and i < MAX_LINES) : (i += 1) {
+ var len: usize = 0;
+ var span_start: usize = 0;
+ var span_col: usize = 0;
+ var span_style: vaxis.Style = .{};
+ var span_open = false;
+
+ var col: usize = 0;
+ while (col < win_term.width and col < ncols and len < MAX_LINE_LEN - 4) : (col += 1) {
+ const cell_info = term.screens.active.pages.getCell(.{ .viewport = .{
+ .x = @intCast(col),
+ .y = @intCast(i),
+ } }) orelse continue;
+
+ if (cell_info.cell.wide == .spacer_tail) continue;
+
+ const style = cellStyle(cell_info);
+ if (!span_open) {
+ span_open = true;
+ span_start = len;
+ span_col = col;
+ span_style = style;
+ } else if (!vaxis.Style.eql(span_style, style)) {
+ _ = win_term.printSegment(.{
+ .text = tty_render_lines[i][span_start..len],
+ .style = span_style,
+ }, .{
+ .row_offset = @intCast(i),
+ .col_offset = @intCast(span_col),
+ .wrap = .none,
+ });
+ span_start = len;
+ span_col = col;
+ span_style = style;
+ }
+
+ switch (cell_info.cell.content_tag) {
+ .codepoint, .codepoint_grapheme => {
+ appendCp(&tty_render_lines[i], &len, cell_info.cell.codepoint());
+ if (cell_info.cell.hasGrapheme()) {
+ if (cell_info.node.data.lookupGrapheme(cell_info.cell)) |grapheme| {
+ for (grapheme) |cp| appendCp(&tty_render_lines[i], &len, cp);
+ }
+ }
+ },
+ .bg_color_palette, .bg_color_rgb => appendCp(&tty_render_lines[i], &len, ' '),
+ }
+ }
+
+ if (span_open and len > span_start) {
+ _ = win_term.printSegment(.{
+ .text = tty_render_lines[i][span_start..len],
+ .style = span_style,
+ }, .{
+ .row_offset = @intCast(i),
+ .col_offset = @intCast(span_col),
+ .wrap = .none,
+ });
+ }
+ }
+ win_term.showCursor(term.screens.active.cursor.x, term.screens.active.cursor.y);
+
+ if (mouse_seen and mouse_row >= 0 and mouse_col >= 0 and mouse_row < win.height and mouse_col < win.width) {
+ _ = win.printSegment(.{ .text = "@", .style = .{ .reverse = true, .bold = true } }, .{
+ .row_offset = @intCast(mouse_row),
+ .col_offset = @intCast(mouse_col),
.wrap = .none,
});
}
- win_term.showCursor(term.screens.active.cursor.x, term.screens.active.cursor.y);
try vx.render(tty.writer());
}