From 49d6ee94fcaaf6e77b6498b55ce30b9963d83d45 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 15 Apr 2024 19:50:11 +0200 Subject: [PATCH] refactor: simplify and clean-up navgate command This should also prevent get_mru_position and location_jump from stomping on each other. --- src/Project.zig | 30 ++++++++++-------- src/project_manager.zig | 6 ++-- src/tui/mainview.zig | 68 ++++++++++++++++++++++++++--------------- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/Project.zig b/src/Project.zig index 996f05e..1349dc6 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -221,9 +221,8 @@ pub fn get_mru_position(self: *Self, from: tp.pid_ref, file_path: []const u8) !v } } -pub fn did_open(self: *Self, from: tp.pid_ref, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) tp.result { +pub fn did_open(self: *Self, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) tp.result { self.update_mru(file_path, 0, 0) catch {}; - self.get_mru_position(from, file_path) catch {}; const lsp = self.get_lsp(language_server) catch |e| return tp.exit_error(e); if (!self.file_language_server.contains(file_path)) { const key = self.a.dupe(u8, file_path) catch |e| return tp.exit_error(e); @@ -411,20 +410,25 @@ fn navigate_to_location_link(self: *Self, from: tp.pid_ref, location_link: []con if (!std.mem.eql(u8, targetUri.?[0..7], "file://")) return error.InvalidTargetURI; const file_path = try std.Uri.unescapeString(self.a, targetUri.?[7..]); defer self.a.free(file_path); - try from.send(.{ "cmd", "navigate", .{ .file = file_path } }); if (targetSelectionRange) |sel| { - try from.send(.{ "cmd", "goto", .{ - targetRange.?.start.line + 1, - targetRange.?.start.character + 1, - sel.start.line, - sel.start.character, - sel.end.line, - sel.end.character, + try from.send(.{ "cmd", "navigate", .{ + .file = file_path, + .goto = .{ + targetRange.?.start.line + 1, + targetRange.?.start.character + 1, + sel.start.line, + sel.start.character, + sel.end.line, + sel.end.character, + }, } }); } else { - try from.send(.{ "cmd", "goto", .{ - targetRange.?.start.line + 1, - targetRange.?.start.character + 1, + try from.send(.{ "cmd", "navigate", .{ + .file = file_path, + .goto = .{ + targetRange.?.start.line + 1, + targetRange.?.start.character + 1, + }, } }); } } diff --git a/src/project_manager.zig b/src/project_manager.zig index 3fbef18..fb91df8 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -196,7 +196,7 @@ const Process = struct { self.query_recent_files(from, project_directory, max, query) catch |e| return from.forward_error(e); } else if (try m.match(.{ "did_open", tp.extract(&project_directory), tp.extract(&path), tp.extract(&file_type), tp.extract_cbor(&language_server), tp.extract(&version), tp.extract(&text_ptr), tp.extract(&text_len) })) { const text = if (text_len > 0) @as([*]const u8, @ptrFromInt(text_ptr))[0..text_len] else ""; - self.did_open(from, project_directory, path, file_type, language_server, version, text) catch |e| return from.forward_error(e); + self.did_open(project_directory, path, file_type, language_server, version, text) catch |e| return from.forward_error(e); } else if (try m.match(.{ "did_change", tp.extract(&project_directory), tp.extract(&path), tp.extract(&version), tp.extract(&root_dst), tp.extract(&root_src) })) { self.did_change(project_directory, path, version, root_dst, root_src) catch |e| return from.forward_error(e); } else if (try m.match(.{ "did_save", tp.extract(&project_directory), tp.extract(&path) })) { @@ -244,11 +244,11 @@ const Process = struct { self.logger.print("query \"{s}\" matched {d}/{d} in {d} ms", .{ query, matched, project.files.items.len, query_time }); } - fn did_open(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) tp.result { + fn did_open(self: *Process, project_directory: []const u8, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) tp.result { const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_open" }); defer frame.deinit(); const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project"); - return project.did_open(from, file_path, file_type, language_server, version, text); + return project.did_open(file_path, file_type, language_server, version, text); } fn did_change(self: *Process, project_directory: []const u8, file_path: []const u8, version: usize, root_dst: usize, root_src: usize) tp.result { diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 26743ae..35da739 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -1,6 +1,7 @@ const std = @import("std"); const nc = @import("notcurses"); const tp = @import("thespian"); +const cbor = @import("cbor"); const tracy = @import("tracy"); const root = @import("root"); const location_history = @import("location_history"); @@ -174,22 +175,32 @@ const cmds = struct { var file_name: []const u8 = undefined; var line: ?i64 = null; var column: ?i64 = null; - var obj = std.json.ObjectMap.init(self.a); - defer obj.deinit(); - if (ctx.args.match(tp.extract(&obj)) catch false) { - if (obj.get("line")) |v| switch (v) { - .integer => |line_| line = line_, - else => return tp.exit_error(error.InvalidArgument), - }; - if (obj.get("column")) |v| switch (v) { - .integer => |column_| column = column_, - else => return tp.exit_error(error.InvalidArgument), - }; - if (obj.get("file")) |v| switch (v) { - .string => |file_| file = file_, - else => return tp.exit_error(error.InvalidArgument), - }; - } else if (ctx.args.match(tp.extract(&file_name)) catch false) { + var goto_args: []const u8 = &.{}; + + var iter = ctx.args.buf; + if (cbor.decodeMapHeader(&iter)) |len_| { + var len = len_; + while (len > 0) : (len -= 1) { + var field_name: []const u8 = undefined; + if (!(cbor.matchString(&iter, &field_name) catch |e| return tp.exit_error(e))) + return tp.exit_error(error.InvalidArgument); + if (std.mem.eql(u8, field_name, "line")) { + if (!(cbor.matchValue(&iter, cbor.extract(&line)) catch |e| return tp.exit_error(e))) + return tp.exit_error(error.InvalidArgument); + } else if (std.mem.eql(u8, field_name, "column")) { + if (!(cbor.matchValue(&iter, cbor.extract(&column)) catch |e| return tp.exit_error(e))) + return tp.exit_error(error.InvalidArgument); + } else if (std.mem.eql(u8, field_name, "file")) { + if (!(cbor.matchValue(&iter, cbor.extract(&file)) catch |e| return tp.exit_error(e))) + return tp.exit_error(error.InvalidArgument); + } else if (std.mem.eql(u8, field_name, "goto")) { + if (!(cbor.matchValue(&iter, cbor.extract_cbor(&goto_args)) catch |e| return tp.exit_error(e))) + return tp.exit_error(error.InvalidArgument); + } else { + cbor.skipValue(&iter) catch |e| return tp.exit_error(e); + } + } + } else |_| if (ctx.args.match(tp.extract(&file_name)) catch false) { file = file_name; } else return tp.exit_error(error.InvalidArgument); @@ -198,18 +209,23 @@ const cmds = struct { std.mem.eql(u8, fp, f) else false else false; + if (!same_file) { if (self.editor) |editor| editor.send_editor_jump_source() catch {}; try self.create_editor(); try command.executeName("open_file", command.fmt(.{f})); } - if (line) |l| { + if (goto_args.len != 0) { + try command.executeName("goto", .{ .args = .{ .buf = goto_args } }); + } else if (line) |l| { try command.executeName("goto_line", command.fmt(.{l})); if (!same_file) try command.executeName("scroll_view_center", .{}); - } - if (column) |col| { - try command.executeName("goto_column", command.fmt(.{col})); + if (column) |col| + try command.executeName("goto_column", command.fmt(.{col})); + } else { + if (!same_file) + try project_manager.get_mru_position(f); } tui.need_render(); } @@ -286,7 +302,6 @@ const cmds = struct { gutter.relative = lnr; } } - }; pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result { @@ -339,11 +354,16 @@ pub fn location_update(self: *Self, m: tp.message) tp.result { } fn location_jump(from: tp.pid_ref, file_path: []const u8, cursor: location_history.Cursor, selection: ?location_history.Selection) void { - from.send(.{ "cmd", "navigate", .{ .file = file_path } }) catch return; if (selection) |sel| - from.send(.{ "cmd", "goto", .{ cursor.row, cursor.col, sel.begin.row, sel.begin.col, sel.end.row, sel.end.col } }) catch return + from.send(.{ "cmd", "navigate", .{ + .file = file_path, + .goto = .{ cursor.row, cursor.col, sel.begin.row, sel.begin.col, sel.end.row, sel.end.col }, + } }) catch return else - from.send(.{ "cmd", "goto", .{ cursor.row, cursor.col } }) catch return; + from.send(.{ "cmd", "navigate", .{ + .file = file_path, + .goto = .{ cursor.row, cursor.col }, + } }) catch return; } fn clear_auto_find(self: *Self, editor: *ed.Editor) !void {