diff options
Diffstat (limited to 'main.zig')
| -rw-r--r-- | main.zig | 83 |
1 files changed, 78 insertions, 5 deletions
@@ -115,8 +115,13 @@ pub fn main(init: std.process.Init) !void { var term_stream = term.vtStream(); defer term_stream.deinit(); - var tty_buf: [0x10000]u8 = undefined; + var selection_start_col: ?i32 = null; + var selection_end_col: ?i32 = null; + var selection_start_row: ?i32 = null; + var selection_end_row: ?i32 = null; + var selection_state: enum { done, dragging, none } = .none; + var tty_buf: [0x10000]u8 = undefined; var tty = try vaxis.Tty.init(io, &tty_buf); var vx = try vaxis.init(io, gpa, init.environ_map, .{}); @@ -174,11 +179,36 @@ pub fn main(init: std.process.Init) !void { term.screens.active.scroll(.{ .delta_row = -(mouse.row) }); } - if (mouse.button == .left and mouse.col > term_x_padding) {} - if (mouse.button == .right and mouse.col <= term_x_padding) { term.screens.active.scroll(.{ .delta_row = mouse.row }); } + + // selection + if (mouse.button == .left and mouse.col > term_x_padding) { + selection_start_col = mouse.col; + selection_start_row = mouse.row + @as( + i32, + @intCast(term.screens.active.pages.scrollbar().offset), + ); + selection_state = .dragging; + } + } + + if (mouse.type == .drag and selection_state == .dragging and mouse.col > term_x_padding) { + selection_end_col = mouse.col; + selection_end_row = mouse.row + @as( + i32, + @intCast(term.screens.active.pages.scrollbar().offset), + ); + } + + if (mouse.type == .release and mouse.col > term_x_padding) { + selection_end_col = mouse.col; + selection_end_row = mouse.row + @as( + i32, + @intCast(term.screens.active.pages.scrollbar().offset), + ); + selection_state = .done; } }, .key_press => |key| { @@ -288,13 +318,52 @@ pub fn main(init: std.process.Init) !void { }); win_child.clear(); - _ = win_child.printSegment(.{ .text = tty_str }, .{}); + + // _ = win_child.printSegment(.{ .text = tty_str }, .{}); + // Selection rectangle in win_child-local space: rows carry the scroll + // offset; cols are window-relative, so shift left by term_x_padding to + // land inside win_child (x_off = term_x_padding). + const off: i32 = @intCast(term.screens.active.pages.scrollbar().offset); + const sel: ?struct { r0: i32, r1: i32, c0: i32, c1: i32 } = blk: { + if (selection_state == .none) break :blk null; + const sr = selection_start_row orelse break :blk null; + const er = selection_end_row orelse break :blk null; + const sc = selection_start_col orelse break :blk null; + const ec = selection_end_col orelse break :blk null; + break :blk .{ + .r0 = @min(sr, er), + .r1 = @max(sr, er), + .c0 = @min(sc, ec) - term_x_padding, + .c1 = @max(sc, ec) - term_x_padding, + }; + }; + + var lines_it = std.mem.splitAny(u8, tty_str, "\n"); + { + var i: u16 = 0; + while (lines_it.next()) |line| : (i += 1) { + const j = @as(i32, i) + off; + if (sel) |s| if (j >= s.r0 and j <= s.r1) { + // ponytail: byte index == column (ASCII); wide chars misalign. + const b0 = @min(@as(usize, @intCast(@max(0, s.c0))), line.len); + const b1 = @min(@as(usize, @intCast(@max(0, s.c1 + 1))), line.len); + _ = win_child.print(&.{ + .{ .text = line[0..b0] }, + .{ .text = line[b0..b1], .style = .{ .bg = .{ .index = 4 }, .fg = .{ .index = 3 } } }, + .{ .text = line[b1..] }, + }, .{ .row_offset = i }); + continue; + }; + _ = win_child.printSegment(.{ .text = line }, .{ .row_offset = i }); + } + } + win_child.showCursor(term.screens.active.cursor.x, term.screens.active.cursor.y); const pty_ws = pty_get_size(pty_master); const dbg_str = try std.fmt.bufPrintSentinel( &dbg_print_buf, - "c {} {}\npty pid {}\n grid {}x{} pty {}x{}\n resizes={}\n scroll {}/{} vis: {}\n", + "c {} {}\npty pid {}\n grid {}x{} pty {}x{}\n resizes={}\n scroll {}/{} vis: {}\n{} -> {}, {} -> {}", .{ pty_master.handle, term.screens.active.cursor.x, @@ -307,6 +376,10 @@ pub fn main(init: std.process.Init) !void { term.screens.active.pages.scrollbar().offset, term.screens.active.pages.scrollbar().total, term.screens.active.pages.scrollbar().len, + selection_start_col orelse 0, + selection_end_col orelse 0, + selection_start_row orelse 0, + selection_end_row orelse 0, }, 0, ); |
