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",
|
.hash = "1220220dbc7fe91c1c54438193ca765cebbcb7d58f35cdcaee404a9d2245a42a4362",
|
||||||
},
|
},
|
||||||
.thespian = .{
|
.thespian = .{
|
||||||
.url = "https://github.com/neurocyte/thespian/archive/3ace3163087a0260b30e2c420de76235dd82451f.tar.gz",
|
.url = "https://github.com/neurocyte/thespian/archive/f1a89bdf9d9fac2cd7d6c1479e5bc99c8dd4c904.tar.gz",
|
||||||
.hash = "1220ffbfff37c24b68424a3c9223cf57daed5debdbb6b7751a36b9dca318825cff4c",
|
.hash = "1220f1f69aaad041ca96e5a06fb14ff510c3775d809a37a83b8651e7f0f71be8deaf",
|
||||||
},
|
},
|
||||||
.themes = .{
|
.themes = .{
|
||||||
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-15e8cad1619429bf2547a6819b5b999510d5c1e5/flow-themes.tar.gz",
|
.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 module_name = @typeName(Self);
|
||||||
const sp_tag = "child";
|
const sp_tag = "child";
|
||||||
const debug_lsp = true;
|
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) };
|
return .{ .a = a, .pid = try Process.create(a, project, cmd) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,23 +26,23 @@ pub fn term(self: *Self) void {
|
||||||
self.pid.deinit();
|
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" });
|
// const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".send_request" });
|
||||||
// defer frame.deinit();
|
// defer frame.deinit();
|
||||||
var cb = std.ArrayList(u8).init(self.a);
|
var cb = std.ArrayList(u8).init(self.a);
|
||||||
defer cb.deinit();
|
defer cb.deinit();
|
||||||
cbor.writeValue(cb.writer(), m) 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 }) catch |e| return tp.exit_error(e);
|
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);
|
var cb = std.ArrayList(u8).init(self.a);
|
||||||
defer cb.deinit();
|
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);
|
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 });
|
return self.pid.send(.{ "NTFY", method, cb });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ const Process = struct {
|
||||||
|
|
||||||
const Receiver = tp.Receiver(*Process);
|
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;
|
var tag: []const u8 = undefined;
|
||||||
if (try cmd.match(.{tp.extract(&tag)})) {
|
if (try cmd.match(.{tp.extract(&tag)})) {
|
||||||
//
|
//
|
||||||
|
@ -92,7 +91,7 @@ const Process = struct {
|
||||||
.requests = std.AutoHashMap(i32, tp.pid).init(a),
|
.requests = std.AutoHashMap(i32, tp.pid).init(a),
|
||||||
.sp_tag = try sp_tag_.toOwnedSliceSentinel(0),
|
.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 {
|
fn deinit(self: *Process) void {
|
||||||
|
@ -126,17 +125,21 @@ const Process = struct {
|
||||||
const frame = tracy.initZone(@src(), .{ .name = module_name ++ " start" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ " start" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
_ = tp.set_trap(true);
|
_ = 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);
|
tp.receive(&self.receiver);
|
||||||
|
|
||||||
var log_file_path = std.ArrayList(u8).init(self.a);
|
var log_file_path = std.ArrayList(u8).init(self.a);
|
||||||
defer log_file_path.deinit();
|
defer log_file_path.deinit();
|
||||||
const state_dir = root.get_state_dir() 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);
|
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);
|
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 {
|
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 });
|
const frame = tracy.initZone(@src(), .{ .name = module_name });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
errdefer self.deinit();
|
errdefer self.deinit();
|
||||||
|
@ -146,9 +149,9 @@ const Process = struct {
|
||||||
var code: u32 = 0;
|
var code: u32 = 0;
|
||||||
|
|
||||||
if (try m.match(.{ "REQ", tp.extract(&method), tp.extract(&bytes) })) {
|
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) })) {
|
} 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"})) {
|
} else if (try m.match(.{"close"})) {
|
||||||
self.write_log("### LSP close ###\n", .{});
|
self.write_log("### LSP close ###\n", .{});
|
||||||
try self.close();
|
try self.close();
|
||||||
|
@ -156,9 +159,9 @@ const Process = struct {
|
||||||
self.write_log("### LSP terminated ###\n", .{});
|
self.write_log("### LSP terminated ###\n", .{});
|
||||||
try self.term();
|
try self.term();
|
||||||
} else if (try m.match(.{ self.sp_tag, "stdout", tp.extract(&bytes) })) {
|
} 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) })) {
|
} 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) })) {
|
} else if (try m.match(.{ self.sp_tag, "stderr", tp.extract(&bytes) })) {
|
||||||
self.write_log("{s}\n", .{bytes});
|
self.write_log("{s}\n", .{bytes});
|
||||||
} else if (try m.match(.{ "exit", "normal" })) {
|
} 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;
|
var i: usize = 0;
|
||||||
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
||||||
for (self.files.items) |file| {
|
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);
|
return self.simple_query_recent_files(from, max, query);
|
||||||
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
defer from.send(.{ "PRJ", "recent_done", query }) catch {};
|
||||||
|
|
||||||
var searcher = try fuzzig.Ascii.init(
|
var searcher = fuzzig.Ascii.init(
|
||||||
self.a,
|
self.a,
|
||||||
std.fs.max_path_bytes, // haystack max size
|
std.fs.max_path_bytes, // haystack max size
|
||||||
std.fs.max_path_bytes, // needle max size
|
std.fs.max_path_bytes, // needle max size
|
||||||
.{ .case_sensitive = false },
|
.{ .case_sensitive = false },
|
||||||
);
|
) catch |e| switch (e) {
|
||||||
|
error.OutOfMemory => @panic("OOM in fussiz.Ascii.init"),
|
||||||
|
else => |e_| return e_,
|
||||||
|
};
|
||||||
defer searcher.deinit();
|
defer searcher.deinit();
|
||||||
|
|
||||||
const Match = struct {
|
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 {};
|
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)) {
|
if (!self.file_language_server.contains(file_path)) {
|
||||||
const key = self.a.dupe(u8, file_path) catch |e| return tp.exit_error(e);
|
const key = try self.a.dupe(u8, file_path);
|
||||||
self.file_language_server.put(key, lsp) catch |e| return tp.exit_error(e);
|
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);
|
defer self.a.free(uri);
|
||||||
try lsp.send_notification("textDocument/didOpen", .{
|
try lsp.send_notification("textDocument/didOpen", .{
|
||||||
.textDocument = .{ .uri = uri, .languageId = file_type, .version = version, .text = text },
|
.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 {
|
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 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);
|
defer self.a.free(uri);
|
||||||
|
|
||||||
const root_dst: Buffer.Root = if (root_dst_addr == 0) return else @ptrFromInt(root_dst_addr);
|
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 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);
|
defer self.a.free(uri);
|
||||||
try lsp.send_notification("textDocument/didSave", .{
|
try lsp.send_notification("textDocument/didSave", .{
|
||||||
.textDocument = .{ .uri = uri },
|
.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 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);
|
defer self.a.free(uri);
|
||||||
try lsp.send_notification("textDocument/didClose", .{
|
try lsp.send_notification("textDocument/didClose", .{
|
||||||
.textDocument = .{ .uri = uri },
|
.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 {
|
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 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);
|
defer self.a.free(uri);
|
||||||
const response = try lsp.send_request(self.a, "textDocument/definition", .{
|
const response = try lsp.send_request(self.a, "textDocument/definition", .{
|
||||||
.textDocument = .{ .uri = uri },
|
.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 {
|
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 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);
|
defer self.a.free(uri);
|
||||||
const response = try lsp.send_request(self.a, "textDocument/completion", .{
|
const response = try lsp.send_request(self.a, "textDocument/completion", .{
|
||||||
.textDocument = .{ .uri = uri },
|
.textDocument = .{ .uri = uri },
|
||||||
|
@ -613,7 +616,7 @@ pub fn show_message(_: *Self, _: tp.pid_ref, params_cb: []const u8) !void {
|
||||||
logger.print("{s}", .{msg});
|
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", .{
|
return lsp.send_request(self.a, "initialize", .{
|
||||||
.processId = if (builtin.os.tag == .linux) std.os.linux.getpid() else null,
|
.processId = if (builtin.os.tag == .linux) std.os.linux.getpid() else null,
|
||||||
.rootPath = project_path,
|
.rootPath = project_path,
|
||||||
|
|
|
@ -7,7 +7,6 @@ const cbor = @import("cbor");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const module_name = @typeName(Self);
|
const module_name = @typeName(Self);
|
||||||
pub const Error = error{ OutOfMemory, Exit };
|
|
||||||
|
|
||||||
pub const Kind = enum { insert, delete };
|
pub const Kind = enum { insert, delete };
|
||||||
pub const Edit = struct {
|
pub const Edit = struct {
|
||||||
|
@ -19,7 +18,7 @@ pub const Edit = struct {
|
||||||
|
|
||||||
pid: ?tp.pid,
|
pid: ?tp.pid,
|
||||||
|
|
||||||
pub fn create() Error!Self {
|
pub fn create() !Self {
|
||||||
return .{ .pid = try Process.create() };
|
return .{ .pid = try Process.create() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,14 +38,14 @@ const Process = struct {
|
||||||
const Receiver = tp.Receiver(*Process);
|
const Receiver = tp.Receiver(*Process);
|
||||||
const outer_a = std.heap.page_allocator;
|
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);
|
const self = try outer_a.create(Process);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.arena = std.heap.ArenaAllocator.init(outer_a),
|
.arena = std.heap.ArenaAllocator.init(outer_a),
|
||||||
.a = self.arena.allocator(),
|
.a = self.arena.allocator(),
|
||||||
.receiver = Receiver.init(Process.receive, self),
|
.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 {
|
fn start(self: *Process) tp.result {
|
||||||
|
@ -67,7 +66,7 @@ const Process = struct {
|
||||||
var root_src: usize = 0;
|
var root_src: usize = 0;
|
||||||
|
|
||||||
return if (try m.match(.{ "D", tp.extract(&cb), tp.extract(&root_dst), tp.extract(&root_src) }))
|
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"}))
|
else if (try m.match(.{"shutdown"}))
|
||||||
tp.exit_normal();
|
tp.exit_normal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ const tp = @import("thespian");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const module_name = @typeName(Self);
|
const module_name = @typeName(Self);
|
||||||
pub const Error = error{ OutOfMemory, Exit };
|
|
||||||
|
|
||||||
pid: ?tp.pid,
|
pid: ?tp.pid,
|
||||||
|
|
||||||
|
@ -17,7 +16,7 @@ pub const Selection = struct {
|
||||||
end: Cursor = Cursor{},
|
end: Cursor = Cursor{},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create() Error!Self {
|
pub fn create() !Self {
|
||||||
return .{ .pid = try Process.create() };
|
return .{ .pid = try Process.create() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ const Process = struct {
|
||||||
selection: ?Selection = null,
|
selection: ?Selection = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create() Error!tp.pid {
|
pub fn create() !tp.pid {
|
||||||
const self = try outer_a.create(Process);
|
const self = try outer_a.create(Process);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.arena = std.heap.ArenaAllocator.init(outer_a),
|
.arena = std.heap.ArenaAllocator.init(outer_a),
|
||||||
|
@ -55,7 +54,7 @@ const Process = struct {
|
||||||
.forwards = std.ArrayList(Entry).init(self.a),
|
.forwards = std.ArrayList(Entry).init(self.a),
|
||||||
.receiver = Receiver.init(Process.receive, self),
|
.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 {
|
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 {
|
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();
|
errdefer self.deinit();
|
||||||
|
|
||||||
var c: Cursor = .{};
|
var c: Cursor = .{};
|
||||||
|
@ -106,9 +109,9 @@ const Process = struct {
|
||||||
tp.exit_normal();
|
tp.exit_normal();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(self: *Process, entry_: Entry) tp.result {
|
fn update(self: *Process, entry_: Entry) !void {
|
||||||
const entry: Entry = .{
|
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,
|
.cursor = entry_.cursor,
|
||||||
.selection = entry_.selection,
|
.selection = entry_.selection,
|
||||||
};
|
};
|
||||||
|
@ -129,7 +132,7 @@ const Process = struct {
|
||||||
self.a.free(top.file_path);
|
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 }));
|
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| {
|
} 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 }));
|
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();
|
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 {
|
fn start(args: StartArgs) tp.result {
|
||||||
_ = tp.set_trap(true);
|
_ = 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();
|
errdefer this.deinit();
|
||||||
tp.receive(&this.receiver);
|
tp.receive(&this.receiver);
|
||||||
}
|
}
|
||||||
|
@ -135,15 +135,27 @@ pub const Logger = struct {
|
||||||
error.Exit => {
|
error.Exit => {
|
||||||
const msg_: tp.message = .{ .buf = tp.error_message() };
|
const msg_: tp.message = .{ .buf = tp.error_message() };
|
||||||
var msg__: []const u8 = undefined;
|
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;
|
msg__ = msg_.buf;
|
||||||
|
}
|
||||||
if (msg__.len > buf.len) {
|
if (msg__.len > buf.len) {
|
||||||
self.proc.send(.{ "log", "error", self.tag, context, "->", "MESSAGE TOO LARGE" }) catch {};
|
self.proc.send(.{ "log", "error", self.tag, context, "->", "MESSAGE TOO LARGE" }) catch {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const msg___ = buf[0..msg__.len];
|
const msg___ = buf[0..msg__.len];
|
||||||
@memcpy(msg___, msg__);
|
@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 => {
|
else => {
|
||||||
msg = @errorName(e);
|
msg = @errorName(e);
|
||||||
|
|
|
@ -13,13 +13,13 @@ pid: tp.pid_ref,
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const module_name = @typeName(Self);
|
const module_name = @typeName(Self);
|
||||||
|
|
||||||
pub fn get() error{Exit}!Self {
|
pub fn get() !Self {
|
||||||
const pid = tp.env.get().proc(module_name);
|
const pid = tp.env.get().proc(module_name);
|
||||||
return if (pid.expired()) create() else .{ .pid = pid };
|
return if (pid.expired()) create() else .{ .pid = pid };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create() error{Exit}!Self {
|
fn create() !Self {
|
||||||
const pid = Process.create() catch |e| return tp.exit_error(e);
|
const pid = try Process.create();
|
||||||
defer pid.deinit();
|
defer pid.deinit();
|
||||||
tp.env.get().proc_set(module_name, pid.ref());
|
tp.env.get().proc_set(module_name, pid.ref());
|
||||||
return .{ .pid = tp.env.get().proc(module_name) };
|
return .{ .pid = tp.env.get().proc(module_name) };
|
||||||
|
@ -34,35 +34,35 @@ pub fn shutdown() void {
|
||||||
pid.send(.{"shutdown"}) catch {};
|
pid.send(.{"shutdown"}) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_cwd() tp.result {
|
pub fn open_cwd() !void {
|
||||||
return open(".");
|
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;
|
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
const project_directory = std.fs.cwd().realpath(rel_project_directory, &path_buf) catch "(none)";
|
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);
|
var dir = try std.fs.openDirAbsolute(project_directory, .{});
|
||||||
dir.setAsCwd() catch |e| return tp.exit_error(e);
|
try dir.setAsCwd();
|
||||||
dir.close();
|
dir.close();
|
||||||
tp.env.get().str_set("project", project_directory);
|
tp.env.get().str_set("project", project_directory);
|
||||||
return (try get()).pid.send(.{ "open", 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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "request_recent_files", project, max });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "query_recent_files", project, max, query });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
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 });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "did_change", project, file_path, version, root_dst, root_src });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "did_save", project, file_path });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "did_close", project, file_path });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "goto_definition", project, file_path, row, col });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "completion", project, file_path, row, col });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
return (try get()).pid.send(.{ "update_mru", project, file_path, row, col });
|
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");
|
const project = tp.env.get().str("project");
|
||||||
if (project.len == 0)
|
if (project.len == 0)
|
||||||
return tp.exit("No project");
|
return tp.exit("No project");
|
||||||
|
@ -140,7 +140,7 @@ const Process = struct {
|
||||||
.receiver = Receiver.init(Process.receive, self),
|
.receiver = Receiver.init(Process.receive, self),
|
||||||
.projects = ProjectsMap.init(a),
|
.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 {
|
fn deinit(self: *Process) void {
|
||||||
|
@ -166,11 +166,11 @@ const Process = struct {
|
||||||
self.receive_safe(from, m) catch |e| {
|
self.receive_safe(from, m) catch |e| {
|
||||||
if (std.mem.eql(u8, "normal", tp.error_text()))
|
if (std.mem.eql(u8, "normal", tp.error_text()))
|
||||||
return e;
|
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 project_directory: []const u8 = undefined;
|
||||||
var path: []const u8 = undefined;
|
var path: []const u8 = undefined;
|
||||||
var query: []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) })) {
|
} else if (try m.match(.{ "walk_tree_done", tp.extract(&project_directory) })) {
|
||||||
if (self.walker) |pid| pid.deinit();
|
if (self.walker) |pid| pid.deinit();
|
||||||
self.walker = null;
|
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) })) {
|
} 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) })) {
|
} 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);
|
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) })) {
|
} 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" })) {
|
} else if (try m.match(.{ "child", tp.extract(&path), "done" })) {
|
||||||
self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path});
|
self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path});
|
||||||
} else if (try m.match(.{ "open", tp.extract(&project_directory) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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 "";
|
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) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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) })) {
|
} 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"})) {
|
} else if (try m.match(.{"shutdown"})) {
|
||||||
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
|
if (self.walker) |pid| pid.send(.{"stop"}) catch {};
|
||||||
self.persist_projects();
|
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) {
|
if (self.projects.get(project_directory) == null) {
|
||||||
self.logger.print("opening: {s}", .{project_directory});
|
self.logger.print("opening: {s}", .{project_directory});
|
||||||
const project = try self.a.create(Project);
|
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 });
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_open" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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);
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_change" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_save" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||||
return project.did_save(file_path);
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".did_close" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
||||||
return project.did_close(file_path);
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".goto_definition" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".completion" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = module_name ++ ".get_mru_position" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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");
|
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;
|
_ = language_server;
|
||||||
const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project");
|
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"))
|
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"))
|
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
|
else
|
||||||
tp.exit_fmt("unsupported LSP notification: {s}", .{method});
|
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;
|
_ = self;
|
||||||
_ = project_directory;
|
_ = project_directory;
|
||||||
_ = language_server;
|
_ = 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 {
|
return struct {
|
||||||
a: std.mem.Allocator,
|
a: std.mem.Allocator,
|
||||||
root_path: []const u8,
|
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 tree_walker = @This();
|
||||||
const Receiver = tp.Receiver(*tree_walker);
|
const Receiver = tp.Receiver(*tree_walker);
|
||||||
|
|
||||||
fn spawn_link(a: std.mem.Allocator, root_path: []const u8) error{Exit}!tp.pid {
|
fn spawn_link(a: std.mem.Allocator, root_path: []const u8) !tp.pid {
|
||||||
const self = a.create(tree_walker) catch |e| return tp.exit_error(e);
|
const self = try a.create(tree_walker);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.a = a,
|
.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(),
|
.parent = tp.self_pid().clone(),
|
||||||
.receiver = Receiver.init(tree_walker.receive, self),
|
.receiver = Receiver.init(tree_walker.receive, self),
|
||||||
.dir = std.fs.cwd().openDir(self.root_path, .{ .iterate = true }) catch |e| return tp.exit_error(e),
|
.dir = try std.fs.cwd().openDir(self.root_path, .{ .iterate = true }),
|
||||||
.walker = walk_filtered(self.dir, self.a) catch |e| return tp.exit_error(e),
|
.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 {
|
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" });
|
const frame = tracy.initZone(@src(), .{ .name = "project scan" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
tp.receive(&self.receiver);
|
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 {
|
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();
|
defer frame.deinit();
|
||||||
|
|
||||||
if (try m.match(.{"next"})) {
|
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"})) {
|
} else if (try m.match(.{"stop"})) {
|
||||||
return tp.exit_normal();
|
return tp.exit_normal();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,9 +11,9 @@ stdin_behavior: std.process.Child.StdIo,
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
const module_name = @typeName(Self);
|
const module_name = @typeName(Self);
|
||||||
pub const max_chunk_size = tp.subprocess.max_chunk_size;
|
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 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;
|
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);
|
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);
|
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 };
|
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);
|
try self.input(bytes);
|
||||||
return bytes.len;
|
return bytes.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn input(self: *const Self, bytes: []const u8) tp.result {
|
pub fn input(self: *const Self, bytes: []const u8) !void {
|
||||||
const pid = if (self.pid) |pid| pid else return tp.exit_error(error.Closed);
|
const pid = if (self.pid) |pid| pid else return error.Closed;
|
||||||
var remaining = bytes;
|
var remaining = bytes;
|
||||||
while (remaining.len > 0)
|
while (remaining.len > 0)
|
||||||
remaining = loop: {
|
remaining = loop: {
|
||||||
|
@ -83,7 +83,7 @@ const Process = struct {
|
||||||
|
|
||||||
const Receiver = tp.Receiver(*Process);
|
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);
|
const self = try a.create(Process);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.a = a,
|
.a = a,
|
||||||
|
@ -95,7 +95,7 @@ const Process = struct {
|
||||||
.logger = log.logger(@typeName(Self)),
|
.logger = log.logger(@typeName(Self)),
|
||||||
.stdin_behavior = stdin_behavior,
|
.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 {
|
fn deinit(self: *Process) void {
|
||||||
|
@ -121,7 +121,7 @@ const Process = struct {
|
||||||
"--json",
|
"--json",
|
||||||
self.query,
|
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);
|
tp.receive(&self.receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,14 +130,14 @@ const Process = struct {
|
||||||
var bytes: []u8 = "";
|
var bytes: []u8 = "";
|
||||||
|
|
||||||
if (try m.match(.{ "input", tp.extract(&bytes) })) {
|
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);
|
try sp.send(bytes);
|
||||||
} else if (try m.match(.{"close"})) {
|
} else if (try m.match(.{"close"})) {
|
||||||
try self.close();
|
try self.close();
|
||||||
} else if (try m.match(.{ module_name, "stdout", tp.extract(&bytes) })) {
|
} 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 })) {
|
} 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) })) {
|
} else if (try m.match(.{ module_name, "stderr", tp.extract(&bytes) })) {
|
||||||
self.logger.print("ERR: {s}", .{bytes});
|
self.logger.print("ERR: {s}", .{bytes});
|
||||||
} else if (try m.match(.{ "exit", "normal" })) {
|
} 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 {
|
pub fn filter(self: *const List, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
var sfa = std.heap.stackFallback(4096, self.a);
|
var sfa = std.heap.stackFallback(4096, self.a);
|
||||||
const a = sfa.get();
|
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);
|
defer a.free(buf);
|
||||||
@memcpy(buf[0..m.buf.len], m.buf);
|
@memcpy(buf[0..m.buf.len], m.buf);
|
||||||
const m_: tp.message = .{ .buf = buf[0..m.buf.len] };
|
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 = usize;
|
||||||
pub const ID_unknown = std.math.maxInt(ID);
|
pub const ID_unknown = std.math.maxInt(ID);
|
||||||
|
|
||||||
|
pub const Result = anyerror!void;
|
||||||
pub const Context = struct {
|
pub const Context = struct {
|
||||||
args: tp.message = .{},
|
args: tp.message = .{},
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ pub fn Closure(comptime T: type) type {
|
||||||
f: FunT,
|
f: FunT,
|
||||||
data: T,
|
data: T,
|
||||||
|
|
||||||
const FunT: type = *const fn (T, ctx: Context) tp.result;
|
const FunT: type = *const fn (T, ctx: Context) Result;
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub fn init(f: FunT, data: T, name: []const u8) Self {
|
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 {
|
fn run(vtbl: *Vtable, ctx: Context) tp.result {
|
||||||
const self: *Self = fromVtable(vtbl);
|
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 {
|
fn fromVtable(vtbl: *Vtable) *Self {
|
||||||
|
@ -96,7 +97,7 @@ pub fn execute(id: ID, ctx: Context) tp.result {
|
||||||
const cmd = commands.items[id];
|
const cmd = commands.items[id];
|
||||||
if (cmd) |p| {
|
if (cmd) |p| {
|
||||||
// var buf: [tp.max_message_size]u8 = undefined;
|
// 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);
|
return p.run(p, ctx);
|
||||||
} else {
|
} else {
|
||||||
return tp.exit_fmt("CommandNotAvailable: {d}", .{id});
|
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 {
|
fn CmdDef(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Fn = fn (T, Context) tp.result;
|
const Fn = fn (T, Context) anyerror!void;
|
||||||
name: [:0]const u8,
|
name: [:0]const u8,
|
||||||
f: *const Fn,
|
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 {
|
pub fn handle_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||||
if (try m.match(.{ "E", "update", tp.more }))
|
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) }))
|
if (try m.match(.{ "E", "view", tp.extract(&self.lines), tp.extract(&self.rows), tp.extract(&self.row) }))
|
||||||
return self.update_width();
|
return self.update_width();
|
||||||
if (try m.match(.{ "E", "pos", tp.extract(&self.lines), tp.extract(&self.line), tp.more }))
|
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 {
|
pub fn filter_receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
var cb: []const u8 = undefined;
|
var cb: []const u8 = undefined;
|
||||||
if (try m.match(.{ "DIFF", tp.extract_cbor(&cb) })) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -189,24 +189,25 @@ const Commands = command.Collection(cmds);
|
||||||
const cmds = struct {
|
const cmds = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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();
|
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();
|
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();
|
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: {
|
self.fire = if (self.fire) |*fire| ret: {
|
||||||
fire.deinit();
|
fire.deinit();
|
||||||
break :ret null;
|
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 {
|
pub fn listen(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||||
if (try m.match(.{ "M", tp.more })) return;
|
if (try m.match(.{ "M", tp.more })) return;
|
||||||
var buf: [4096]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
const json = m.to_json(&buf) 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);
|
self.append(json) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive(_: *Self, _: tp.pid_ref, _: tp.message) error{Exit}!bool {
|
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);
|
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;
|
var enabled = true;
|
||||||
if (self.panels) |panels| {
|
if (self.panels) |panels| {
|
||||||
if (panels.get(@typeName(view))) |w| {
|
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;
|
enabled = false;
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
const panels = WidgetList.createH(self.a, self.widgets.widget(), "panel", .{ .static = self.box().h / 5 }) catch |e| return tp.exit_error(e);
|
const panels = try WidgetList.createH(self.a, self.widgets.widget(), "panel", .{ .static = self.box().h / 5 });
|
||||||
self.widgets.add(panels.widget()) catch |e| return tp.exit_error(e);
|
try self.widgets.add(panels.widget());
|
||||||
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));
|
||||||
self.panels = panels;
|
self.panels = panels;
|
||||||
}
|
}
|
||||||
tui.current().resize();
|
tui.current().resize();
|
||||||
|
@ -141,11 +141,11 @@ fn close_all_panel_views(self: *Self) void {
|
||||||
tui.current().resize();
|
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| {
|
if (self.widgets.get(@typeName(view))) |w| {
|
||||||
self.widgets.remove(w.*);
|
self.widgets.remove(w.*);
|
||||||
} else {
|
} 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();
|
tui.current().resize();
|
||||||
}
|
}
|
||||||
|
@ -153,23 +153,24 @@ fn toggle_view(self: *Self, view: anytype) tp.result {
|
||||||
const cmds = struct {
|
const cmds = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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())
|
if (self.editor) |editor| if (editor.is_dirty())
|
||||||
return tp.exit("unsaved changes");
|
return tp.exit("unsaved changes");
|
||||||
try tp.self_pid().send("quit");
|
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");
|
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 project_manager.open_cwd();
|
||||||
_ = try self.statusbar.msg(.{ "PRJ", "open" });
|
_ = 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;
|
var project_dir: []const u8 = undefined;
|
||||||
if (!try ctx.args.match(.{tp.extract(&project_dir)}))
|
if (!try ctx.args.match(.{tp.extract(&project_dir)}))
|
||||||
return;
|
return;
|
||||||
|
@ -177,7 +178,7 @@ const cmds = struct {
|
||||||
_ = try self.statusbar.msg(.{ "PRJ", "open" });
|
_ = 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();
|
tui.reset_drag_context();
|
||||||
const frame = tracy.initZone(@src(), .{ .name = "navigate" });
|
const frame = tracy.initZone(@src(), .{ .name = "navigate" });
|
||||||
defer frame.deinit();
|
defer frame.deinit();
|
||||||
|
@ -192,27 +193,27 @@ const cmds = struct {
|
||||||
var len = len_;
|
var len = len_;
|
||||||
while (len > 0) : (len -= 1) {
|
while (len > 0) : (len -= 1) {
|
||||||
var field_name: []const u8 = undefined;
|
var field_name: []const u8 = undefined;
|
||||||
if (!(cbor.matchString(&iter, &field_name) catch |e| return tp.exit_error(e)))
|
if (!try cbor.matchString(&iter, &field_name))
|
||||||
return tp.exit_error(error.InvalidArgument);
|
return error.InvalidArgument;
|
||||||
if (std.mem.eql(u8, field_name, "line")) {
|
if (std.mem.eql(u8, field_name, "line")) {
|
||||||
if (!(cbor.matchValue(&iter, cbor.extract(&line)) catch |e| return tp.exit_error(e)))
|
if (!try cbor.matchValue(&iter, cbor.extract(&line)))
|
||||||
return tp.exit_error(error.InvalidArgument);
|
return error.InvalidArgument;
|
||||||
} else if (std.mem.eql(u8, field_name, "column")) {
|
} else if (std.mem.eql(u8, field_name, "column")) {
|
||||||
if (!(cbor.matchValue(&iter, cbor.extract(&column)) catch |e| return tp.exit_error(e)))
|
if (!try cbor.matchValue(&iter, cbor.extract(&column)))
|
||||||
return tp.exit_error(error.InvalidArgument);
|
return error.InvalidArgument;
|
||||||
} else if (std.mem.eql(u8, field_name, "file")) {
|
} else if (std.mem.eql(u8, field_name, "file")) {
|
||||||
if (!(cbor.matchValue(&iter, cbor.extract(&file)) catch |e| return tp.exit_error(e)))
|
if (!try cbor.matchValue(&iter, cbor.extract(&file)))
|
||||||
return tp.exit_error(error.InvalidArgument);
|
return error.InvalidArgument;
|
||||||
} else if (std.mem.eql(u8, field_name, "goto")) {
|
} 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)))
|
if (!try cbor.matchValue(&iter, cbor.extract_cbor(&goto_args)))
|
||||||
return tp.exit_error(error.InvalidArgument);
|
return error.InvalidArgument;
|
||||||
} else {
|
} 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) {
|
} else |_| if (ctx.args.match(tp.extract(&file_name)) catch false) {
|
||||||
file = file_name;
|
file = file_name;
|
||||||
} else return tp.exit_error(error.InvalidArgument);
|
} else return error.InvalidArgument;
|
||||||
|
|
||||||
if (tp.env.get().str("project").len == 0) {
|
if (tp.env.get().str("project").len == 0) {
|
||||||
try open_project_cwd(self, .{});
|
try open_project_cwd(self, .{});
|
||||||
|
@ -247,57 +248,57 @@ const cmds = struct {
|
||||||
tui.need_render();
|
tui.need_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_help(self: *Self, _: Ctx) tp.result {
|
pub fn open_help(self: *Self, _: Ctx) Result {
|
||||||
tui.reset_drag_context();
|
tui.reset_drag_context();
|
||||||
try self.create_editor();
|
try self.create_editor();
|
||||||
try command.executeName("open_scratch_buffer", command.fmt(.{ "help.md", @embedFile("help.md") }));
|
try command.executeName("open_scratch_buffer", command.fmt(.{ "help.md", @embedFile("help.md") }));
|
||||||
tui.need_render();
|
tui.need_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_config(_: *Self, _: Ctx) tp.result {
|
pub fn open_config(_: *Self, _: Ctx) Result {
|
||||||
const file_name = root.get_config_file_name() catch |e| return tp.exit_error(e);
|
const file_name = try root.get_config_file_name();
|
||||||
try tp.self_pid().send(.{ "cmd", "navigate", .{ .file = 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();
|
try self.create_editor();
|
||||||
self.read_restore_info() catch |e| return tp.exit_error(e);
|
try self.read_restore_info();
|
||||||
tui.need_render();
|
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);
|
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);
|
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);
|
_ = 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);
|
_ = 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);
|
_ = 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);
|
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);
|
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();
|
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();
|
const tui_ = tui.current();
|
||||||
var ln = tui_.config.gutter_line_numbers;
|
var ln = tui_.config.gutter_line_numbers;
|
||||||
var lnr = tui_.config.gutter_line_numbers_relative;
|
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 = ln;
|
||||||
tui_.config.gutter_line_numbers_relative = lnr;
|
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| {
|
if (self.widgets.get("editor_gutter")) |gutter_widget| {
|
||||||
const gutter = if (gutter_widget.dynamic_cast(@import("editor_gutter.zig"))) |p| p else return;
|
const gutter = if (gutter_widget.dynamic_cast(@import("editor_gutter.zig"))) |p| p else return;
|
||||||
gutter.linenum = ln;
|
gutter.linenum = ln;
|
||||||
|
@ -387,8 +388,8 @@ fn location_jump(from: tp.pid_ref, file_path: []const u8, cursor: location_histo
|
||||||
} }) catch return;
|
} }) catch return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_auto_find(self: *Self, editor: *ed.Editor) !void {
|
fn clear_auto_find(self: *Self, editor: *ed.Editor) void {
|
||||||
try editor.clear_matches();
|
editor.clear_matches();
|
||||||
self.store_last_match_text(null);
|
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);
|
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 {};
|
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 {};
|
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);
|
errdefer editor_widget.deinit(self.a);
|
||||||
if (editor_widget.get("editor")) |editor| {
|
if (editor_widget.get("editor")) |editor| {
|
||||||
editor.subscribe(EventHandler.to_unowned(self.statusbar)) catch @panic("subscribe unsupported");
|
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;
|
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();
|
tui.reset_drag_context();
|
||||||
if (self.editor) |_| return;
|
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);
|
errdefer home_widget.deinit(self.a);
|
||||||
self.widgets.replace(0, home_widget);
|
self.widgets.replace(0, home_widget);
|
||||||
tui.current().resize();
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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"})) {
|
} 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) })) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_keybind() void {}
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||||
switch (keypress) {
|
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;
|
defer self.leader = null;
|
||||||
const ldr = if (self.leader) |leader| leader else return;
|
const ldr = if (self.leader) |leader| leader else return;
|
||||||
return switch (ldr.modifiers) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
var buf: [6]u8 = undefined;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
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 self.flush_input();
|
||||||
try command.executeName("paste", command.fmt(.{bytes}));
|
try command.executeName("paste", command.fmt(.{bytes}));
|
||||||
}
|
}
|
||||||
|
|
||||||
var insert_chars_id: ?command.ID = null;
|
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) {
|
if (self.input.items.len > 0) {
|
||||||
defer self.input.clearRetainingCapacity();
|
defer self.input.clearRetainingCapacity();
|
||||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
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}));
|
try command.execute(id, command.fmt(.{self.input.items}));
|
||||||
self.last_cmd = "insert_chars";
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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"})) {
|
} 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) })) {
|
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.insert_bytes(text);
|
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_keybind() void {}
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
||||||
switch (keypress) {
|
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;
|
defer self.leader = null;
|
||||||
const ldr = if (self.leader) |leader| leader else return;
|
const ldr = if (self.leader) |leader| leader else return;
|
||||||
return switch (ldr.modifiers) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
var buf: [6]u8 = undefined;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
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;
|
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) {
|
if (self.input.items.len > 0) {
|
||||||
defer self.input.clearRetainingCapacity();
|
defer self.input.clearRetainingCapacity();
|
||||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
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}));
|
try command.execute(id, command.fmt(.{self.input.items}));
|
||||||
self.last_cmd = "insert_chars";
|
self.last_cmd = "insert_chars";
|
||||||
|
@ -306,25 +306,26 @@ const Commands = command.Collection(cmds_);
|
||||||
const cmds_ = struct {
|
const cmds_ = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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", .{});
|
try self.cmd("save_file", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
pub fn q(self: *Self, _: Ctx) Result {
|
||||||
try self.cmd("quit", .{});
|
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", .{});
|
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("save_file", .{});
|
||||||
try self.cmd("quit", .{});
|
try self.cmd("quit", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||||
self.cmd("save_file", .{}) catch {};
|
self.cmd("save_file", .{}) catch {};
|
||||||
try self.cmd("quit_without_saving", .{});
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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"})) {
|
} 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) })) {
|
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.insert_bytes(text);
|
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_keybind() void {}
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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');
|
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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
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
|
if (keypress == key.LCTRL or
|
||||||
keypress == key.RCTRL or
|
keypress == key.RCTRL or
|
||||||
keypress == key.LALT 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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||||
|
@ -416,27 +416,27 @@ fn add_count(self: *Self, value: usize) void {
|
||||||
self.count += value;
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
var buf: [6]u8 = undefined;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
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;
|
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) {
|
if (self.input.items.len > 0) {
|
||||||
defer self.input.clearRetainingCapacity();
|
defer self.input.clearRetainingCapacity();
|
||||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
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}));
|
try command.execute(id, command.fmt(.{self.input.items}));
|
||||||
self.last_cmd = "insert_chars";
|
self.last_cmd = "insert_chars";
|
||||||
|
@ -610,25 +610,26 @@ const Commands = command.Collection(cmds_);
|
||||||
const cmds_ = struct {
|
const cmds_ = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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", .{});
|
try self.cmd("save_file", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
pub fn q(self: *Self, _: Ctx) Result {
|
||||||
try self.cmd("quit", .{});
|
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", .{});
|
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("save_file", .{});
|
||||||
try self.cmd("quit", .{});
|
try self.cmd("quit", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||||
self.cmd("save_file", .{}) catch {};
|
self.cmd("save_file", .{}) catch {};
|
||||||
try self.cmd("quit_without_saving", .{});
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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"})) {
|
} 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) })) {
|
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.insert_bytes(text);
|
self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
try self.flush_input();
|
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_keybind() void {}
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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');
|
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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
|
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
|
if (keypress == key.LCTRL or
|
||||||
keypress == key.RCTRL or
|
keypress == key.RCTRL or
|
||||||
keypress == key.LALT 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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
|
||||||
|
@ -376,27 +376,27 @@ fn add_count(self: *Self, value: usize) void {
|
||||||
self.count += value;
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
var buf: [6]u8 = undefined;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
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)
|
if (self.input.items.len + 4 > input_buffer_size)
|
||||||
try self.flush_input();
|
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;
|
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) {
|
if (self.input.items.len > 0) {
|
||||||
defer self.input.clearRetainingCapacity();
|
defer self.input.clearRetainingCapacity();
|
||||||
const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse {
|
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}));
|
try command.execute(id, command.fmt(.{self.input.items}));
|
||||||
self.last_cmd = "insert_chars";
|
self.last_cmd = "insert_chars";
|
||||||
|
@ -570,25 +570,26 @@ const Commands = command.Collection(cmds_);
|
||||||
const cmds_ = struct {
|
const cmds_ = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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", .{});
|
try self.cmd("save_file", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"q"(self: *Self, _: Ctx) tp.result {
|
pub fn @"q"(self: *Self, _: Ctx) Result {
|
||||||
try self.cmd("quit", .{});
|
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", .{});
|
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("save_file", .{});
|
||||||
try self.cmd("quit", .{});
|
try self.cmd("quit", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn @"wq!"(self: *Self, _: Ctx) tp.result {
|
pub fn @"wq!"(self: *Self, _: Ctx) Result {
|
||||||
self.cmd("save_file", .{}) catch {};
|
self.cmd("save_file", .{}) catch {};
|
||||||
try self.cmd("quit_without_saving", .{});
|
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) })) {
|
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"})) {
|
} 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) })) {
|
} 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;
|
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) {
|
switch (evtype) {
|
||||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => 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)
|
if (self.input.len + 16 > self.buf.len)
|
||||||
try self.flush_input();
|
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];
|
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)
|
if (self.input.len + 16 > self.buf.len)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
const newlen = self.input.len + bytes.len;
|
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;
|
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 (self.input.len > 0) {
|
||||||
if (eql(u8, self.input, self.last_input))
|
if (eql(u8, self.input, self.last_input))
|
||||||
return;
|
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) })) {
|
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"})) {
|
} 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) })) {
|
} 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;
|
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) {
|
switch (evtype) {
|
||||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
|
||||||
key.LALT, key.RALT => 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)
|
if (self.input.len + 16 > self.buf.len)
|
||||||
try self.flush_input();
|
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];
|
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)
|
if (self.input.len + 16 > self.buf.len)
|
||||||
try self.flush_input();
|
try self.flush_input();
|
||||||
const newlen = self.input.len + bytes.len;
|
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;
|
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 (self.input.len > 0) {
|
||||||
if (eql(u8, self.input, self.last_input))
|
if (eql(u8, self.input, self.last_input))
|
||||||
return;
|
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) })) {
|
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;
|
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) {
|
switch (evtype) {
|
||||||
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => try self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
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;
|
var buf: [32]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.file_path.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
try self.file_path.appendSlice(buf[0..bytes]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||||
self.file_path.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
try self.file_path.appendSlice(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd(_: *Self, name_: []const u8, ctx: command.Context) tp.result {
|
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 {
|
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) })) {
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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) })) {
|
} 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;
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("command_palette_menu_activate", .{}),
|
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("command_palette_menu_activate", .{}),
|
||||||
else => {},
|
else => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_query(self: *Self) tp.result {
|
fn start_query(self: *Self) !void {
|
||||||
self.items = 0;
|
self.items = 0;
|
||||||
self.menu.reset_items();
|
self.menu.reset_items();
|
||||||
self.menu.selected = null;
|
self.menu.selected = null;
|
||||||
|
@ -289,10 +289,10 @@ fn start_query(self: *Self) tp.result {
|
||||||
defer pos += 1;
|
defer pos += 1;
|
||||||
if (pos < self.view_pos) continue;
|
if (pos < self.view_pos) continue;
|
||||||
if (self.items < self.view_rows)
|
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 {
|
} 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.menu.select_down();
|
||||||
self.do_resize();
|
self.do_resize();
|
||||||
|
@ -360,7 +360,7 @@ fn add_item(self: *Self, name: []const u8, id: command.ID, matches: ?[]const usi
|
||||||
self.items += 1;
|
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| {
|
if (std.mem.lastIndexOfAny(u8, self.inputbox.text.items, "/\\. -_")) |pos| {
|
||||||
self.inputbox.text.shrinkRetainingCapacity(pos);
|
self.inputbox.text.shrinkRetainingCapacity(pos);
|
||||||
} else {
|
} else {
|
||||||
|
@ -371,7 +371,7 @@ fn delete_word(self: *Self) tp.result {
|
||||||
return self.start_query();
|
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) {
|
if (self.inputbox.text.items.len > 0) {
|
||||||
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
|
@ -380,17 +380,17 @@ fn delete_code_point(self: *Self) tp.result {
|
||||||
return self.start_query();
|
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;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
try self.inputbox.text.appendSlice(buf[0..bytes]);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
self.view_pos = 0;
|
self.view_pos = 0;
|
||||||
return self.start_query();
|
return self.start_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||||
self.inputbox.text.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
try self.inputbox.text.appendSlice(bytes);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
self.view_pos = 0;
|
self.view_pos = 0;
|
||||||
return self.start_query();
|
return self.start_query();
|
||||||
|
@ -476,8 +476,9 @@ fn restore_state(self: *Self) !void {
|
||||||
const cmds = struct {
|
const cmds = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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 (self.menu.selected) |selected| {
|
||||||
if (selected == self.view_rows - 1) {
|
if (selected == self.view_rows - 1) {
|
||||||
self.view_pos += 1;
|
self.view_pos += 1;
|
||||||
|
@ -489,7 +490,7 @@ const cmds = struct {
|
||||||
self.menu.select_down();
|
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 (self.menu.selected) |selected| {
|
||||||
if (selected == 0 and self.view_pos > 0) {
|
if (selected == 0 and self.view_pos > 0) {
|
||||||
self.view_pos -= 1;
|
self.view_pos -= 1;
|
||||||
|
@ -501,7 +502,7 @@ const cmds = struct {
|
||||||
self.menu.select_up();
|
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) {
|
if (self.total_items > self.view_rows) {
|
||||||
self.view_pos += self.view_rows;
|
self.view_pos += self.view_rows;
|
||||||
if (self.view_pos > self.total_items - self.view_rows)
|
if (self.view_pos > self.total_items - self.view_rows)
|
||||||
|
@ -511,14 +512,14 @@ const cmds = struct {
|
||||||
self.menu.select_last();
|
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)
|
if (self.view_pos > self.view_rows)
|
||||||
self.view_pos -= self.view_rows;
|
self.view_pos -= self.view_rows;
|
||||||
try self.start_query();
|
try self.start_query();
|
||||||
self.menu.select_first();
|
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();
|
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 {
|
fn receive_project_manager(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
if (try m.match(.{ "PRJ", tp.more })) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
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 file_name: []const u8 = undefined;
|
||||||
var matches: []const u8 = undefined;
|
var matches: []const u8 = undefined;
|
||||||
var query: []const u8 = undefined;
|
var query: []const u8 = undefined;
|
||||||
if (try m.match(.{ "PRJ", "recent", tp.extract(&file_name), tp.extract_cbor(&matches) })) {
|
if (try m.match(.{ "PRJ", "recent", tp.extract(&file_name), tp.extract_cbor(&matches) })) {
|
||||||
if (self.need_reset) self.reset_results();
|
if (self.need_reset) self.reset_results();
|
||||||
self.longest = @max(self.longest, file_name.len);
|
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 });
|
self.menu.resize(.{ .y = 0, .x = 25, .w = @min(self.longest, max_menu_width) + 2 });
|
||||||
if (self.need_select_first) {
|
if (self.need_select_first) {
|
||||||
self.menu.select_down();
|
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) })) {
|
} else if (try m.match(.{ "PRJ", "recent", tp.extract(&file_name) })) {
|
||||||
if (self.need_reset) self.reset_results();
|
if (self.need_reset) self.reset_results();
|
||||||
self.longest = @max(self.longest, file_name.len);
|
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 });
|
self.menu.resize(.{ .y = 0, .x = 25, .w = @min(self.longest, max_menu_width) + 2 });
|
||||||
if (self.need_select_first) {
|
if (self.need_select_first) {
|
||||||
self.menu.select_down();
|
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;
|
var text: []const u8 = undefined;
|
||||||
|
|
||||||
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
|
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) })) {
|
} 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;
|
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) {
|
return switch (evtype) {
|
||||||
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
|
||||||
event_type.REPEAT => 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;
|
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
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) {
|
return switch (keypress) {
|
||||||
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("open_recent_menu_activate", .{}),
|
key.LCTRL, key.RCTRL => if (self.menu.selected orelse 0 > 0) return self.cmd("open_recent_menu_activate", .{}),
|
||||||
else => {},
|
else => {},
|
||||||
|
@ -285,13 +285,13 @@ fn reset_results(self: *Self) void {
|
||||||
self.need_select_first = true;
|
self.need_select_first = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_query(self: *Self) tp.result {
|
fn start_query(self: *Self) !void {
|
||||||
if (self.query_pending) return;
|
if (self.query_pending) return;
|
||||||
self.query_pending = true;
|
self.query_pending = true;
|
||||||
try project_manager.query_recent_files(max_recent_files, self.inputbox.text.items);
|
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| {
|
if (std.mem.lastIndexOfAny(u8, self.inputbox.text.items, "/\\. -_")) |pos| {
|
||||||
self.inputbox.text.shrinkRetainingCapacity(pos);
|
self.inputbox.text.shrinkRetainingCapacity(pos);
|
||||||
} else {
|
} else {
|
||||||
|
@ -301,7 +301,7 @@ fn delete_word(self: *Self) tp.result {
|
||||||
return self.start_query();
|
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) {
|
if (self.inputbox.text.items.len > 0) {
|
||||||
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
self.inputbox.text.shrinkRetainingCapacity(self.inputbox.text.items.len - 1);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
|
@ -309,16 +309,16 @@ fn delete_code_point(self: *Self) tp.result {
|
||||||
return self.start_query();
|
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;
|
var buf: [6]u8 = undefined;
|
||||||
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
|
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
|
||||||
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
|
try self.inputbox.text.appendSlice(buf[0..bytes]);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
return self.start_query();
|
return self.start_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_bytes(self: *Self, bytes: []const u8) tp.result {
|
fn insert_bytes(self: *Self, bytes: []const u8) !void {
|
||||||
self.inputbox.text.appendSlice(bytes) catch |e| return tp.exit_error(e);
|
try self.inputbox.text.appendSlice(bytes);
|
||||||
self.inputbox.cursor = self.inputbox.text.items.len;
|
self.inputbox.cursor = self.inputbox.text.items.len;
|
||||||
return self.start_query();
|
return self.start_query();
|
||||||
}
|
}
|
||||||
|
@ -339,16 +339,17 @@ const Commands = command.Collection(cmds);
|
||||||
const cmds = struct {
|
const cmds = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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();
|
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();
|
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();
|
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 {
|
fn receive_log(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
var clear_msg_num: usize = 0;
|
var clear_msg_num: usize = 0;
|
||||||
if (try m.match(.{ "log", tp.more })) {
|
if (try m.match(.{ "log", tp.more })) {
|
||||||
logview.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);
|
self.process_log(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
return true;
|
return true;
|
||||||
} else if (try m.match(.{ "MINILOG", tp.extract(&clear_msg_num) })) {
|
} else if (try m.match(.{ "MINILOG", tp.extract(&clear_msg_num) })) {
|
||||||
if (clear_msg_num == self.msg_counter)
|
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 {
|
fn start(args: StartArgs) tp.result {
|
||||||
_ = tp.set_trap(true);
|
_ = 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();
|
errdefer self.deinit();
|
||||||
tp.receive(&self.receiver);
|
tp.receive(&self.receiver);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ fn init(a: Allocator) !*Self {
|
||||||
return 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}));
|
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 {
|
fn listen_sigwinch(self: *Self) tp.result {
|
||||||
if (self.sigwinch_signal) |old| old.deinit();
|
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 {
|
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| {
|
self.receive_safe(from, m) catch |e| {
|
||||||
if (std.mem.eql(u8, "normal", tp.error_text()))
|
if (std.mem.eql(u8, "normal", tp.error_text()))
|
||||||
return e;
|
return error.Exit;
|
||||||
if (std.mem.eql(u8, "restart", tp.error_text()))
|
if (std.mem.eql(u8, "restart", tp.error_text()))
|
||||||
return e;
|
return error.Exit;
|
||||||
self.logger.err("UI", e);
|
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 input: []const u8 = undefined;
|
||||||
var text: []const u8 = undefined;
|
var text: []const u8 = undefined;
|
||||||
if (try m.match(.{ "VXS", tp.extract(&input), tp.extract(&text) })) {
|
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();
|
try self.dispatch_flush_input_event();
|
||||||
if (self.unrendered_input_events_count > 0 and !self.frame_clock_running)
|
if (self.unrendered_input_events_count > 0 and !self.frame_clock_running)
|
||||||
need_render();
|
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;
|
var buf: [32]u8 = undefined;
|
||||||
if (self.input_mode) |mode|
|
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 {
|
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 m: tp.message = .{ .buf = cbor_msg };
|
||||||
const from = tp.self_pid();
|
const from = tp.self_pid();
|
||||||
self.unrendered_input_events_count += 1;
|
self.unrendered_input_events_count += 1;
|
||||||
if (self.drag_source) |_|
|
const send_func = if (self.drag_source) |_| &send_mouse_drag else &send_mouse;
|
||||||
self.send_mouse_drag(y, x, from, m) catch |e| self.logger.err("dispatch mouse", e)
|
send_func(self, 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);
|
|
||||||
self.drag_source = null;
|
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;
|
var buf: [256]u8 = undefined;
|
||||||
if (self.hover_focus) |h| {
|
if (self.hover_focus) |h| {
|
||||||
if (self.is_live_widget_ptr(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;
|
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);
|
_ = try w.send(from, m);
|
||||||
} else {
|
} else {
|
||||||
if (self.hover_focus) |h| {
|
if (self.hover_focus) |h| {
|
||||||
var buf: [256]u8 = undefined;
|
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;
|
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;
|
var buf: [256]u8 = undefined;
|
||||||
if (self.hover_focus) |h| {
|
if (self.hover_focus) |h| {
|
||||||
if (self.is_live_widget_ptr(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;
|
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 {
|
} else {
|
||||||
if (self.hover_focus) |h| {
|
if (self.hover_focus) |h| {
|
||||||
var buf: [256]u8 = undefined;
|
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;
|
self.hover_focus = null;
|
||||||
}
|
}
|
||||||
|
@ -510,83 +508,84 @@ pub fn save_config(self: *const Self) !void {
|
||||||
const cmds = struct {
|
const cmds = struct {
|
||||||
pub const Target = Self;
|
pub const Target = Self;
|
||||||
const Ctx = command.Context;
|
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");
|
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.theme = get_next_theme_by_name(self.theme.name);
|
||||||
self.config.theme = self.theme.name;
|
self.config.theme = self.theme.name;
|
||||||
self.logger.print("theme: {s}", .{self.theme.description});
|
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.theme = get_prev_theme_by_name(self.theme.name);
|
||||||
self.config.theme = self.theme.name;
|
self.config.theme = self.theme.name;
|
||||||
self.logger.print("theme: {s}", .{self.theme.description});
|
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.config.show_whitespace = !self.config.show_whitespace;
|
||||||
self.logger.print("show_whitspace {s}", .{if (self.config.show_whitespace) "enabled" else "disabled"});
|
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;
|
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);
|
_ = 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.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}));
|
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;
|
var mode: []const u8 = undefined;
|
||||||
if (!try ctx.args.match(.{tp.extract(&mode)}))
|
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.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||||
if (self.input_mode) |*m| m.deinit();
|
if (self.input_mode) |*m| m.deinit();
|
||||||
self.input_mode = if (std.mem.eql(u8, mode, "vim/normal"))
|
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"))
|
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"))
|
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"))
|
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"))
|
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: {
|
else ret: {
|
||||||
self.logger.print("unknown mode {s}", .{mode});
|
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});
|
// 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}));
|
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.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||||
self.input_mode_outer = self.input_mode;
|
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.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||||
self.input_mode_outer = self.input_mode;
|
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;
|
if (self.input_mode_outer == null) return;
|
||||||
defer {
|
defer {
|
||||||
self.input_mode = self.input_mode_outer;
|
self.input_mode = self.input_mode_outer;
|
||||||
|
@ -595,29 +594,29 @@ const cmds = struct {
|
||||||
if (self.input_mode) |*mode| mode.deinit();
|
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);
|
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);
|
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);
|
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);
|
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);
|
return enter_mini_mode(self, @import("mode/mini/open_file.zig"), ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MiniModeFactory = fn (Allocator, Ctx) error{ NotFound, OutOfMemory }!EventHandler;
|
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.mini_mode) |_| try exit_mini_mode(self, .{});
|
||||||
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
|
||||||
self.input_mode_outer = self.input_mode;
|
self.input_mode_outer = self.input_mode;
|
||||||
|
@ -626,7 +625,7 @@ const cmds = struct {
|
||||||
self.input_mode_outer = null;
|
self.input_mode_outer = null;
|
||||||
self.mini_mode = 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 = .{
|
self.input_mode = .{
|
||||||
.handler = mode_instance.handler(),
|
.handler = mode_instance.handler(),
|
||||||
.name = mode_instance.name(),
|
.name = mode_instance.name(),
|
||||||
|
@ -635,7 +634,7 @@ const cmds = struct {
|
||||||
self.mini_mode = .{};
|
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;
|
if (self.mini_mode) |_| {} else return;
|
||||||
defer {
|
defer {
|
||||||
self.input_mode = self.input_mode_outer;
|
self.input_mode = self.input_mode_outer;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue