diff options
| -rw-r--r-- | main.zig | 175 |
1 files changed, 51 insertions, 124 deletions
@@ -31,41 +31,23 @@ extern "c" fn _exit(status: c_int) noreturn; // * ../03-plano // right click and enter on lines to open files at specified lines -pub const Command = struct { - prev: ?*Command = null, - pub var value: union(enum) { - close, - ping, - nop, - quit, - tick, - key_press: vaxis.Key, - pty_read: []u8, - winsize: vaxis.Winsize, - mouse: vaxis.Mouse, - } = .nop; +const Event = union(enum) { + quit, + key_press: vaxis.Key, + pty_read: []u8, + winsize: vaxis.Winsize, + mouse: vaxis.Mouse, }; -const Loop = vaxis.Loop(@TypeOf(Command.value)); +const Loop = vaxis.Loop(Event); const MAX_LINES: usize = 0x1000; const MAX_LINE_LEN: usize = 0x200; const MAX_HISTORY: usize = 0x100; const FILE_PANE: usize = 0; const TTY_PANE: usize = 1; -const TS_COMMENT: u8 = 1; -const TS_STRING: u8 = 2; -const TS_NUMBER: u8 = 3; -const TS_KEYWORD: u8 = 4; -const TS_TYPE: u8 = 5; -const TS_FUNCTION: u8 = 6; -const TS_BUILTIN: u8 = 7; - -fn ticker(io: std.Io, loop: *Loop) void { - while (true) { - io.sleep(.fromMilliseconds(2), .awake) catch return; - _ = loop.tryPostEvent(.tick) catch return; - } -} +const TS_STRING: u8 = 1; +const TS_NUMBER: u8 = 2; +const TS_KEYWORD: u8 = 3; fn fork_pty(argv: [:0]const u8, ws: std.posix.winsize) std.Io.File { var master: c_int = undefined; @@ -96,41 +78,18 @@ fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, loop: *Loop) !v try loop.postEvent(.quit); } -fn putLine(lines: *[MAX_LINES][MAX_LINE_LEN]u8, idx: usize, text: []const u8) void { - const len = @min(text.len, MAX_LINE_LEN - 1); - @memcpy(lines[idx][0..len], text[0..len]); - lines[idx][len] = 0; -} - -fn putString(buf: *[MAX_LINE_LEN]u8, text: []const u8) usize { - const len = @min(text.len, MAX_LINE_LEN - 1); - @memcpy(buf[0..len], text[0..len]); - buf[len] = 0; - return len; -} - fn pathFrom(base: []const u8, name: []const u8, buf: *[MAX_LINE_LEN]u8) []const u8 { - if (std.fs.path.isAbsolute(name)) { - const len = putString(buf, name); - return buf[0..len]; - } - - return std.fmt.bufPrint(buf, "{s}/{s}", .{ base, name }) catch blk: { - const len = putString(buf, name); - break :blk buf[0..len]; - }; + if (std.fs.path.isAbsolute(name)) return name; + return std.fmt.bufPrint(buf, "{s}/{s}", .{ base, name }) catch name; } -fn splitLines(lines: *[MAX_LINES][MAX_LINE_LEN]u8, text: []const u8) usize { +// lines point into the backing text (file_text / tty_text); no copy. +fn splitLines(lines: *[MAX_LINES][]const u8, text: []const u8) usize { var iter = std.mem.splitScalar(u8, text, '\n'); var i: usize = 0; while (iter.next()) |line| : (i += 1) { if (i >= MAX_LINES) break; - putLine(lines, i, line); - } - if (i == 0) { - putLine(lines, 0, ""); - i = 1; + lines[i] = line; } return i; } @@ -155,23 +114,22 @@ fn loadFile( io: std.Io, gpa: std.mem.Allocator, path: []const u8, - lines: *[MAX_LINES][MAX_LINE_LEN]u8, + lines: *[MAX_LINES][]const u8, rendered_lines: *usize, - current_path: *[MAX_LINE_LEN]u8, - current_path_len: *usize, + current_path_buf: *[MAX_LINE_LEN]u8, + current_path: *[]const u8, file_text: *[]u8, highlight_styles: *[MAX_LINES][MAX_LINE_LEN]u8, ) !void { for (highlight_styles) |*row| @memset(row, 0); - const path_len = @min(path.len, MAX_LINE_LEN - 1); - @memcpy(current_path[0..path_len], path[0..path_len]); - current_path[path_len] = 0; - current_path_len.* = path_len; + current_path.* = std.fmt.bufPrint(current_path_buf, "{s}", .{path}) catch path; + + if (file_text.*.len > 0) gpa.free(file_text.*); + file_text.* = &.{}; var file = std.Io.Dir.cwd().openFile(io, path, .{ .mode = .read_only }) catch |err| { - const msg = try std.fmt.bufPrint(&lines[0], "could not open {s}: {}", .{ path, err }); - lines[0][msg.len] = 0; - rendered_lines.* = 1; + file_text.* = try std.fmt.allocPrint(gpa, "could not open {s}: {}", .{ path, err }); + rendered_lines.* = splitLines(lines, file_text.*); return; }; defer file.close(io); @@ -179,15 +137,11 @@ fn loadFile( var read_buf: [0x1000]u8 = undefined; const flen = try file.length(io); var reader = file.reader(io, &read_buf); - const text = reader.interface.readAlloc(gpa, @min(flen, 0x100000)) catch |err| { - const msg = try std.fmt.bufPrint(&lines[0], "could not read {s}: {}", .{ path, err }); - lines[0][msg.len] = 0; - rendered_lines.* = 1; + file_text.* = reader.interface.readAlloc(gpa, @min(flen, 0x100000)) catch |err| { + file_text.* = try std.fmt.allocPrint(gpa, "could not read {s}: {}", .{ path, err }); + rendered_lines.* = splitLines(lines, file_text.*); return; }; - - if (file_text.*.len > 0) gpa.free(file_text.*); - file_text.* = text; rendered_lines.* = splitLines(lines, file_text.*); var language: ?*const ts.Language = null; @@ -225,13 +179,9 @@ fn loadFile( for (match.captures) |capture| { const capture_name = query.captureNameForId(capture.index) orelse ""; var style: u8 = 0; - if (std.mem.indexOf(u8, capture_name, "comment") != null) style = TS_COMMENT; if (std.mem.indexOf(u8, capture_name, "string") != null or std.mem.indexOf(u8, capture_name, "character") != null) style = TS_STRING; if (std.mem.indexOf(u8, capture_name, "number") != null or std.mem.indexOf(u8, capture_name, "float") != null or std.mem.indexOf(u8, capture_name, "boolean") != null) style = TS_NUMBER; if (std.mem.indexOf(u8, capture_name, "keyword") != null or std.mem.indexOf(u8, capture_name, "include") != null or std.mem.indexOf(u8, capture_name, "operator") != null) style = TS_KEYWORD; - if (std.mem.indexOf(u8, capture_name, "type") != null or std.mem.indexOf(u8, capture_name, "constructor") != null) style = TS_TYPE; - if (std.mem.indexOf(u8, capture_name, "function") != null or std.mem.indexOf(u8, capture_name, "method") != null or std.mem.indexOf(u8, capture_name, "macro") != null) style = TS_FUNCTION; - if (std.mem.indexOf(u8, capture_name, "builtin") != null) style = TS_BUILTIN; if (style == 0) continue; const start = capture.node.startPoint(); @@ -322,20 +272,22 @@ pub fn main(init: std.process.Init) !void { defer term_stream.deinit(); var tty_buf: [0x10000]u8 = undefined; - var display_lines: [2][MAX_LINES][MAX_LINE_LEN]u8 = undefined; + var display_lines: [2][MAX_LINES][]const u8 = undefined; var tty_render_lines: [MAX_LINES][MAX_LINE_LEN]u8 = undefined; var highlight_styles: [MAX_LINES][MAX_LINE_LEN]u8 = undefined; var file_text: []u8 = &.{}; defer if (file_text.len > 0) gpa.free(file_text); + var tty_text: []const u8 = &.{}; + defer if (tty_text.len > 0) gpa.free(tty_text); var rendered_lines = [_]usize{ 0, 0 }; var line_nums: [MAX_LINES][8]u8 = undefined; var file_scroll: usize = 0; - var current_path: [MAX_LINE_LEN]u8 = undefined; - var current_path_len: usize = 0; - var term_cwd: [MAX_LINE_LEN]u8 = undefined; - var term_cwd_len = putString(&term_cwd, init.environ_map.get("PWD") orelse "."); - var cwd_history: [MAX_HISTORY][MAX_LINE_LEN]u8 = undefined; - var cwd_history_lens: [MAX_HISTORY]usize = undefined; + var current_path_buf: [MAX_LINE_LEN]u8 = undefined; + var current_path: []const u8 = ""; + var term_cwd_buf: [MAX_LINE_LEN]u8 = undefined; + var term_cwd: []const u8 = init.environ_map.get("PWD") orelse "."; + var cwd_history_buf: [MAX_HISTORY][MAX_LINE_LEN]u8 = undefined; + var cwd_history: [MAX_HISTORY][]const u8 = undefined; var cwd_history_len: usize = 0; try loadFile( io, @@ -343,8 +295,8 @@ pub fn main(init: std.process.Init) !void { if (args.len > 1) args[1] else "main.zig", &display_lines[FILE_PANE], &rendered_lines[FILE_PANE], + ¤t_path_buf, ¤t_path, - ¤t_path_len, &file_text, &highlight_styles, ); @@ -419,44 +371,36 @@ pub fn main(init: std.process.Init) !void { 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); + selected_word = extractWord(display_lines[FILE_PANE][line_idx], selected_col); } } } else { const line_idx: usize = @intCast(@max(mouse.row, 0)); if (line_idx < rendered_lines[TTY_PANE]) { - const len = std.mem.findSentinel(u8, 0, @ptrCast(&display_lines[TTY_PANE][line_idx])); const selected_col: usize = @intCast(@max(mouse.col - right_x, 0)); - const selected_line = display_lines[TTY_PANE][line_idx][0..len]; - selected_word = extractWord(selected_line, selected_col); + selected_word = extractWord(display_lines[TTY_PANE][line_idx], selected_col); } } if (selected_word) |word| { if (word.len > 0) { - var found_path_buf: [MAX_LINE_LEN]u8 = undefined; var candidate_buf: [MAX_LINE_LEN]u8 = undefined; var found_path: []const u8 = ""; var found_kind: ?std.Io.File.Kind = null; - const current_candidate = pathFrom(term_cwd[0..term_cwd_len], word, &candidate_buf); + const current_candidate = pathFrom(term_cwd, word, &candidate_buf); if (std.Io.Dir.cwd().statFile(io, current_candidate, .{})) |stat| { - const found_len = putString(&found_path_buf, current_candidate); - found_path = found_path_buf[0..found_len]; + found_path = current_candidate; found_kind = stat.kind; } else |_| {} var h = cwd_history_len; while (found_kind == null and h > 0) { h -= 1; - const old_cwd = cwd_history[h][0..cwd_history_lens[h]]; - const candidate = pathFrom(old_cwd, word, &candidate_buf); + const candidate = pathFrom(cwd_history[h], word, &candidate_buf); if (std.Io.Dir.cwd().statFile(io, candidate, .{})) |stat| { - const found_len = putString(&found_path_buf, candidate); - found_path = found_path_buf[0..found_len]; + found_path = candidate; found_kind = stat.kind; } else |_| {} } @@ -464,10 +408,10 @@ pub fn main(init: std.process.Init) !void { if (found_kind) |kind| { if (kind == .directory) { if (cwd_history_len < MAX_HISTORY) { - cwd_history_lens[cwd_history_len] = putString(&cwd_history[cwd_history_len], term_cwd[0..term_cwd_len]); + cwd_history[cwd_history_len] = std.fmt.bufPrint(&cwd_history_buf[cwd_history_len], "{s}", .{term_cwd}) catch term_cwd; cwd_history_len += 1; } - term_cwd_len = putString(&term_cwd, found_path); + term_cwd = std.fmt.bufPrint(&term_cwd_buf, "{s}", .{found_path}) catch term_cwd; try writer.interface.writeAll("cd "); try writer.interface.writeAll(found_path); @@ -475,7 +419,7 @@ pub fn main(init: std.process.Init) !void { try writer.flush(); if (!mouse_on_left) term.scrollViewport(.bottom); } else { - loadFile(io, gpa, found_path, &display_lines[FILE_PANE], &rendered_lines[FILE_PANE], ¤t_path, ¤t_path_len, &file_text, &highlight_styles) catch {}; + loadFile(io, gpa, found_path, &display_lines[FILE_PANE], &rendered_lines[FILE_PANE], ¤t_path_buf, ¤t_path, &file_text, &highlight_styles) catch {}; file_scroll = 0; } } @@ -525,13 +469,12 @@ pub fn main(init: std.process.Init) !void { }, .winsize => |ws| try vx.resize(gpa, tty.writer(), ws), .quit => break, - else => {}, } // term.scrollViewport(.bottom); - const tty_str = try term.plainString(gpa); - defer gpa.free(tty_str); - rendered_lines[TTY_PANE] = splitLines(&display_lines[TTY_PANE], tty_str); + if (tty_text.len > 0) gpa.free(tty_text); + tty_text = try term.plainString(gpa); + rendered_lines[TTY_PANE] = splitLines(&display_lines[TTY_PANE], tty_text); const win_file = win.child(.{ .border = .{ .where = .right }, @@ -543,7 +486,7 @@ pub fn main(init: std.process.Init) !void { }); win.clear(); - _ = win_file.printSegment(.{ .text = current_path[0..current_path_len] }, .{ + _ = win_file.printSegment(.{ .text = current_path }, .{ .row_offset = 0, .col_offset = 5, .wrap = .none, @@ -553,7 +496,7 @@ pub fn main(init: std.process.Init) !void { var i: usize = 0; while (i < visible_lines and i + file_scroll < rendered_lines[FILE_PANE]) : (i += 1) { const line_idx = i + file_scroll; - const len = std.mem.findSentinel(u8, 0, @ptrCast(&display_lines[FILE_PANE][line_idx])); + const len = @min(display_lines[FILE_PANE][line_idx].len, MAX_LINE_LEN); const num = try std.fmt.bufPrint(&line_nums[i], "{d:0>4}", .{line_idx + 1}); _ = win_file.printSegment(.{ .text = num }, .{ .row_offset = @intCast(i + 1), @@ -569,10 +512,6 @@ pub fn main(init: std.process.Init) !void { var style: vaxis.Style = .{}; var rgb = term.colors.palette.current[0]; switch (style_id) { - TS_COMMENT => { - rgb = term.colors.palette.current[8]; - style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } }, .dim = true, .italic = true }; - }, TS_STRING => { rgb = term.colors.palette.current[2]; style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } } }; @@ -585,18 +524,6 @@ pub fn main(init: std.process.Init) !void { rgb = term.colors.palette.current[5]; style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } }, .bold = true }; }, - TS_TYPE => { - rgb = term.colors.palette.current[6]; - style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } } }; - }, - TS_FUNCTION => { - rgb = term.colors.palette.current[4]; - style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } }, .bold = true }; - }, - TS_BUILTIN => { - rgb = term.colors.palette.current[13]; - style = .{ .fg = .{ .rgb = .{ rgb.r, rgb.g, rgb.b } } }; - }, else => {}, } _ = win_file.printSegment(.{ |
