feat: add support for language server window/showMessage notifications
This commit is contained in:
		
							parent
							
								
									f91ae313d1
								
							
						
					
					
						commit
						ef57339258
					
				
					 4 changed files with 44 additions and 0 deletions
				
			
		|  | @ -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, | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/log.zig
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								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 {}; | ||||
|     } | ||||
| }; | ||||
|  |  | |||
|  | @ -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 }); | ||||
|     } | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue