refactor: rework error handling to simplifiy command implementation and provide better back traces
This commit is contained in:
parent
21b604f4d6
commit
032982c1e8
26 changed files with 821 additions and 785 deletions
|
@ -16,8 +16,8 @@
|
|||
.hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362",
|
||||
},
|
||||
.thespian = .{
|
||||
.url = "https://github.com/neurocyte/thespian/archive/3ace3163087a0260b30e2c420de76235dd82451f.tar.gz",
|
||||
.hash = "1220ffbfff37c24b68424a3c9223cf57daed5debdbb6b7751a36b9dca318825cff4c",
|
||||
.url = "https://github.com/neurocyte/thespian/archive/f1a89bdf9d9fac2cd7d6c1479e5bc99c8dd4c904.tar.gz",
|
||||
.hash = "1220f1f69aaad041ca96e5a06fb14ff510c3775d809a37a83b8651e7f0f71be8deaf",
|
||||
},
|
||||
.themes = .{
|
||||
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-15e8cad1619429bf2547a6819b5b999510d5c1e5/flow-themes.tar.gz",
|
||||
|
|
39
src/LSP.zig
39
src/LSP.zig
|
@ -11,9 +11,8 @@ const Self = @This();
|
|||
const module_name = @typeName(Self);
|
||||
const sp_tag = "child";
|
||||
const debug_lsp = true;
|
||||
pub const Error = error{ OutOfMemory, Exit };
|
||||
|
||||
pub fn open(a: std.mem.Allocator, project: []const u8, cmd: tp.message) Error!Self {
|
||||
pub fn open(a: std.mem.Allocator, project: []const u8, cmd: tp.message) !Self {
|
||||
return .{ .a = a, .pid = try Process.create(a, project, cmd) };
|
||||
}
|
||||
|
||||
|
@ -27,23 +26,23 @@ pub fn term(self: *Self) void {
|
|||
self.pid.deinit();
|
||||
}
|
||||
|
||||
pub fn send_request(self: Self, a: std.mem.Allocator, method: []const u8, m: anytype) error{Exit}!tp.message {
|
||||
pub fn send_request(self: Self, a: std.mem.Allocator, method: []const u8, m: anytype) !tp.message {
|
||||
// const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".send_request" });
|
||||
// defer frame.deinit();
|
||||
var cb = std.ArrayList(u8).init(self.a);
|
||||
defer cb.deinit();
|
||||
cbor.writeValue(cb.writer(), m) catch |e| return tp.exit_error(e);
|
||||
return self.pid.call(a, std.time.ns_per_s / 2, .{ "REQ", method, cb.items }) catch |e| return tp.exit_error(e);
|
||||
try cbor.writeValue(cb.writer(), m);
|
||||
return self.pid.call(a, std.time.ns_per_s / 2, .{ "REQ", method, cb.items });
|
||||
}
|
||||
|
||||
pub fn send_notification(self: Self, method: []const u8, m: anytype) tp.result {
|
||||
pub fn send_notification(self: Self, method: []const u8, m: anytype) !void {
|
||||
var cb = std.ArrayList(u8).init(self.a);
|
||||
defer cb.deinit();
|
||||
cbor.writeValue(cb.writer(), m) catch |e| return tp.exit_error(e);
|
||||
try cbor.writeValue(cb.writer(), m);
|
||||
return self.send_notification_raw(method, cb.items);
|
||||
}
|
||||
|
||||
pub fn send_notification_raw(self: Self, method: []const u8, cb: []const u8) tp.result {
|
||||
pub fn send_notification_raw(self: Self, method: []const u8, cb: []const u8) !void {
|
||||
return self.pid.send(.{ "NTFY", method, cb });
|
||||
}
|
||||
|
||||
|
@ -67,7 +66,7 @@ const Process = struct {
|
|||
|
||||
const Receiver = tp.Receiver(*Process);
|
||||
|
||||
pub fn create(a: std.mem.Allocator, project: []const u8, cmd: tp.message) Error!tp.pid {
|
||||
pub fn create(a: std.mem.Allocator, project: []const u8, cmd: tp.message) !tp.pid {
|
||||
var tag: []const u8 = undefined;
|
||||
if (try cmd.match(.{tp.extract(&tag)})) {
|
||||
//
|
||||
|
@ -92,7 +91,7 @@ const Process = struct {
|
|||
.requests = std.AutoHashMap(i32, tp.pid).init(a),
|
||||
.sp_tag = try sp_tag_.toOwnedSliceSentinel(0),
|
||||
};
|
||||
return tp.spawn_link(self.a, self, Process.start, self.tag) catch |e| tp.exit_error(e);
|
||||
return tp.spawn_link(self.a, self, Process.start, self.tag);
|
||||
}
|
||||
|
||||
fn deinit(self: *Process) void {
|
||||
|
@ -126,17 +125,21 @@ const Process = struct {
|
|||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ " start" });
|
||||
defer frame.deinit();
|
||||
_ = tp.set_trap(true);
|
||||
self.sp = tp.subprocess.init(self.a, self.cmd, self.sp_tag, .Pipe) catch |e| return tp.exit_error(e);
|
||||
self.sp = tp.subprocess.init(self.a, self.cmd, self.sp_tag, .Pipe) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
tp.receive(&self.receiver);
|
||||
|
||||
var log_file_path = std.ArrayList(u8).init(self.a);
|
||||
defer log_file_path.deinit();
|
||||
const state_dir = root.get_state_dir() catch |e| return tp.exit_error(e);
|
||||
log_file_path.writer().print("{s}/lsp-{s}.log", .{ state_dir, self.tag }) catch |e| return tp.exit_error(e);
|
||||
self.log_file = std.fs.createFileAbsolute(log_file_path.items, .{ .truncate = true }) catch |e| return tp.exit_error(e);
|
||||
const state_dir = root.get_state_dir() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
log_file_path.writer().print("{s}/lsp-{s}.log", .{ state_dir, self.tag }) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.log_file = std.fs.createFileAbsolute(log_file_path.items, .{ .truncate = true }) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn receive(self: *Process, from: tp.pid_ref, m: tp.message) tp.result {
|
||||
return self.receive_safe(from, m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name });
|
||||
defer frame.deinit();
|
||||
errdefer self.deinit();
|
||||
|
@ -146,9 +149,9 @@ const Process = struct {
|
|||
var code: u32 = 0;
|
||||
|
||||
if (try m.match(.{ "REQ", tp.extract(&method), tp.extract(&bytes) })) {
|
||||
self.send_request(from, method, bytes) catch |e| return tp.exit_error(e);
|
||||
try self.send_request(from, method, bytes);
|
||||
} else if (try m.match(.{ "NTFY", tp.extract(&method), tp.extract(&bytes) })) {
|
||||
self.send_notification(method, bytes) catch |e| return tp.exit_error(e);
|
||||
try self.send_notification(method, bytes);
|
||||
} else if (try m.match(.{"close"})) {
|
||||
self.write_log("### LSP close ###\n", .{});
|
||||
try self.close();
|
||||
|
@ -156,9 +159,9 @@ const Process = struct {
|
|||
self.write_log("### LSP terminated ###\n", .{});
|
||||
try self.term();
|
||||
} else if (try m.match(.{ self.sp_tag, "stdout", tp.extract(&bytes) })) {
|
||||
self.handle_output(bytes) catch |e| return tp.exit_error(e);
|
||||
try self.handle_output(bytes);
|
||||
} else if (try m.match(.{ self.sp_tag, "term", tp.extract(&err), tp.extract(&code) })) {
|
||||
self.handle_terminated(err, code) catch |e| return tp.exit_error(e);
|
||||
try self.handle_terminated(err, code);
|
||||
} else if (try m.match(.{ self.sp_tag, "stderr", tp.extract(&bytes) })) {
|
||||
self.write_log("{s}\n", .{bytes});
|
||||
} else if (try m.match(.{ "exit", "normal" })) {
|
||||
|
|
|
@ -132,7 +132,7 @@ pub fn request_recent_files(self: *Self, from: tp.pid_ref, max: usize) error{ Ou
|
|||
}
|
||||
}
|
||||
|
||||
fn simple_query_recent_files(self: *Self, from: tp.pid_ref, max: usize, query: []const u8) error{ OutOfMemory, Exit }!usize {
|
||||
fn simple_query_recent_files(self: *Self, from: tp.pid_ref, max: usize, query: []const u8) error{Exit}!usize {
|
||||
var i: usize = 0;
|
||||
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
||||
for (self.files.items) |file| {
|
||||
|
@ -155,12 +155,15 @@ pub fn query_recent_files(self: *Self, from: tp.pid_ref, max: usize, query: []co
|
|||
return self.simple_query_recent_files(from, max, query);
|
||||
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
||||
|
||||
var searcher = try fuzzig.Ascii.init(
|
||||
var searcher = fuzzig.Ascii.init(
|
||||
self.a,
|
||||
std.fs.max_path_bytes, // haystack max size
|
||||
std.fs.max_path_bytes, // needle max size
|
||||
.{ .case_sensitive = false },
|
||||
);
|
||||
) catch |e| switch (e) {
|
||||
error.OutOfMemory => @panic("OOM in fussiz.Ascii.init"),
|
||||
else => |e_| return e_,
|
||||
};
|
||||
defer searcher.deinit();
|
||||
|
||||
const Match = struct {
|
||||
|
@ -251,14 +254,14 @@ pub fn get_mru_position(self: *Self, from: tp.pid_ref, file_path: []const u8) !v
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
pub fn did_open(self: *Self, file_path: []const u8, file_type: []const u8, language_server: []const u8, version: usize, text: []const u8) !void {
|
||||
self.update_mru(file_path, 0, 0) catch {};
|
||||
const lsp = self.get_lsp(language_server) catch |e| return tp.exit_error(e);
|
||||
const lsp = try self.get_lsp(language_server);
|
||||
if (!self.file_language_server.contains(file_path)) {
|
||||
const key = self.a.dupe(u8, file_path) catch |e| return tp.exit_error(e);
|
||||
self.file_language_server.put(key, lsp) catch |e| return tp.exit_error(e);
|
||||
const key = try self.a.dupe(u8, file_path);
|
||||
try self.file_language_server.put(key, lsp);
|
||||
}
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
try lsp.send_notification("textDocument/didOpen", .{
|
||||
.textDocument = .{ .uri = uri, .languageId = file_type, .version = version, .text = text },
|
||||
|
@ -267,7 +270,7 @@ pub fn did_open(self: *Self, file_path: []const u8, file_type: []const u8, langu
|
|||
|
||||
pub fn did_change(self: *Self, file_path: []const u8, version: usize, root_dst_addr: usize, root_src_addr: usize) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
|
||||
const root_dst: Buffer.Root = if (root_dst_addr == 0) return else @ptrFromInt(root_dst_addr);
|
||||
|
@ -359,18 +362,18 @@ fn scan_char(chars: []const u8, lines: *usize, char: u8, last_offset: ?*usize) v
|
|||
}
|
||||
}
|
||||
|
||||
pub fn did_save(self: *Self, file_path: []const u8) tp.result {
|
||||
pub fn did_save(self: *Self, file_path: []const u8) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
try lsp.send_notification("textDocument/didSave", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn did_close(self: *Self, file_path: []const u8) tp.result {
|
||||
pub fn did_close(self: *Self, file_path: []const u8) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
try lsp.send_notification("textDocument/didClose", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
|
@ -379,7 +382,7 @@ pub fn did_close(self: *Self, file_path: []const u8) tp.result {
|
|||
|
||||
pub fn goto_definition(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
const response = try lsp.send_request(self.a, "textDocument/definition", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
|
@ -454,7 +457,7 @@ fn navigate_to_location_link(_: *Self, from: tp.pid_ref, location_link: []const
|
|||
|
||||
pub fn completion(self: *Self, _: tp.pid_ref, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const lsp = try self.get_file_lsp(file_path);
|
||||
const uri = self.make_URI(file_path) catch |e| return tp.exit_error(e);
|
||||
const uri = try self.make_URI(file_path);
|
||||
defer self.a.free(uri);
|
||||
const response = try lsp.send_request(self.a, "textDocument/completion", .{
|
||||
.textDocument = .{ .uri = uri },
|
||||
|
@ -613,7 +616,7 @@ pub fn show_message(_: *Self, _: tp.pid_ref, params_cb: []const u8) !void {
|
|||
logger.print("{s}", .{msg});
|
||||
}
|
||||
|
||||
fn send_lsp_init_request(self: *Self, lsp: LSP, project_path: []const u8, project_basename: []const u8, project_uri: []const u8) error{Exit}!tp.message {
|
||||
fn send_lsp_init_request(self: *Self, lsp: LSP, project_path: []const u8, project_basename: []const u8, project_uri: []const u8) !tp.message {
|
||||
return lsp.send_request(self.a, "initialize", .{
|
||||
.processId = if (builtin.os.tag == .linux) std.os.linux.getpid() else null,
|
||||
.rootPath = project_path,
|
||||
|
|
|
@ -7,7 +7,6 @@ const cbor = @import("cbor");
|
|||
|
||||
const Self = @This();
|
||||
const module_name = @typeName(Self);
|
||||
pub const Error = error{ OutOfMemory, Exit };
|
||||
|
||||
pub const Kind = enum { insert, delete };
|
||||
pub const Edit = struct {
|
||||
|
@ -19,7 +18,7 @@ pub const Edit = struct {
|
|||
|
||||
pid: ?tp.pid,
|
||||
|
||||
pub fn create() Error!Self {
|
||||
pub fn create() !Self {
|
||||
return .{ .pid = try Process.create() };
|
||||
}
|
||||
|
||||
|
@ -39,14 +38,14 @@ const Process = struct {
|
|||
const Receiver = tp.Receiver(*Process);
|
||||
const outer_a = std.heap.page_allocator;
|
||||
|
||||
pub fn create() Error!tp.pid {
|
||||
pub fn create() !tp.pid {
|
||||
const self = try outer_a.create(Process);
|
||||
self.* = .{
|
||||
.arena = std.heap.ArenaAllocator.init(outer_a),
|
||||
.a = self.arena.allocator(),
|
||||
.receiver = Receiver.init(Process.receive, self),
|
||||
};
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name) catch |e| tp.exit_error(e);
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name);
|
||||
}
|
||||
|
||||
fn start(self: *Process) tp.result {
|
||||
|
@ -67,7 +66,7 @@ const Process = struct {
|
|||
var root_src: usize = 0;
|
||||
|
||||
return if (try m.match(.{ "D", tp.extract(&cb), tp.extract(&root_dst), tp.extract(&root_src) }))
|
||||
self.diff(from, cb, root_dst, root_src) catch |e| tp.exit_error(e)
|
||||
self.diff(from, cb, root_dst, root_src) catch |e| tp.exit_error(e, @errorReturnTrace())
|
||||
else if (try m.match(.{"shutdown"}))
|
||||
tp.exit_normal();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ const tp = @import("thespian");
|
|||
|
||||
const Self = @This();
|
||||
const module_name = @typeName(Self);
|
||||
pub const Error = error{ OutOfMemory, Exit };
|
||||
|
||||
pid: ?tp.pid,
|
||||
|
||||
|
@ -17,7 +16,7 @@ pub const Selection = struct {
|
|||
end: Cursor = Cursor{},
|
||||
};
|
||||
|
||||
pub fn create() Error!Self {
|
||||
pub fn create() !Self {
|
||||
return .{ .pid = try Process.create() };
|
||||
}
|
||||
|
||||
|
@ -46,7 +45,7 @@ const Process = struct {
|
|||
selection: ?Selection = null,
|
||||
};
|
||||
|
||||
pub fn create() Error!tp.pid {
|
||||
pub fn create() !tp.pid {
|
||||
const self = try outer_a.create(Process);
|
||||
self.* = .{
|
||||
.arena = std.heap.ArenaAllocator.init(outer_a),
|
||||
|
@ -55,7 +54,7 @@ const Process = struct {
|
|||
.forwards = std.ArrayList(Entry).init(self.a),
|
||||
.receiver = Receiver.init(Process.receive, self),
|
||||
};
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name) catch |e| tp.exit_error(e);
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name);
|
||||
}
|
||||
|
||||
fn start(self: *Process) tp.result {
|
||||
|
@ -87,6 +86,10 @@ const Process = struct {
|
|||
}
|
||||
|
||||
fn receive(self: *Process, from: tp.pid_ref, m: tp.message) tp.result {
|
||||
self.receive_safe(from, m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) !void {
|
||||
errdefer self.deinit();
|
||||
|
||||
var c: Cursor = .{};
|
||||
|
@ -106,9 +109,9 @@ const Process = struct {
|
|||
tp.exit_normal();
|
||||
}
|
||||
|
||||
fn update(self: *Process, entry_: Entry) tp.result {
|
||||
fn update(self: *Process, entry_: Entry) !void {
|
||||
const entry: Entry = .{
|
||||
.file_path = self.a.dupe(u8, entry_.file_path) catch |e| return tp.exit_error(e),
|
||||
.file_path = try self.a.dupe(u8, entry_.file_path),
|
||||
.cursor = entry_.cursor,
|
||||
.selection = entry_.selection,
|
||||
};
|
||||
|
@ -129,7 +132,7 @@ const Process = struct {
|
|||
self.a.free(top.file_path);
|
||||
tp.trace(tp.channel.all, tp.message.fmt(.{ "location", "forward", entry.file_path, entry.cursor.row, entry.cursor.col, self.backwards.items.len, self.forwards.items.len }));
|
||||
} else if (self.current) |current| {
|
||||
self.backwards.append(current) catch |e| return tp.exit_error(e);
|
||||
try self.backwards.append(current);
|
||||
tp.trace(tp.channel.all, tp.message.fmt(.{ "location", "new", current.file_path, current.cursor.row, current.cursor.col, self.backwards.items.len, self.forwards.items.len }));
|
||||
self.clear_forwards();
|
||||
}
|
||||
|
|
18
src/log.zig
18
src/log.zig
|
@ -28,7 +28,7 @@ pub fn spawn(ctx: *tp.context, a: std.mem.Allocator, env: ?*const tp.env) !tp.pi
|
|||
|
||||
fn start(args: StartArgs) tp.result {
|
||||
_ = tp.set_trap(true);
|
||||
var this = Self.init(args) catch |e| return tp.exit_error(e);
|
||||
var this = Self.init(args) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
errdefer this.deinit();
|
||||
tp.receive(&this.receiver);
|
||||
}
|
||||
|
@ -135,15 +135,27 @@ pub const Logger = struct {
|
|||
error.Exit => {
|
||||
const msg_: tp.message = .{ .buf = tp.error_message() };
|
||||
var msg__: []const u8 = undefined;
|
||||
if (!(msg_.match(.{ "exit", tp.extract(&msg__) }) catch false))
|
||||
var trace__: []const u8 = "";
|
||||
if (msg_.match(.{ "exit", tp.extract(&msg__) }) catch false) {
|
||||
//
|
||||
} else if (msg_.match(.{ "exit", tp.extract(&msg__), tp.extract(&trace__) }) catch false) {
|
||||
//
|
||||
} else {
|
||||
msg__ = msg_.buf;
|
||||
}
|
||||
if (msg__.len > buf.len) {
|
||||
self.proc.send(.{ "log", "error", self.tag, context, "->", "MESSAGE TOO LARGE" }) catch {};
|
||||
return;
|
||||
}
|
||||
const msg___ = buf[0..msg__.len];
|
||||
@memcpy(msg___, msg__);
|
||||
msg = msg___;
|
||||
if (buf.len - msg___.len > trace__.len) {
|
||||
const msg____ = buf[0 .. msg__.len + trace__.len];
|
||||
@memcpy(msg____[msg__.len..], trace__);
|
||||
msg = msg____;
|
||||
} else {
|
||||
msg = msg___;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
msg = @errorName(e);
|
||||
|
|
|
@ -13,13 +13,13 @@ pid: tp.pid_ref,
|
|||
const Self = @This();
|
||||
const module_name = @typeName(Self);
|
||||
|
||||
pub fn get() error{Exit}!Self {
|
||||
pub fn get() !Self {
|
||||
const pid = tp.env.get().proc(module_name);
|
||||
return if (pid.expired()) create() else .{ .pid = pid };
|
||||
}
|
||||
|
||||
fn create() error{Exit}!Self {
|
||||
const pid = Process.create() catch |e| return tp.exit_error(e);
|
||||
fn create() !Self {
|
||||
const pid = try Process.create();
|
||||
defer pid.deinit();
|
||||
tp.env.get().proc_set(module_name, pid.ref());
|
||||
return .{ .pid = tp.env.get().proc(module_name) };
|
||||
|
@ -34,35 +34,35 @@ pub fn shutdown() void {
|
|||
pid.send(.{"shutdown"}) catch {};
|
||||
}
|
||||
|
||||
pub fn open_cwd() tp.result {
|
||||
pub fn open_cwd() !void {
|
||||
return open(".");
|
||||
}
|
||||
|
||||
pub fn open(rel_project_directory: []const u8) tp.result {
|
||||
pub fn open(rel_project_directory: []const u8) !void {
|
||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const project_directory = std.fs.cwd().realpath(rel_project_directory, &path_buf) catch "(none)";
|
||||
var dir = std.fs.openDirAbsolute(project_directory, .{}) catch |e| return tp.exit_error(e);
|
||||
dir.setAsCwd() catch |e| return tp.exit_error(e);
|
||||
var dir = try std.fs.openDirAbsolute(project_directory, .{});
|
||||
try dir.setAsCwd();
|
||||
dir.close();
|
||||
tp.env.get().str_set("project", project_directory);
|
||||
return (try get()).pid.send(.{ "open", project_directory });
|
||||
}
|
||||
|
||||
pub fn request_recent_files(max: usize) tp.result {
|
||||
pub fn request_recent_files(max: usize) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "request_recent_files", project, max });
|
||||
}
|
||||
|
||||
pub fn query_recent_files(max: usize, query: []const u8) tp.result {
|
||||
pub fn query_recent_files(max: usize, query: []const u8) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "query_recent_files", project, max, query });
|
||||
}
|
||||
|
||||
pub fn did_open(file_path: []const u8, file_type: *const FileType, version: usize, text: []const u8) tp.result {
|
||||
pub fn did_open(file_path: []const u8, file_type: *const FileType, version: usize, text: []const u8) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
|
@ -70,49 +70,49 @@ pub fn did_open(file_path: []const u8, file_type: *const FileType, version: usiz
|
|||
return (try get()).pid.send(.{ "did_open", project, file_path, file_type.name, file_type.language_server, version, text_ptr, text.len });
|
||||
}
|
||||
|
||||
pub fn did_change(file_path: []const u8, version: usize, root_dst: usize, root_src: usize) tp.result {
|
||||
pub fn did_change(file_path: []const u8, version: usize, root_dst: usize, root_src: usize) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "did_change", project, file_path, version, root_dst, root_src });
|
||||
}
|
||||
|
||||
pub fn did_save(file_path: []const u8) tp.result {
|
||||
pub fn did_save(file_path: []const u8) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "did_save", project, file_path });
|
||||
}
|
||||
|
||||
pub fn did_close(file_path: []const u8) tp.result {
|
||||
pub fn did_close(file_path: []const u8) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "did_close", project, file_path });
|
||||
}
|
||||
|
||||
pub fn goto_definition(file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
pub fn goto_definition(file_path: []const u8, row: usize, col: usize) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "goto_definition", project, file_path, row, col });
|
||||
}
|
||||
|
||||
pub fn completion(file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
pub fn completion(file_path: []const u8, row: usize, col: usize) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "completion", project, file_path, row, col });
|
||||
}
|
||||
|
||||
pub fn update_mru(file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
pub fn update_mru(file_path: []const u8, row: usize, col: usize) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
return (try get()).pid.send(.{ "update_mru", project, file_path, row, col });
|
||||
}
|
||||
|
||||
pub fn get_mru_position(file_path: []const u8) tp.result {
|
||||
pub fn get_mru_position(file_path: []const u8) !void {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0)
|
||||
return tp.exit("No project");
|
||||
|
@ -140,7 +140,7 @@ const Process = struct {
|
|||
.receiver = Receiver.init(Process.receive, self),
|
||||
.projects = ProjectsMap.init(a),
|
||||
};
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name) catch |e| tp.exit_error(e);
|
||||
return tp.spawn_link(self.a, self, Process.start, module_name);
|
||||
}
|
||||
|
||||
fn deinit(self: *Process) void {
|
||||
|
@ -166,11 +166,11 @@ const Process = struct {
|
|||
self.receive_safe(from, m) catch |e| {
|
||||
if (std.mem.eql(u8, "normal", tp.error_text()))
|
||||
return e;
|
||||
self.logger.err("receive", e);
|
||||
self.logger.err("receive", tp.exit_error(e, @errorReturnTrace()));
|
||||
};
|
||||
}
|
||||
|
||||
fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) tp.result {
|
||||
fn receive_safe(self: *Process, from: tp.pid_ref, m: tp.message) !void {
|
||||
var project_directory: []const u8 = undefined;
|
||||
var path: []const u8 = undefined;
|
||||
var query: []const u8 = undefined;
|
||||
|
@ -201,9 +201,9 @@ const Process = struct {
|
|||
} else if (try m.match(.{ "walk_tree_done", tp.extract(&project_directory) })) {
|
||||
if (self.walker) |pid| pid.deinit();
|
||||
self.walker = null;
|
||||
self.loaded(project_directory) catch |e| return from.forward_error(e);
|
||||
self.loaded(project_directory) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "update_mru", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||
self.update_mru(project_directory, path, row, col) catch |e| return from.forward_error(e);
|
||||
self.update_mru(project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "child", tp.extract(&project_directory), tp.extract(&language_server), "notify", tp.extract(&method), tp.extract_cbor(¶ms_cb) })) {
|
||||
self.dispatch_notify(project_directory, language_server, method, params_cb) catch |e| return self.logger.err("lsp-handling", e);
|
||||
} else if (try m.match(.{ "child", tp.extract(&project_directory), tp.extract(&language_server), "request", tp.extract(&method), tp.extract(&id), tp.extract_cbor(¶ms_cb) })) {
|
||||
|
@ -211,26 +211,26 @@ const Process = struct {
|
|||
} else if (try m.match(.{ "child", tp.extract(&path), "done" })) {
|
||||
self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path});
|
||||
} else if (try m.match(.{ "open", tp.extract(&project_directory) })) {
|
||||
self.open(project_directory) catch |e| return from.forward_error(e);
|
||||
self.open(project_directory) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "request_recent_files", tp.extract(&project_directory), tp.extract(&max) })) {
|
||||
self.request_recent_files(from, project_directory, max) catch |e| return from.forward_error(e);
|
||||
self.request_recent_files(from, project_directory, max) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "query_recent_files", tp.extract(&project_directory), tp.extract(&max), tp.extract(&query) })) {
|
||||
self.query_recent_files(from, project_directory, max, query) catch |e| return from.forward_error(e);
|
||||
self.query_recent_files(from, project_directory, max, query) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} 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(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, @errorReturnTrace());
|
||||
} 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);
|
||||
self.did_change(project_directory, path, version, root_dst, root_src) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "did_save", tp.extract(&project_directory), tp.extract(&path) })) {
|
||||
self.did_save(project_directory, path) catch |e| return from.forward_error(e);
|
||||
self.did_save(project_directory, path) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "did_close", tp.extract(&project_directory), tp.extract(&path) })) {
|
||||
self.did_close(project_directory, path) catch |e| return from.forward_error(e);
|
||||
self.did_close(project_directory, path) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "goto_definition", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||
self.goto_definition(from, project_directory, path, row, col) catch |e| return from.forward_error(e);
|
||||
self.goto_definition(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "completion", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) {
|
||||
self.completion(from, project_directory, path, row, col) catch |e| return from.forward_error(e);
|
||||
self.completion(from, project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "get_mru_position", tp.extract(&project_directory), tp.extract(&path) })) {
|
||||
self.get_mru_position(from, project_directory, path) catch |e| return from.forward_error(e);
|
||||
self.get_mru_position(from, project_directory, path) catch |e| return from.forward_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"shutdown"})) {
|
||||
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
|
||||
self.persist_projects();
|
||||
|
@ -245,7 +245,7 @@ const Process = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn open(self: *Process, project_directory: []const u8) error{ OutOfMemory, Exit }!void {
|
||||
fn open(self: *Process, project_directory: []const u8) !void {
|
||||
if (self.projects.get(project_directory) == null) {
|
||||
self.logger.print("opening: {s}", .{project_directory});
|
||||
const project = try self.a.create(Project);
|
||||
|
@ -282,72 +282,72 @@ 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, 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) !void {
|
||||
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(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 {
|
||||
fn did_change(self: *Process, project_directory: []const u8, file_path: []const u8, version: usize, root_dst: usize, root_src: usize) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_change" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.did_change(file_path, version, root_dst, root_src) catch |e| tp.exit_error(e);
|
||||
return project.did_change(file_path, version, root_dst, root_src);
|
||||
}
|
||||
|
||||
fn did_save(self: *Process, project_directory: []const u8, file_path: []const u8) tp.result {
|
||||
fn did_save(self: *Process, project_directory: []const u8, file_path: []const u8) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_save" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.did_save(file_path);
|
||||
}
|
||||
|
||||
fn did_close(self: *Process, project_directory: []const u8, file_path: []const u8) tp.result {
|
||||
fn did_close(self: *Process, project_directory: []const u8, file_path: []const u8) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_close" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.did_close(file_path);
|
||||
}
|
||||
|
||||
fn goto_definition(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
fn goto_definition(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".goto_definition" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.goto_definition(from, file_path, row, col) catch |e| tp.exit_error(e);
|
||||
return project.goto_definition(from, file_path, row, col);
|
||||
}
|
||||
|
||||
fn completion(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
fn completion(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".completion" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.completion(from, file_path, row, col) catch |e| tp.exit_error(e);
|
||||
return project.completion(from, file_path, row, col);
|
||||
}
|
||||
|
||||
fn get_mru_position(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8) tp.result {
|
||||
fn get_mru_position(self: *Process, from: tp.pid_ref, project_directory: []const u8, file_path: []const u8) !void {
|
||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".get_mru_position" });
|
||||
defer frame.deinit();
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.get_mru_position(from, file_path) catch |e| tp.exit_error(e);
|
||||
return project.get_mru_position(from, file_path);
|
||||
}
|
||||
|
||||
fn update_mru(self: *Process, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) tp.result {
|
||||
fn update_mru(self: *Process, project_directory: []const u8, file_path: []const u8, row: usize, col: usize) !void {
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return project.update_mru(file_path, row, col) catch |e| tp.exit_error(e);
|
||||
return project.update_mru(file_path, row, col);
|
||||
}
|
||||
|
||||
fn dispatch_notify(self: *Process, project_directory: []const u8, language_server: []const u8, method: []const u8, params_cb: []const u8) tp.result {
|
||||
fn dispatch_notify(self: *Process, project_directory: []const u8, language_server: []const u8, method: []const u8, params_cb: []const u8) !void {
|
||||
_ = language_server;
|
||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||
return if (std.mem.eql(u8, method, "textDocument/publishDiagnostics"))
|
||||
project.publish_diagnostics(self.parent.ref(), params_cb) catch |e| tp.exit_error(e)
|
||||
project.publish_diagnostics(self.parent.ref(), params_cb)
|
||||
else if (std.mem.eql(u8, method, "window/showMessage"))
|
||||
project.show_message(self.parent.ref(), params_cb) catch |e| tp.exit_error(e)
|
||||
project.show_message(self.parent.ref(), params_cb)
|
||||
else
|
||||
tp.exit_fmt("unsupported LSP notification: {s}", .{method});
|
||||
}
|
||||
|
||||
fn dispatch_request(self: *Process, project_directory: []const u8, language_server: []const u8, method: []const u8, id: i32, params_cb: []const u8) tp.result {
|
||||
fn dispatch_request(self: *Process, project_directory: []const u8, language_server: []const u8, method: []const u8, id: i32, params_cb: []const u8) !void {
|
||||
_ = self;
|
||||
_ = project_directory;
|
||||
_ = language_server;
|
||||
|
@ -410,7 +410,7 @@ const Process = struct {
|
|||
}
|
||||
};
|
||||
|
||||
fn walk_tree_async(a_: std.mem.Allocator, root_path_: []const u8) error{Exit}!tp.pid {
|
||||
fn walk_tree_async(a_: std.mem.Allocator, root_path_: []const u8) !tp.pid {
|
||||
return struct {
|
||||
a: std.mem.Allocator,
|
||||
root_path: []const u8,
|
||||
|
@ -422,17 +422,17 @@ fn walk_tree_async(a_: std.mem.Allocator, root_path_: []const u8) error{Exit}!tp
|
|||
const tree_walker = @This();
|
||||
const Receiver = tp.Receiver(*tree_walker);
|
||||
|
||||
fn spawn_link(a: std.mem.Allocator, root_path: []const u8) error{Exit}!tp.pid {
|
||||
const self = a.create(tree_walker) catch |e| return tp.exit_error(e);
|
||||
fn spawn_link(a: std.mem.Allocator, root_path: []const u8) !tp.pid {
|
||||
const self = try a.create(tree_walker);
|
||||
self.* = .{
|
||||
.a = a,
|
||||
.root_path = a.dupe(u8, root_path) catch |e| return tp.exit_error(e),
|
||||
.root_path = try a.dupe(u8, root_path),
|
||||
.parent = tp.self_pid().clone(),
|
||||
.receiver = Receiver.init(tree_walker.receive, self),
|
||||
.dir = std.fs.cwd().openDir(self.root_path, .{ .iterate = true }) catch |e| return tp.exit_error(e),
|
||||
.walker = walk_filtered(self.dir, self.a) catch |e| return tp.exit_error(e),
|
||||
.dir = try std.fs.cwd().openDir(self.root_path, .{ .iterate = true }),
|
||||
.walker = try walk_filtered(self.dir, self.a),
|
||||
};
|
||||
return tp.spawn_link(a, self, tree_walker.start, module_name ++ ".tree_walker") catch |e| return tp.exit_error(e);
|
||||
return tp.spawn_link(a, self, tree_walker.start, module_name ++ ".tree_walker");
|
||||
}
|
||||
|
||||
fn start(self: *tree_walker) tp.result {
|
||||
|
@ -440,7 +440,7 @@ fn walk_tree_async(a_: std.mem.Allocator, root_path_: []const u8) error{Exit}!tp
|
|||
const frame = tracy.initZone(@src(), .{ .name = "project scan" });
|
||||
defer frame.deinit();
|
||||
tp.receive(&self.receiver);
|
||||
self.next() catch |e| return tp.exit_error(e);
|
||||
self.next() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn deinit(self: *tree_walker) void {
|
||||
|
@ -456,7 +456,7 @@ fn walk_tree_async(a_: std.mem.Allocator, root_path_: []const u8) error{Exit}!tp
|
|||
defer frame.deinit();
|
||||
|
||||
if (try m.match(.{"next"})) {
|
||||
self.next() catch |e| return tp.exit_error(e);
|
||||
self.next() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"stop"})) {
|
||||
return tp.exit_normal();
|
||||
} else {
|
||||
|
|
|
@ -11,9 +11,9 @@ stdin_behavior: std.process.Child.StdIo,
|
|||
const Self = @This();
|
||||
const module_name = @typeName(Self);
|
||||
pub const max_chunk_size = tp.subprocess.max_chunk_size;
|
||||
pub const Writer = std.io.Writer(*Self, error{Exit}, write);
|
||||
pub const Writer = std.io.Writer(*Self, Error, write);
|
||||
pub const BufferedWriter = std.io.BufferedWriter(max_chunk_size, Writer);
|
||||
pub const Error = error{ OutOfMemory, Exit };
|
||||
pub const Error = error{ OutOfMemory, Exit, ThespianSpawnFailed, Closed };
|
||||
|
||||
pub const FindF = fn (a: std.mem.Allocator, query: []const u8, tag: [:0]const u8) Error!Self;
|
||||
|
||||
|
@ -21,11 +21,11 @@ pub fn find_in_stdin(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8)
|
|||
return create(a, query, tag, .Pipe);
|
||||
}
|
||||
|
||||
pub fn find_in_files(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8) Error!Self {
|
||||
pub fn find_in_files(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8) !Self {
|
||||
return create(a, query, tag, .Close);
|
||||
}
|
||||
|
||||
fn create(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8, stdin_behavior: std.process.Child.StdIo) Error!Self {
|
||||
fn create(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8, stdin_behavior: std.process.Child.StdIo) !Self {
|
||||
return .{ .pid = try Process.create(a, query, tag, stdin_behavior), .stdin_behavior = stdin_behavior };
|
||||
}
|
||||
|
||||
|
@ -38,13 +38,13 @@ pub fn deinit(self: *Self) void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write(self: *Self, bytes: []const u8) error{Exit}!usize {
|
||||
pub fn write(self: *Self, bytes: []const u8) !usize {
|
||||
try self.input(bytes);
|
||||
return bytes.len;
|
||||
}
|
||||
|
||||
pub fn input(self: *const Self, bytes: []const u8) tp.result {
|
||||
const pid = if (self.pid) |pid| pid else return tp.exit_error(error.Closed);
|
||||
pub fn input(self: *const Self, bytes: []const u8) !void {
|
||||
const pid = if (self.pid) |pid| pid else return error.Closed;
|
||||
var remaining = bytes;
|
||||
while (remaining.len > 0)
|
||||
remaining = loop: {
|
||||
|
@ -83,7 +83,7 @@ const Process = struct {
|
|||
|
||||
const Receiver = tp.Receiver(*Process);
|
||||
|
||||
pub fn create(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8, stdin_behavior: std.process.Child.StdIo) Error!tp.pid {
|
||||
pub fn create(a: std.mem.Allocator, query: []const u8, tag: [:0]const u8, stdin_behavior: std.process.Child.StdIo) !tp.pid {
|
||||
const self = try a.create(Process);
|
||||
self.* = .{
|
||||
.a = a,
|
||||
|
@ -95,7 +95,7 @@ const Process = struct {
|
|||
.logger = log.logger(@typeName(Self)),
|
||||
.stdin_behavior = stdin_behavior,
|
||||
};
|
||||
return tp.spawn_link(self.a, self, Process.start, tag) catch |e| tp.exit_error(e);
|
||||
return tp.spawn_link(self.a, self, Process.start, tag);
|
||||
}
|
||||
|
||||
fn deinit(self: *Process) void {
|
||||
|
@ -121,7 +121,7 @@ const Process = struct {
|
|||
"--json",
|
||||
self.query,
|
||||
});
|
||||
self.sp = tp.subprocess.init(self.a, args, module_name, self.stdin_behavior) catch |e| return tp.exit_error(e);
|
||||
self.sp = tp.subprocess.init(self.a, args, module_name, self.stdin_behavior) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
tp.receive(&self.receiver);
|
||||
}
|
||||
|
||||
|
@ -130,14 +130,14 @@ const Process = struct {
|
|||
var bytes: []u8 = "";
|
||||
|
||||
if (try m.match(.{ "input", tp.extract(&bytes) })) {
|
||||
const sp = if (self.sp) |sp| sp else return tp.exit_error(error.Closed);
|
||||
const sp = if (self.sp) |sp| sp else return tp.exit_error(error.Closed, null);
|
||||
try sp.send(bytes);
|
||||
} else if (try m.match(.{"close"})) {
|
||||
try self.close();
|
||||
} else if (try m.match(.{ module_name, "stdout", tp.extract(&bytes) })) {
|
||||
self.handle_output(bytes) catch |e| return tp.exit_error(e);
|
||||
self.handle_output(bytes) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ module_name, "term", tp.more })) {
|
||||
self.handle_terminated() catch |e| return tp.exit_error(e);
|
||||
self.handle_terminated() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ module_name, "stderr", tp.extract(&bytes) })) {
|
||||
self.logger.print("ERR: {s}", .{bytes});
|
||||
} else if (try m.match(.{ "exit", "normal" })) {
|
||||
|
|
|
@ -123,7 +123,7 @@ pub const List = struct {
|
|||
pub fn filter(self: *const List, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
var sfa = std.heap.stackFallback(4096, self.a);
|
||||
const a = sfa.get();
|
||||
const buf = a.alloc(u8, m.buf.len) catch |e| return tp.exit_error(e);
|
||||
const buf = a.alloc(u8, m.buf.len) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
defer a.free(buf);
|
||||
@memcpy(buf[0..m.buf.len], m.buf);
|
||||
const m_: tp.message = .{ .buf = buf[0..m.buf.len] };
|
||||
|
|
|
@ -7,6 +7,7 @@ const tui = @import("tui.zig");
|
|||
pub const ID = usize;
|
||||
pub const ID_unknown = std.math.maxInt(ID);
|
||||
|
||||
pub const Result = anyerror!void;
|
||||
pub const Context = struct {
|
||||
args: tp.message = .{},
|
||||
|
||||
|
@ -29,7 +30,7 @@ pub fn Closure(comptime T: type) type {
|
|||
f: FunT,
|
||||
data: T,
|
||||
|
||||
const FunT: type = *const fn (T, ctx: Context) tp.result;
|
||||
const FunT: type = *const fn (T, ctx: Context) Result;
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(f: FunT, data: T, name: []const u8) Self {
|
||||
|
@ -61,7 +62,7 @@ pub fn Closure(comptime T: type) type {
|
|||
|
||||
fn run(vtbl: *Vtable, ctx: Context) tp.result {
|
||||
const self: *Self = fromVtable(vtbl);
|
||||
return self.f(self.data, ctx);
|
||||
return self.f(self.data, ctx) catch |e| tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn fromVtable(vtbl: *Vtable) *Self {
|
||||
|
@ -96,7 +97,7 @@ pub fn execute(id: ID, ctx: Context) tp.result {
|
|||
const cmd = commands.items[id];
|
||||
if (cmd) |p| {
|
||||
// var buf: [tp.max_message_size]u8 = undefined;
|
||||
// log.print("cmd", "execute({s}) {s}", .{ p.name, ctx.args.to_json(&buf) catch "" }) catch |e| return tp.exit_error(e);
|
||||
// log.print("cmd", "execute({s}) {s}", .{ p.name, ctx.args.to_json(&buf) catch "" }) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
return p.run(p, ctx);
|
||||
} else {
|
||||
return tp.exit_fmt("CommandNotAvailable: {d}", .{id});
|
||||
|
@ -129,7 +130,7 @@ pub fn executeName(name: []const u8, ctx: Context) tp.result {
|
|||
|
||||
fn CmdDef(comptime T: type) type {
|
||||
return struct {
|
||||
const Fn = fn (T, Context) tp.result;
|
||||
const Fn = fn (T, Context) anyerror!void;
|
||||
name: [:0]const u8,
|
||||
f: *const Fn,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -76,7 +76,7 @@ fn diff_symbols_clear(self: *Self) void {
|
|||
|
||||
pub fn handle_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||
if (try m.match(.{ "E", "update", tp.more }))
|
||||
return self.diff_update() catch |e| return tp.exit_error(e);
|
||||
return self.diff_update() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
if (try m.match(.{ "E", "view", tp.extract(&self.lines), tp.extract(&self.rows), tp.extract(&self.row) }))
|
||||
return self.update_width();
|
||||
if (try m.match(.{ "E", "pos", tp.extract(&self.lines), tp.extract(&self.line), tp.more }))
|
||||
|
@ -382,7 +382,7 @@ fn process_edit(self: *Self, kind: Kind, line: usize, offset: usize, bytes: []co
|
|||
pub fn filter_receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
var cb: []const u8 = undefined;
|
||||
if (try m.match(.{ "DIFF", tp.extract_cbor(&cb) })) {
|
||||
self.process_diff(cb) catch |e| return tp.exit_error(e);
|
||||
self.process_diff(cb) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -189,24 +189,25 @@ const Commands = command.Collection(cmds);
|
|||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn home_menu_down(self: *Self, _: Ctx) tp.result {
|
||||
pub fn home_menu_down(self: *Self, _: Ctx) Result {
|
||||
self.menu.select_down();
|
||||
}
|
||||
|
||||
pub fn home_menu_up(self: *Self, _: Ctx) tp.result {
|
||||
pub fn home_menu_up(self: *Self, _: Ctx) Result {
|
||||
self.menu.select_up();
|
||||
}
|
||||
|
||||
pub fn home_menu_activate(self: *Self, _: Ctx) tp.result {
|
||||
pub fn home_menu_activate(self: *Self, _: Ctx) Result {
|
||||
self.menu.activate_selected();
|
||||
}
|
||||
|
||||
pub fn home_sheeran(self: *Self, _: Ctx) tp.result {
|
||||
pub fn home_sheeran(self: *Self, _: Ctx) Result {
|
||||
self.fire = if (self.fire) |*fire| ret: {
|
||||
fire.deinit();
|
||||
break :ret null;
|
||||
} else Fire.init(self.a, self.plane) catch |e| return tp.exit_error(e);
|
||||
} else try Fire.init(self.a, self.plane);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -103,8 +103,8 @@ fn append(self: *Self, json: []const u8) !void {
|
|||
pub fn listen(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||
if (try m.match(.{ "M", tp.more })) return;
|
||||
var buf: [4096]u8 = undefined;
|
||||
const json = m.to_json(&buf) catch |e| return tp.exit_error(e);
|
||||
self.append(json) catch |e| return tp.exit_error(e);
|
||||
const json = m.to_json(&buf) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.append(json) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
pub fn receive(_: *Self, _: tp.pid_ref, _: tp.message) error{Exit}!bool {
|
||||
|
|
|
@ -108,7 +108,7 @@ pub fn box(self: *const Self) Box {
|
|||
return Box.from(self.plane);
|
||||
}
|
||||
|
||||
fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) error{Exit}!bool {
|
||||
fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) !bool {
|
||||
var enabled = true;
|
||||
if (self.panels) |panels| {
|
||||
if (panels.get(@typeName(view))) |w| {
|
||||
|
@ -121,12 +121,12 @@ fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) error{Exit}!
|
|||
enabled = false;
|
||||
}
|
||||
} else {
|
||||
panels.add(view.create(self.a, self.widgets.plane) catch |e| return tp.exit_error(e)) catch |e| return tp.exit_error(e);
|
||||
try panels.add(try view.create(self.a, self.widgets.plane));
|
||||
}
|
||||
} else {
|
||||
const panels = WidgetList.createH(self.a, self.widgets.widget(), "panel", .{ .static = self.box().h / 5 }) catch |e| return tp.exit_error(e);
|
||||
self.widgets.add(panels.widget()) catch |e| return tp.exit_error(e);
|
||||
panels.add(view.create(self.a, self.widgets.plane) catch |e| return tp.exit_error(e)) catch |e| return tp.exit_error(e);
|
||||
const panels = try WidgetList.createH(self.a, self.widgets.widget(), "panel", .{ .static = self.box().h / 5 });
|
||||
try self.widgets.add(panels.widget());
|
||||
try panels.add(try view.create(self.a, self.widgets.plane));
|
||||
self.panels = panels;
|
||||
}
|
||||
tui.current().resize();
|
||||
|
@ -141,11 +141,11 @@ fn close_all_panel_views(self: *Self) void {
|
|||
tui.current().resize();
|
||||
}
|
||||
|
||||
fn toggle_view(self: *Self, view: anytype) tp.result {
|
||||
fn toggle_view(self: *Self, view: anytype) !void {
|
||||
if (self.widgets.get(@typeName(view))) |w| {
|
||||
self.widgets.remove(w.*);
|
||||
} else {
|
||||
self.widgets.add(view.create(self.a, self.plane) catch |e| return tp.exit_error(e)) catch |e| return tp.exit_error(e);
|
||||
try self.widgets.add(try view.create(self.a, self.plane));
|
||||
}
|
||||
tui.current().resize();
|
||||
}
|
||||
|
@ -153,23 +153,24 @@ fn toggle_view(self: *Self, view: anytype) tp.result {
|
|||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn quit(self: *Self, _: Ctx) tp.result {
|
||||
pub fn quit(self: *Self, _: Ctx) Result {
|
||||
if (self.editor) |editor| if (editor.is_dirty())
|
||||
return tp.exit("unsaved changes");
|
||||
try tp.self_pid().send("quit");
|
||||
}
|
||||
|
||||
pub fn quit_without_saving(_: *Self, _: Ctx) tp.result {
|
||||
pub fn quit_without_saving(_: *Self, _: Ctx) Result {
|
||||
try tp.self_pid().send("quit");
|
||||
}
|
||||
|
||||
pub fn open_project_cwd(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_project_cwd(self: *Self, _: Ctx) Result {
|
||||
try project_manager.open_cwd();
|
||||
_ = try self.statusbar.msg(.{ "PRJ", "open" });
|
||||
}
|
||||
|
||||
pub fn open_project_dir(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn open_project_dir(self: *Self, ctx: Ctx) Result {
|
||||
var project_dir: []const u8 = undefined;
|
||||
if (!try ctx.args.match(.{tp.extract(&project_dir)}))
|
||||
return;
|
||||
|
@ -177,7 +178,7 @@ const cmds = struct {
|
|||
_ = try self.statusbar.msg(.{ "PRJ", "open" });
|
||||
}
|
||||
|
||||
pub fn navigate(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn navigate(self: *Self, ctx: Ctx) Result {
|
||||
tui.reset_drag_context();
|
||||
const frame = tracy.initZone(@src(), .{ .name = "navigate" });
|
||||
defer frame.deinit();
|
||||
|
@ -192,27 +193,27 @@ const cmds = struct {
|
|||
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 (!try cbor.matchString(&iter, &field_name))
|
||||
return 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);
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&line)))
|
||||
return 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);
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&column)))
|
||||
return 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);
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&file)))
|
||||
return 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);
|
||||
if (!try cbor.matchValue(&iter, cbor.extract_cbor(&goto_args)))
|
||||
return error.InvalidArgument;
|
||||
} else {
|
||||
cbor.skipValue(&iter) catch |e| return tp.exit_error(e);
|
||||
try cbor.skipValue(&iter);
|
||||
}
|
||||
}
|
||||
} else |_| if (ctx.args.match(tp.extract(&file_name)) catch false) {
|
||||
file = file_name;
|
||||
} else return tp.exit_error(error.InvalidArgument);
|
||||
} else return error.InvalidArgument;
|
||||
|
||||
if (tp.env.get().str("project").len == 0) {
|
||||
try open_project_cwd(self, .{});
|
||||
|
@ -247,57 +248,57 @@ const cmds = struct {
|
|||
tui.need_render();
|
||||
}
|
||||
|
||||
pub fn open_help(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_help(self: *Self, _: Ctx) Result {
|
||||
tui.reset_drag_context();
|
||||
try self.create_editor();
|
||||
try command.executeName("open_scratch_buffer", command.fmt(.{ "help.md", @embedFile("help.md") }));
|
||||
tui.need_render();
|
||||
}
|
||||
|
||||
pub fn open_config(_: *Self, _: Ctx) tp.result {
|
||||
const file_name = root.get_config_file_name() catch |e| return tp.exit_error(e);
|
||||
pub fn open_config(_: *Self, _: Ctx) Result {
|
||||
const file_name = try root.get_config_file_name();
|
||||
try tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_name } });
|
||||
}
|
||||
|
||||
pub fn restore_session(self: *Self, _: Ctx) tp.result {
|
||||
pub fn restore_session(self: *Self, _: Ctx) Result {
|
||||
try self.create_editor();
|
||||
self.read_restore_info() catch |e| return tp.exit_error(e);
|
||||
try self.read_restore_info();
|
||||
tui.need_render();
|
||||
}
|
||||
|
||||
pub fn toggle_logview(self: *Self, _: Ctx) tp.result {
|
||||
pub fn toggle_logview(self: *Self, _: Ctx) Result {
|
||||
self.logview_enabled = try self.toggle_panel_view(@import("logview.zig"), false);
|
||||
}
|
||||
|
||||
pub fn show_logview(self: *Self, _: Ctx) tp.result {
|
||||
pub fn show_logview(self: *Self, _: Ctx) Result {
|
||||
self.logview_enabled = try self.toggle_panel_view(@import("logview.zig"), true);
|
||||
}
|
||||
|
||||
pub fn toggle_inputview(self: *Self, _: Ctx) tp.result {
|
||||
pub fn toggle_inputview(self: *Self, _: Ctx) Result {
|
||||
_ = try self.toggle_panel_view(@import("inputview.zig"), false);
|
||||
}
|
||||
|
||||
pub fn toggle_inspector_view(self: *Self, _: Ctx) tp.result {
|
||||
pub fn toggle_inspector_view(self: *Self, _: Ctx) Result {
|
||||
_ = try self.toggle_panel_view(@import("inspector_view.zig"), false);
|
||||
}
|
||||
|
||||
pub fn show_inspector_view(self: *Self, _: Ctx) tp.result {
|
||||
pub fn show_inspector_view(self: *Self, _: Ctx) Result {
|
||||
_ = try self.toggle_panel_view(@import("inspector_view.zig"), true);
|
||||
}
|
||||
|
||||
pub fn jump_back(self: *Self, _: Ctx) tp.result {
|
||||
pub fn jump_back(self: *Self, _: Ctx) Result {
|
||||
try self.location_history.back(location_jump);
|
||||
}
|
||||
|
||||
pub fn jump_forward(self: *Self, _: Ctx) tp.result {
|
||||
pub fn jump_forward(self: *Self, _: Ctx) Result {
|
||||
try self.location_history.forward(location_jump);
|
||||
}
|
||||
|
||||
pub fn show_home(self: *Self, _: Ctx) tp.result {
|
||||
pub fn show_home(self: *Self, _: Ctx) Result {
|
||||
return self.create_home();
|
||||
}
|
||||
|
||||
pub fn gutter_mode_next(self: *Self, _: Ctx) tp.result {
|
||||
pub fn gutter_mode_next(self: *Self, _: Ctx) Result {
|
||||
const tui_ = tui.current();
|
||||
var ln = tui_.config.gutter_line_numbers;
|
||||
var lnr = tui_.config.gutter_line_numbers_relative;
|
||||
|
@ -313,7 +314,7 @@ const cmds = struct {
|
|||
}
|
||||
tui_.config.gutter_line_numbers = ln;
|
||||
tui_.config.gutter_line_numbers_relative = lnr;
|
||||
tui_.save_config() catch |e| return tp.exit_error(e);
|
||||
try tui_.save_config();
|
||||
if (self.widgets.get("editor_gutter")) |gutter_widget| {
|
||||
const gutter = if (gutter_widget.dynamic_cast(@import("editor_gutter.zig"))) |p| p else return;
|
||||
gutter.linenum = ln;
|
||||
|
@ -387,8 +388,8 @@ fn location_jump(from: tp.pid_ref, file_path: []const u8, cursor: location_histo
|
|||
} }) catch return;
|
||||
}
|
||||
|
||||
fn clear_auto_find(self: *Self, editor: *ed.Editor) !void {
|
||||
try editor.clear_matches();
|
||||
fn clear_auto_find(self: *Self, editor: *ed.Editor) void {
|
||||
editor.clear_matches();
|
||||
self.store_last_match_text(null);
|
||||
}
|
||||
|
||||
|
@ -412,11 +413,11 @@ pub fn walk(self: *Self, ctx: *anyopaque, f: Widget.WalkFn, w: *Widget) bool {
|
|||
return self.floating_views.walk(ctx, f) or self.widgets.walk(ctx, f, &self.widgets_widget) or f(ctx, w);
|
||||
}
|
||||
|
||||
fn create_editor(self: *Self) tp.result {
|
||||
fn create_editor(self: *Self) !void {
|
||||
if (self.editor) |editor| if (editor.file_path) |file_path| self.push_file_stack(file_path) catch {};
|
||||
self.widgets.replace(0, Widget.empty(self.a, self.plane, .dynamic) catch |e| return tp.exit_error(e));
|
||||
self.widgets.replace(0, try Widget.empty(self.a, self.plane, .dynamic));
|
||||
command.executeName("enter_mode_default", .{}) catch {};
|
||||
var editor_widget = ed.create(self.a, Widget.to(self)) catch |e| return tp.exit_error(e);
|
||||
var editor_widget = try ed.create(self.a, Widget.to(self));
|
||||
errdefer editor_widget.deinit(self.a);
|
||||
if (editor_widget.get("editor")) |editor| {
|
||||
editor.subscribe(EventHandler.to_unowned(self.statusbar)) catch @panic("subscribe unsupported");
|
||||
|
@ -443,10 +444,10 @@ fn show_home_async(_: *Self) void {
|
|||
tp.self_pid().send(.{ "cmd", "show_home" }) catch return;
|
||||
}
|
||||
|
||||
fn create_home(self: *Self) tp.result {
|
||||
fn create_home(self: *Self) !void {
|
||||
tui.reset_drag_context();
|
||||
if (self.editor) |_| return;
|
||||
var home_widget = home.create(self.a, Widget.to(self)) catch |e| return tp.exit_error(e);
|
||||
var home_widget = try home.create(self.a, Widget.to(self));
|
||||
errdefer home_widget.deinit(self.a);
|
||||
self.widgets.replace(0, home_widget);
|
||||
tui.current().resize();
|
||||
|
|
|
@ -50,18 +50,18 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.paste_bytes(text);
|
||||
self.paste_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn add_keybind() void {}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -70,7 +70,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||
switch (keypress) {
|
||||
|
@ -225,7 +225,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) tp.result {
|
||||
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
|
||||
defer self.leader = null;
|
||||
const ldr = if (self.leader) |leader| leader else return;
|
||||
return switch (ldr.modifiers) {
|
||||
|
@ -245,7 +245,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||
|
@ -253,32 +253,32 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.input.appendSlice(buf[0..bytes]);
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
self.input.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
try self.input.appendSlice(bytes);
|
||||
}
|
||||
|
||||
fn paste_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn paste_bytes(self: *Self, bytes: []const u8) !void {
|
||||
try self.flush_input();
|
||||
try command.executeName("paste", command.fmt(.{bytes}));
|
||||
}
|
||||
|
||||
var insert_chars_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.items.len > 0) {
|
||||
defer self.input.clearRetainingCapacity();
|
||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
||||
return tp.exit_error(error.InputTargetNotFound);
|
||||
return tp.exit_error(error.InputTargetNotFound, null);
|
||||
};
|
||||
try command.execute(id, command.fmt(.{self.input.items}));
|
||||
self.last_cmd = "insert_chars";
|
||||
|
|
|
@ -53,20 +53,20 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.flush_input();
|
||||
try self.insert_bytes(text);
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn add_keybind() void {}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -75,7 +75,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||
switch (keypress) {
|
||||
|
@ -227,7 +227,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) tp.result {
|
||||
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
|
||||
defer self.leader = null;
|
||||
const ldr = if (self.leader) |leader| leader else return;
|
||||
return switch (ldr.modifiers) {
|
||||
|
@ -247,7 +247,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||
|
@ -255,27 +255,27 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.input.appendSlice(buf[0..bytes]);
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
self.input.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
try self.input.appendSlice(bytes);
|
||||
}
|
||||
|
||||
var insert_chars_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.items.len > 0) {
|
||||
defer self.input.clearRetainingCapacity();
|
||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
||||
return tp.exit_error(error.InputTargetNotFound);
|
||||
return tp.exit_error(error.InputTargetNotFound, null);
|
||||
};
|
||||
try command.execute(id, command.fmt(.{self.input.items}));
|
||||
self.last_cmd = "insert_chars";
|
||||
|
@ -306,25 +306,26 @@ const Commands = command.Collection(cmds_);
|
|||
const cmds_ = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn @"w"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn w(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
}
|
||||
|
||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn q(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"q!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"q!"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn wq(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||
self.cmd("save_file", .{}) catch {};
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
|
|
@ -55,20 +55,20 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.flush_input();
|
||||
try self.insert_bytes(text);
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn add_keybind() void {}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -77,7 +77,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||
|
@ -290,7 +290,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
if (keypress == key.LCTRL or
|
||||
keypress == key.RCTRL or
|
||||
keypress == key.LALT or
|
||||
|
@ -403,7 +403,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||
|
@ -416,27 +416,27 @@ fn add_count(self: *Self, value: usize) void {
|
|||
self.count += value;
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.input.appendSlice(buf[0..bytes]);
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
self.input.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
try self.input.appendSlice(bytes);
|
||||
}
|
||||
|
||||
var insert_chars_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.items.len > 0) {
|
||||
defer self.input.clearRetainingCapacity();
|
||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
||||
return tp.exit_error(error.InputTargetNotFound);
|
||||
return tp.exit_error(error.InputTargetNotFound, null);
|
||||
};
|
||||
try command.execute(id, command.fmt(.{self.input.items}));
|
||||
self.last_cmd = "insert_chars";
|
||||
|
@ -610,25 +610,26 @@ const Commands = command.Collection(cmds_);
|
|||
const cmds_ = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn @"w"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn w(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
}
|
||||
|
||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn q(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"q!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"q!"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn wq(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||
self.cmd("save_file", .{}) catch {};
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
|
|
@ -55,20 +55,20 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.flush_input();
|
||||
try self.insert_bytes(text);
|
||||
try self.flush_input();
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn add_keybind() void {}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -77,7 +77,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||
|
@ -288,7 +288,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
if (keypress == key.LCTRL or
|
||||
keypress == key.RCTRL or
|
||||
keypress == key.LALT or
|
||||
|
@ -363,7 +363,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||
|
@ -376,27 +376,27 @@ fn add_count(self: *Self, value: usize) void {
|
|||
self.count += value;
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.input.appendSlice(buf[0..bytes]);
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.items.len + 4 > input_buffer_size)
|
||||
try self.flush_input();
|
||||
self.input.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
try self.input.appendSlice(bytes);
|
||||
}
|
||||
|
||||
var insert_chars_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.items.len > 0) {
|
||||
defer self.input.clearRetainingCapacity();
|
||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
||||
return tp.exit_error(error.InputTargetNotFound);
|
||||
return tp.exit_error(error.InputTargetNotFound, null);
|
||||
};
|
||||
try command.execute(id, command.fmt(.{self.input.items}));
|
||||
self.last_cmd = "insert_chars";
|
||||
|
@ -570,25 +570,26 @@ const Commands = command.Collection(cmds_);
|
|||
const cmds_ = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn @"w"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"w"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
}
|
||||
|
||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"q"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"q!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"q!"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"wq"(self: *Self, _: Ctx) Result {
|
||||
try self.cmd("save_file", .{});
|
||||
try self.cmd("quit", .{});
|
||||
}
|
||||
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
||||
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||
self.cmd("save_file", .{}) catch {};
|
||||
try self.cmd("quit_without_saving", .{});
|
||||
}
|
||||
|
|
|
@ -74,16 +74,16 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
}
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
self.flush_input() catch |e| return e;
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.insert_bytes(text);
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
switch (evtype) {
|
||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => try self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -92,7 +92,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
}
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
return switch (modifiers) {
|
||||
mod.CTRL => switch (keynormal) {
|
||||
|
@ -150,7 +150,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_fast_scroll", .{}),
|
||||
|
@ -158,14 +158,14 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.len + 16 > self.buf.len)
|
||||
try self.flush_input();
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.input = self.buf[0 .. self.input.len + bytes];
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.len + 16 > self.buf.len)
|
||||
try self.flush_input();
|
||||
const newlen = self.input.len + bytes.len;
|
||||
|
@ -175,7 +175,7 @@ fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
|||
|
||||
var find_cmd_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.len > 0) {
|
||||
if (eql(u8, self.input, self.last_input))
|
||||
return;
|
||||
|
|
|
@ -73,16 +73,16 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
}
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{"F"})) {
|
||||
self.flush_input() catch |e| return e;
|
||||
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.insert_bytes(text);
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
switch (evtype) {
|
||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => try self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -91,7 +91,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
}
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
return switch (modifiers) {
|
||||
mod.CTRL => switch (keynormal) {
|
||||
|
@ -147,7 +147,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||
key.LALT, key.RALT => self.cmd("disable_fast_scroll", .{}),
|
||||
|
@ -155,14 +155,14 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
if (self.input.len + 16 > self.buf.len)
|
||||
try self.flush_input();
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]);
|
||||
self.input = self.buf[0 .. self.input.len + bytes];
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
if (self.input.len + 16 > self.buf.len)
|
||||
try self.flush_input();
|
||||
const newlen = self.input.len + bytes.len;
|
||||
|
@ -172,7 +172,7 @@ fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
|||
|
||||
var find_cmd_id: ?command.ID = null;
|
||||
|
||||
fn flush_input(self: *Self) tp.result {
|
||||
fn flush_input(self: *Self) !void {
|
||||
if (self.input.len > 0) {
|
||||
if (eql(u8, self.input, self.last_input))
|
||||
return;
|
||||
|
|
|
@ -65,12 +65,12 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
}
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
switch (evtype) {
|
||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => try self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -79,7 +79,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
}
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
return switch (modifiers) {
|
||||
mod.CTRL => switch (keynormal) {
|
||||
|
@ -121,16 +121,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(_: *Self, _: u32, _: u32, _: u32) tp.result {}
|
||||
fn mapRelease(_: *Self, _: u32, _: u32, _: u32) !void {}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
var buf: [32]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.file_path.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.file_path.appendSlice(buf[0..bytes]);
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
self.file_path.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
try self.file_path.appendSlice(bytes);
|
||||
}
|
||||
|
||||
fn cmd(_: *Self, name_: []const u8, ctx: command.Context) tp.result {
|
||||
|
|
|
@ -170,7 +170,7 @@ fn menu_action_execute_command(menu: **Menu.State(*Self), button: *Button.State(
|
|||
|
||||
fn on_scroll(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!void {
|
||||
if (try m.match(.{ "scroll_to", tp.extract(&self.view_pos) })) {
|
||||
try self.start_query();
|
||||
self.start_query() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,14 +186,14 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.insert_bytes(text);
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -202,7 +202,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
return switch (modifiers) {
|
||||
mod.CTRL => switch (keynormal) {
|
||||
|
@ -267,14 +267,14 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("command_palette_menu_activate", .{}),
|
||||
else => {},
|
||||
};
|
||||
}
|
||||
|
||||
fn start_query(self: *Self) tp.result {
|
||||
fn start_query(self: *Self) !void {
|
||||
self.items = 0;
|
||||
self.menu.reset_items();
|
||||
self.menu.selected = null;
|
||||
|
@ -289,10 +289,10 @@ fn start_query(self: *Self) tp.result {
|
|||
defer pos += 1;
|
||||
if (pos < self.view_pos) continue;
|
||||
if (self.items < self.view_rows)
|
||||
self.add_item(cmd_.name, cmd_.id, null) catch |e| return tp.exit_error(e);
|
||||
try self.add_item(cmd_.name, cmd_.id, null);
|
||||
}
|
||||
} else {
|
||||
_ = self.query_commands(self.inputbox.text.items) catch |e| return tp.exit_error(e);
|
||||
_ = try self.query_commands(self.inputbox.text.items);
|
||||
}
|
||||
self.menu.select_down();
|
||||
self.do_resize();
|
||||
|
@ -360,7 +360,7 @@ fn add_item(self: *Self, name: []const u8, id: command.ID, matches: ?[]const usi
|
|||
self.items += 1;
|
||||
}
|
||||
|
||||
fn delete_word(self: *Self) tp.result {
|
||||
fn delete_word(self: *Self) !void {
|
||||
if (std.mem.lastIndexOfAny(u8, self.inputbox.text.items, "/\\. -_")) |pos| {
|
||||
self.inputbox.text.shrinkRetainingCapacity(pos);
|
||||
} else {
|
||||
|
@ -371,7 +371,7 @@ fn delete_word(self: *Self) tp.result {
|
|||
return self.start_query();
|
||||
}
|
||||
|
||||
fn delete_code_point(self: *Self) tp.result {
|
||||
fn delete_code_point(self: *Self) !void {
|
||||
if (self.inputbox.text.items.len > 0) {
|
||||
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
|
@ -380,17 +380,17 @@ fn delete_code_point(self: *Self) tp.result {
|
|||
return self.start_query();
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.inputbox.text.appendSlice(buf[0..bytes]);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
self.inputbox.text.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
try self.inputbox.text.appendSlice(bytes);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
self.view_pos = 0;
|
||||
return self.start_query();
|
||||
|
@ -476,8 +476,9 @@ fn restore_state(self: *Self) !void {
|
|||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn command_palette_menu_down(self: *Self, _: Ctx) tp.result {
|
||||
pub fn command_palette_menu_down(self: *Self, _: Ctx) Result {
|
||||
if (self.menu.selected) |selected| {
|
||||
if (selected == self.view_rows - 1) {
|
||||
self.view_pos += 1;
|
||||
|
@ -489,7 +490,7 @@ const cmds = struct {
|
|||
self.menu.select_down();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_up(self: *Self, _: Ctx) tp.result {
|
||||
pub fn command_palette_menu_up(self: *Self, _: Ctx) Result {
|
||||
if (self.menu.selected) |selected| {
|
||||
if (selected == 0 and self.view_pos > 0) {
|
||||
self.view_pos -= 1;
|
||||
|
@ -501,7 +502,7 @@ const cmds = struct {
|
|||
self.menu.select_up();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_pagedown(self: *Self, _: Ctx) tp.result {
|
||||
pub fn command_palette_menu_pagedown(self: *Self, _: Ctx) Result {
|
||||
if (self.total_items > self.view_rows) {
|
||||
self.view_pos += self.view_rows;
|
||||
if (self.view_pos > self.total_items - self.view_rows)
|
||||
|
@ -511,14 +512,14 @@ const cmds = struct {
|
|||
self.menu.select_last();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_pageup(self: *Self, _: Ctx) tp.result {
|
||||
pub fn command_palette_menu_pageup(self: *Self, _: Ctx) Result {
|
||||
if (self.view_pos > self.view_rows)
|
||||
self.view_pos -= self.view_rows;
|
||||
try self.start_query();
|
||||
self.menu.select_first();
|
||||
}
|
||||
|
||||
pub fn command_palette_menu_activate(self: *Self, _: Ctx) tp.result {
|
||||
pub fn command_palette_menu_activate(self: *Self, _: Ctx) Result {
|
||||
self.menu.activate_selected();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -150,20 +150,20 @@ fn add_item(self: *Self, file_name: []const u8, matches: ?[]const u8) !void {
|
|||
|
||||
fn receive_project_manager(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
if (try m.match(.{ "PRJ", tp.more })) {
|
||||
try self.process_project_manager(m);
|
||||
self.process_project_manager(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn process_project_manager(self: *Self, m: tp.message) tp.result {
|
||||
fn process_project_manager(self: *Self, m: tp.message) !void {
|
||||
var file_name: []const u8 = undefined;
|
||||
var matches: []const u8 = undefined;
|
||||
var query: []const u8 = undefined;
|
||||
if (try m.match(.{ "PRJ", "recent", tp.extract(&file_name), tp.extract_cbor(&matches) })) {
|
||||
if (self.need_reset) self.reset_results();
|
||||
self.longest = @max(self.longest, file_name.len);
|
||||
self.add_item(file_name, matches) catch |e| return tp.exit_error(e);
|
||||
try self.add_item(file_name, matches);
|
||||
self.menu.resize(.{ .y = 0, .x = 25, .w = @min(self.longest, max_menu_width) + 2 });
|
||||
if (self.need_select_first) {
|
||||
self.menu.select_down();
|
||||
|
@ -173,7 +173,7 @@ fn process_project_manager(self: *Self, m: tp.message) tp.result {
|
|||
} else if (try m.match(.{ "PRJ", "recent", tp.extract(&file_name) })) {
|
||||
if (self.need_reset) self.reset_results();
|
||||
self.longest = @max(self.longest, file_name.len);
|
||||
self.add_item(file_name, null) catch |e| return tp.exit_error(e);
|
||||
try self.add_item(file_name, null);
|
||||
self.menu.resize(.{ .y = 0, .x = 25, .w = @min(self.longest, max_menu_width) + 2 });
|
||||
if (self.need_select_first) {
|
||||
self.menu.select_down();
|
||||
|
@ -198,14 +198,14 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
var text: []const u8 = undefined;
|
||||
|
||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
||||
try self.mapEvent(evtype, keypress, egc, modifiers);
|
||||
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.insert_bytes(text);
|
||||
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
return switch (evtype) {
|
||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
|
||||
|
@ -214,7 +214,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
|
|||
};
|
||||
}
|
||||
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
||||
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||
return switch (modifiers) {
|
||||
mod.CTRL => switch (keynormal) {
|
||||
|
@ -271,7 +271,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
|
|||
};
|
||||
}
|
||||
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32) tp.result {
|
||||
fn mapRelease(self: *Self, keypress: u32, _: u32) !void {
|
||||
return switch (keypress) {
|
||||
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("open_recent_menu_activate", .{}),
|
||||
else => {},
|
||||
|
@ -285,13 +285,13 @@ fn reset_results(self: *Self) void {
|
|||
self.need_select_first = true;
|
||||
}
|
||||
|
||||
fn start_query(self: *Self) tp.result {
|
||||
fn start_query(self: *Self) !void {
|
||||
if (self.query_pending) return;
|
||||
self.query_pending = true;
|
||||
try project_manager.query_recent_files(max_recent_files, self.inputbox.text.items);
|
||||
}
|
||||
|
||||
fn delete_word(self: *Self) tp.result {
|
||||
fn delete_word(self: *Self) !void {
|
||||
if (std.mem.lastIndexOfAny(u8, self.inputbox.text.items, "/\\. -_")) |pos| {
|
||||
self.inputbox.text.shrinkRetainingCapacity(pos);
|
||||
} else {
|
||||
|
@ -301,7 +301,7 @@ fn delete_word(self: *Self) tp.result {
|
|||
return self.start_query();
|
||||
}
|
||||
|
||||
fn delete_code_point(self: *Self) tp.result {
|
||||
fn delete_code_point(self: *Self) !void {
|
||||
if (self.inputbox.text.items.len > 0) {
|
||||
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
|
@ -309,16 +309,16 @@ fn delete_code_point(self: *Self) tp.result {
|
|||
return self.start_query();
|
||||
}
|
||||
|
||||
fn insert_code_point(self: *Self, c: u32) tp.result {
|
||||
fn insert_code_point(self: *Self, c: u32) !void {
|
||||
var buf: [6]u8 = undefined;
|
||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
||||
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
||||
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||
try self.inputbox.text.appendSlice(buf[0..bytes]);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
return self.start_query();
|
||||
}
|
||||
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
||||
self.inputbox.text.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
||||
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||
try self.inputbox.text.appendSlice(bytes);
|
||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||
return self.start_query();
|
||||
}
|
||||
|
@ -339,16 +339,17 @@ const Commands = command.Collection(cmds);
|
|||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn open_recent_menu_down(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_recent_menu_down(self: *Self, _: Ctx) Result {
|
||||
self.menu.select_down();
|
||||
}
|
||||
|
||||
pub fn open_recent_menu_up(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_recent_menu_up(self: *Self, _: Ctx) Result {
|
||||
self.menu.select_up();
|
||||
}
|
||||
|
||||
pub fn open_recent_menu_activate(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_recent_menu_activate(self: *Self, _: Ctx) Result {
|
||||
self.menu.activate_selected();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -71,8 +71,8 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
|||
fn receive_log(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
var clear_msg_num: usize = 0;
|
||||
if (try m.match(.{ "log", tp.more })) {
|
||||
logview.process_log(m) catch |e| return tp.exit_error(e);
|
||||
self.process_log(m) catch |e| return tp.exit_error(e);
|
||||
logview.process_log(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
self.process_log(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
return true;
|
||||
} else if (try m.match(.{ "MINILOG", tp.extract(&clear_msg_num) })) {
|
||||
if (clear_msg_num == self.msg_counter)
|
||||
|
|
103
src/tui/tui.zig
103
src/tui/tui.zig
|
@ -72,7 +72,7 @@ pub fn spawn(a: Allocator, ctx: *tp.context, eh: anytype, env: ?*const tp.env) !
|
|||
|
||||
fn start(args: StartArgs) tp.result {
|
||||
_ = tp.set_trap(true);
|
||||
var self = init(args.a) catch |e| return tp.exit_error(e);
|
||||
var self = init(args.a) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
errdefer self.deinit();
|
||||
tp.receive(&self.receiver);
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ fn init(a: Allocator) !*Self {
|
|||
return self;
|
||||
}
|
||||
|
||||
fn init_delayed(self: *Self) tp.result {
|
||||
fn init_delayed(self: *Self) !void {
|
||||
if (self.input_mode) |_| {} else return cmds.enter_mode(self, command.Context.fmt(.{self.config.input_mode}));
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ fn deinit(self: *Self) void {
|
|||
|
||||
fn listen_sigwinch(self: *Self) tp.result {
|
||||
if (self.sigwinch_signal) |old| old.deinit();
|
||||
self.sigwinch_signal = tp.signal.init(std.posix.SIG.WINCH, tp.message.fmt(.{"sigwinch"})) catch |e| return tp.exit_error(e);
|
||||
self.sigwinch_signal = tp.signal.init(std.posix.SIG.WINCH, tp.message.fmt(.{"sigwinch"})) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
|
||||
fn receive(self: *Self, from: tp.pid_ref, m: tp.message) tp.result {
|
||||
|
@ -183,18 +183,18 @@ fn receive(self: *Self, from: tp.pid_ref, m: tp.message) tp.result {
|
|||
|
||||
self.receive_safe(from, m) catch |e| {
|
||||
if (std.mem.eql(u8, "normal", tp.error_text()))
|
||||
return e;
|
||||
return error.Exit;
|
||||
if (std.mem.eql(u8, "restart", tp.error_text()))
|
||||
return e;
|
||||
self.logger.err("UI", e);
|
||||
return error.Exit;
|
||||
self.logger.err("UI", tp.exit_error(e, @errorReturnTrace()));
|
||||
};
|
||||
}
|
||||
|
||||
fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) tp.result {
|
||||
fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
|
||||
var input: []const u8 = undefined;
|
||||
var text: []const u8 = undefined;
|
||||
if (try m.match(.{ "VXS", tp.extract(&input), tp.extract(&text) })) {
|
||||
self.rdr.process_input_event(input, if (text.len > 0) text else null) catch |e| return tp.exit_error(e);
|
||||
try self.rdr.process_input_event(input, if (text.len > 0) text else null);
|
||||
try self.dispatch_flush_input_event();
|
||||
if (self.unrendered_input_events_count > 0 and !self.frame_clock_running)
|
||||
need_render();
|
||||
|
@ -355,10 +355,10 @@ fn render(self: *Self) void {
|
|||
}
|
||||
}
|
||||
|
||||
fn dispatch_flush_input_event(self: *Self) tp.result {
|
||||
fn dispatch_flush_input_event(self: *Self) !void {
|
||||
var buf: [32]u8 = undefined;
|
||||
if (self.input_mode) |mode|
|
||||
try mode.handler.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{"F"}) catch |e| return tp.exit_error(e));
|
||||
try mode.handler.send(tp.self_pid(), try tp.message.fmtbuf(&buf, .{"F"}));
|
||||
}
|
||||
|
||||
fn dispatch_input(ctx: *anyopaque, cbor_msg: []const u8) void {
|
||||
|
@ -383,10 +383,8 @@ fn dispatch_mouse(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) voi
|
|||
const m: tp.message = .{ .buf = cbor_msg };
|
||||
const from = tp.self_pid();
|
||||
self.unrendered_input_events_count += 1;
|
||||
if (self.drag_source) |_|
|
||||
self.send_mouse_drag(y, x, from, m) catch |e| self.logger.err("dispatch mouse", e)
|
||||
else
|
||||
self.send_mouse(y, x, from, m) catch |e| self.logger.err("dispatch mouse", e);
|
||||
const send_func = if (self.drag_source) |_| &send_mouse_drag else &send_mouse;
|
||||
send_func(self, y, x, from, m) catch |e| self.logger.err("dispatch mouse", e);
|
||||
self.drag_source = null;
|
||||
}
|
||||
|
||||
|
@ -462,16 +460,16 @@ fn send_mouse(self: *Self, y: c_int, x: c_int, from: tp.pid_ref, m: tp.message)
|
|||
var buf: [256]u8 = undefined;
|
||||
if (self.hover_focus) |h| {
|
||||
if (self.is_live_widget_ptr(h))
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e));
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
self.hover_focus = w;
|
||||
_ = try w.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", true }) catch |e| return tp.exit_error(e));
|
||||
_ = try w.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", true }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
_ = try w.send(from, m);
|
||||
} else {
|
||||
if (self.hover_focus) |h| {
|
||||
var buf: [256]u8 = undefined;
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e));
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
self.hover_focus = null;
|
||||
}
|
||||
|
@ -488,15 +486,15 @@ fn send_mouse_drag(self: *Self, y: c_int, x: c_int, from: tp.pid_ref, m: tp.mess
|
|||
var buf: [256]u8 = undefined;
|
||||
if (self.hover_focus) |h| {
|
||||
if (self.is_live_widget_ptr(h))
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e));
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
self.hover_focus = w;
|
||||
_ = try w.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", true }) catch |e| return tp.exit_error(e));
|
||||
_ = try w.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", true }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
} else {
|
||||
if (self.hover_focus) |h| {
|
||||
var buf: [256]u8 = undefined;
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e));
|
||||
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
|
||||
}
|
||||
self.hover_focus = null;
|
||||
}
|
||||
|
@ -510,83 +508,84 @@ pub fn save_config(self: *const Self) !void {
|
|||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
const Result = command.Result;
|
||||
|
||||
pub fn restart(_: *Self, _: Ctx) tp.result {
|
||||
pub fn restart(_: *Self, _: Ctx) Result {
|
||||
try tp.self_pid().send("restart");
|
||||
}
|
||||
|
||||
pub fn theme_next(self: *Self, _: Ctx) tp.result {
|
||||
pub fn theme_next(self: *Self, _: Ctx) Result {
|
||||
self.theme = get_next_theme_by_name(self.theme.name);
|
||||
self.config.theme = self.theme.name;
|
||||
self.logger.print("theme: {s}", .{self.theme.description});
|
||||
self.save_config() catch |e| return tp.exit_error(e);
|
||||
try self.save_config();
|
||||
}
|
||||
|
||||
pub fn theme_prev(self: *Self, _: Ctx) tp.result {
|
||||
pub fn theme_prev(self: *Self, _: Ctx) Result {
|
||||
self.theme = get_prev_theme_by_name(self.theme.name);
|
||||
self.config.theme = self.theme.name;
|
||||
self.logger.print("theme: {s}", .{self.theme.description});
|
||||
self.save_config() catch |e| return tp.exit_error(e);
|
||||
try self.save_config();
|
||||
}
|
||||
|
||||
pub fn toggle_whitespace(self: *Self, _: Ctx) tp.result {
|
||||
pub fn toggle_whitespace(self: *Self, _: Ctx) Result {
|
||||
self.config.show_whitespace = !self.config.show_whitespace;
|
||||
self.logger.print("show_whitspace {s}", .{if (self.config.show_whitespace) "enabled" else "disabled"});
|
||||
self.save_config() catch |e| return tp.exit_error(e);
|
||||
try self.save_config();
|
||||
var buf: [32]u8 = undefined;
|
||||
const m = tp.message.fmtbuf(&buf, .{ "show_whitespace", self.config.show_whitespace }) catch |e| return tp.exit_error(e);
|
||||
const m = try tp.message.fmtbuf(&buf, .{ "show_whitespace", self.config.show_whitespace });
|
||||
_ = try self.send_widgets(tp.self_pid(), m);
|
||||
}
|
||||
|
||||
pub fn toggle_input_mode(self: *Self, _: Ctx) tp.result {
|
||||
pub fn toggle_input_mode(self: *Self, _: Ctx) Result {
|
||||
self.config.input_mode = if (std.mem.eql(u8, self.config.input_mode, "flow")) "vim/normal" else "flow";
|
||||
self.save_config() catch |e| return tp.exit_error(e);
|
||||
try self.save_config();
|
||||
return enter_mode(self, Ctx.fmt(.{self.config.input_mode}));
|
||||
}
|
||||
|
||||
pub fn enter_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_mode(self: *Self, ctx: Ctx) Result {
|
||||
var mode: []const u8 = undefined;
|
||||
if (!try ctx.args.match(.{tp.extract(&mode)}))
|
||||
return tp.exit_error(error.InvalidArgument);
|
||||
return tp.exit_error(error.InvalidArgument, null);
|
||||
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||
if (self.input_mode) |*m| m.deinit();
|
||||
self.input_mode = if (std.mem.eql(u8, mode, "vim/normal"))
|
||||
@import("mode/input/vim/normal.zig").create(self.a) catch |e| return tp.exit_error(e)
|
||||
try @import("mode/input/vim/normal.zig").create(self.a)
|
||||
else if (std.mem.eql(u8, mode, "vim/insert"))
|
||||
@import("mode/input/vim/insert.zig").create(self.a) catch |e| return tp.exit_error(e)
|
||||
try @import("mode/input/vim/insert.zig").create(self.a)
|
||||
else if (std.mem.eql(u8, mode, "vim/visual"))
|
||||
@import("mode/input/vim/visual.zig").create(self.a) catch |e| return tp.exit_error(e)
|
||||
try @import("mode/input/vim/visual.zig").create(self.a)
|
||||
else if (std.mem.eql(u8, mode, "flow"))
|
||||
@import("mode/input/flow.zig").create(self.a) catch |e| return tp.exit_error(e)
|
||||
try @import("mode/input/flow.zig").create(self.a)
|
||||
else if (std.mem.eql(u8, mode, "home"))
|
||||
@import("mode/input/home.zig").create(self.a) catch |e| return tp.exit_error(e)
|
||||
try @import("mode/input/home.zig").create(self.a)
|
||||
else ret: {
|
||||
self.logger.print("unknown mode {s}", .{mode});
|
||||
break :ret @import("mode/input/flow.zig").create(self.a) catch |e| return tp.exit_error(e);
|
||||
break :ret try @import("mode/input/flow.zig").create(self.a);
|
||||
};
|
||||
// self.logger.print("input mode: {s}", .{(self.input_mode orelse return).description});
|
||||
}
|
||||
|
||||
pub fn enter_mode_default(self: *Self, _: Ctx) tp.result {
|
||||
pub fn enter_mode_default(self: *Self, _: Ctx) Result {
|
||||
return enter_mode(self, Ctx.fmt(.{self.config.input_mode}));
|
||||
}
|
||||
|
||||
pub fn open_command_palette(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_command_palette(self: *Self, _: Ctx) Result {
|
||||
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||
self.input_mode_outer = self.input_mode;
|
||||
self.input_mode = @import("mode/overlay/command_palette.zig").create(self.a) catch |e| return tp.exit_error(e);
|
||||
self.input_mode = try @import("mode/overlay/command_palette.zig").create(self.a);
|
||||
}
|
||||
|
||||
pub fn open_recent(self: *Self, _: Ctx) tp.result {
|
||||
pub fn open_recent(self: *Self, _: Ctx) Result {
|
||||
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||
self.input_mode_outer = self.input_mode;
|
||||
self.input_mode = @import("mode/overlay/open_recent.zig").create(self.a) catch |e| return tp.exit_error(e);
|
||||
self.input_mode = try @import("mode/overlay/open_recent.zig").create(self.a);
|
||||
}
|
||||
|
||||
pub fn exit_overlay_mode(self: *Self, _: Ctx) tp.result {
|
||||
pub fn exit_overlay_mode(self: *Self, _: Ctx) Result {
|
||||
if (self.input_mode_outer == null) return;
|
||||
defer {
|
||||
self.input_mode = self.input_mode_outer;
|
||||
|
@ -595,29 +594,29 @@ const cmds = struct {
|
|||
if (self.input_mode) |*mode| mode.deinit();
|
||||
}
|
||||
|
||||
pub fn enter_find_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_find_mode(self: *Self, ctx: Ctx) Result {
|
||||
return enter_mini_mode(self, @import("mode/mini/find.zig"), ctx);
|
||||
}
|
||||
|
||||
pub fn enter_find_in_files_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_find_in_files_mode(self: *Self, ctx: Ctx) Result {
|
||||
return enter_mini_mode(self, @import("mode/mini/find_in_files.zig"), ctx);
|
||||
}
|
||||
|
||||
pub fn enter_goto_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_goto_mode(self: *Self, ctx: Ctx) Result {
|
||||
return enter_mini_mode(self, @import("mode/mini/goto.zig"), ctx);
|
||||
}
|
||||
|
||||
pub fn enter_move_to_char_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_move_to_char_mode(self: *Self, ctx: Ctx) Result {
|
||||
return enter_mini_mode(self, @import("mode/mini/move_to_char.zig"), ctx);
|
||||
}
|
||||
|
||||
pub fn enter_open_file_mode(self: *Self, ctx: Ctx) tp.result {
|
||||
pub fn enter_open_file_mode(self: *Self, ctx: Ctx) Result {
|
||||
return enter_mini_mode(self, @import("mode/mini/open_file.zig"), ctx);
|
||||
}
|
||||
|
||||
const MiniModeFactory = fn (Allocator, Ctx) error{ NotFound, OutOfMemory }!EventHandler;
|
||||
|
||||
fn enter_mini_mode(self: *Self, comptime mode: anytype, ctx: Ctx) tp.result {
|
||||
fn enter_mini_mode(self: *Self, comptime mode: anytype, ctx: Ctx) Result {
|
||||
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||
self.input_mode_outer = self.input_mode;
|
||||
|
@ -626,7 +625,7 @@ const cmds = struct {
|
|||
self.input_mode_outer = null;
|
||||
self.mini_mode = null;
|
||||
}
|
||||
const mode_instance = mode.create(self.a, ctx) catch |e| return tp.exit_error(e);
|
||||
const mode_instance = try mode.create(self.a, ctx);
|
||||
self.input_mode = .{
|
||||
.handler = mode_instance.handler(),
|
||||
.name = mode_instance.name(),
|
||||
|
@ -635,7 +634,7 @@ const cmds = struct {
|
|||
self.mini_mode = .{};
|
||||
}
|
||||
|
||||
pub fn exit_mini_mode(self: *Self, _: Ctx) tp.result {
|
||||
pub fn exit_mini_mode(self: *Self, _: Ctx) Result {
|
||||
if (self.mini_mode) |_| {} else return;
|
||||
defer {
|
||||
self.input_mode = self.input_mode_outer;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue