From 02c35fa571f31549295aff183e6a28c3c7c0ab79 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 16 Jun 2026 10:12:09 -0300 Subject: mouse navigation prototype functional --- main.zig | 53 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/main.zig b/main.zig index 0c7b780e..855c330c 100644 --- a/main.zig +++ b/main.zig @@ -35,6 +35,17 @@ fn ticker(io: std.Io, loop: *Loop) void { } } +fn extract_word(str: []u8, i: usize) []u8 { + std.debug.assert(i < str.len); + var l = i; + var r = i; + + while (l > 0 and (!std.ascii.isWhitespace(str[l - 1]))) : (l -= 1) {} + while (r < str.len and (!std.ascii.isWhitespace(str[r]))) : (r += 1) {} + + return str[l..r]; +} + pub fn main(init: std.process.Init) !void { std.debug.print("hello!\n", .{}); @@ -47,6 +58,7 @@ pub fn main(init: std.process.Init) !void { var tty_buf: [0x10000]u8 = undefined; var lines: [0x1000][MAX_LEN]u8 = undefined; const lstart = 5; + const colstart = 4; const dir = std.Io.Dir.cwd(); var cwd = try std.Io.Dir.openDir(dir, io, ".", .{ .iterate = true }); @@ -90,6 +102,9 @@ pub fn main(init: std.process.Init) !void { var tick_task = try io.concurrent(ticker, .{ io, &loop }); defer tick_task.cancel(io); + var idk: u64 = 0; + var last_scroll = io.vtable.now(@ptrCast(&idk), .real); + while (true) { const event = try loop.nextEvent(); const win = vx.window(); @@ -103,27 +118,39 @@ pub fn main(init: std.process.Init) !void { } }, .mouse => |m| { - if (m.type == .press and m.button == .wheel_down) { - scroll_off += 1; - win.clear(); - } - if (m.type == .press and m.button == .wheel_up) { - if (scroll_off > 0) { - scroll_off -= 1; + if (m.type == .press and (m.button == .wheel_down or m.button == .wheel_up)) { + const delta = last_scroll.untilNow(io, .real); + // basic debouncing + if (delta.toMilliseconds() < 30) continue; + + last_scroll = io.vtable.now(@ptrCast(&idk), .real); + + if (m.type == .press and m.button == .wheel_down) { + scroll_off += 1; win.clear(); } - continue; + + if (m.type == .press and m.button == .wheel_up) { + if (scroll_off > 0) { + scroll_off -= 1; + win.clear(); + } + continue; + } } - const line_idx = @as(usize, @intCast(m.row)) + scroll_off; - _ = try std.fmt.bufPrintSentinel(&lines[3], "{} {any}", .{ rendered_lines, m }, 0); + _ = try std.fmt.bufPrintSentinel(&lines[3], "{any}", .{m}, 0); if (m.type == .press and (m.button == .right or m.button == .left)) { // const txt = try std.fmt.allocPrint(gpa, "col={} row={} xo={} yo={}", .{ m.col, m.row, m.xoffset, m.yoffset }); + + const line_idx = @as(usize, @intCast(m.row)) + scroll_off; const len = std.mem.findSentinel(u8, 0, @ptrCast(&lines[line_idx])); + const selected_col = @as(usize, @intCast(m.col)) - colstart; const selected_line = lines[line_idx][0..len]; + const next = extract_word(selected_line, selected_col); - if (cwd.openDir(io, selected_line, .{ .iterate = true })) |d| { + if (cwd.openDir(io, next, .{ .iterate = true })) |d| { cwd = d; var walk = try cwd.walkSelectively(gpa); defer walk.deinit(); @@ -139,7 +166,7 @@ pub fn main(init: std.process.Init) !void { win.clear(); // if it's not a dir maybe it's a file } else |_| { - if (cwd.openFile(io, selected_line, .{ .mode = .read_only })) |f| { + if (cwd.openFile(io, next, .{ .mode = .read_only })) |f| { var buf: [0x100]u8 = undefined; const flen = try f.length(io); var reader = f.reader(io, &buf); @@ -169,7 +196,7 @@ pub fn main(init: std.process.Init) !void { _ = win.printSegment(.{ .text = lines[i + scroll_off][0..len] }, .{ .row_offset = @intCast(i), - .col_offset = 4, + .col_offset = colstart, .wrap = .none, }); -- cgit v1.3