diff --git a/src/Project.zig b/src/Project.zig index 80c2351..f2d7693 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -1,6 +1,7 @@ const std = @import("std"); const tp = @import("thespian"); const cbor = @import("cbor"); +const log = @import("log"); const root = @import("root"); const dizzy = @import("dizzy"); const Buffer = @import("Buffer"); @@ -587,6 +588,31 @@ fn read_position(position: []const u8) !Position { return .{ .line = line.?, .character = character.? }; } +pub fn show_message(_: *Self, _: tp.pid_ref, params_cb: []const u8) !void { + var type_: i32 = 0; + var message: ?[]const u8 = null; + var iter = params_cb; + var len = try cbor.decodeMapHeader(&iter); + while (len > 0) : (len -= 1) { + var field_name: []const u8 = undefined; + if (!(try cbor.matchString(&iter, &field_name))) return error.InvalidMessage; + if (std.mem.eql(u8, field_name, "type")) { + if (!(try cbor.matchValue(&iter, cbor.extract(&type_)))) return error.InvalidMessageField; + } else if (std.mem.eql(u8, field_name, "message")) { + if (!(try cbor.matchValue(&iter, cbor.extract(&message)))) return error.InvalidMessageField; + } else { + try cbor.skipValue(&iter); + } + } + const msg = if (message) |m| m else return; + const logger = log.logger("lsp"); + defer logger.deinit(); + if (type_ <= 2) + logger.err_msg("lsp", msg) + else + 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 { return lsp.send_request(self.a, "initialize", .{ .processId = if (builtin.os.tag == .linux) std.os.linux.getpid() else null, diff --git a/src/log.zig b/src/log.zig index 3455b9b..c635d64 100644 --- a/src/log.zig +++ b/src/log.zig @@ -121,6 +121,12 @@ pub const Logger = struct { self.proc.send(.{ "log", self.tag, output }) catch {}; } + pub fn print_err(self: Logger, context: []const u8, comptime fmt: anytype, args: anytype) void { + var buf: [max_log_message]u8 = undefined; + const output = std.fmt.bufPrint(&buf, fmt, args) catch "MESSAGE TOO LARGE"; + self.err_msg(context, output); + } + pub fn err(self: Logger, context: []const u8, e: anyerror) void { defer tp.reset_error(); var buf: [max_log_message]u8 = undefined; @@ -143,6 +149,10 @@ pub const Logger = struct { msg = @errorName(e); }, } + self.err_msg(context, msg); + } + + pub fn err_msg(self: Logger, context: []const u8, msg: []const u8) void { self.proc.send(.{ "log", "error", self.tag, context, "->", msg }) catch {}; } }; diff --git a/src/project_manager.zig b/src/project_manager.zig index 9d34cd5..56ae5d3 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -318,6 +318,8 @@ const Process = struct { const project = if (self.projects.get(project_directory)) |p| p else return tp.exit("No project"); return if (std.mem.eql(u8, method, "textDocument/publishDiagnostics")) project.publish_diagnostics(self.parent.ref(), params_cb) catch |e| tp.exit_error(e) + else if (std.mem.eql(u8, method, "window/showMessage")) + project.show_message(self.parent.ref(), params_cb) catch |e| tp.exit_error(e) else tp.unexpected(.{ .buf = params_cb }); } diff --git a/src/tui/tui.zig b/src/tui/tui.zig index c3df327..538bfb7 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -317,6 +317,12 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) tp.result { if (try m.match(.{ "exit", "DEADSEND", tp.more })) return; + var msg: []const u8 = undefined; + if (try m.match(.{ "exit", tp.extract(&msg), tp.more })) { + self.logger.err_msg("tui", msg); + return; + } + if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses return;