diff options
Diffstat (limited to 'src/gui')
| -rw-r--r-- | src/gui/gui.zig | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig index 91380e46..11e9f53b 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -899,6 +899,9 @@ const Msg = union(enum) { eof: struct { pane: u8, gen: u32, fd: c_int }, /// a language query finished on its own thread (see lspThread) lsp: struct { id: u32, rows: []u8 }, + /// a language SERVER changed state; narrated by the client's reader + /// threads through the status sink, lsp-allocator-owned + lsp_status: []u8, /// a selection-filter worker finished; every stdout is gpa-owned pipe: selection_pipe.Response, /// something happened in a watched directory (see watchThread) @@ -917,6 +920,7 @@ const Msg = union(enum) { switch (m) { .output => |o| gpa.free(o.bytes), .lsp => |l| lsp_allocator.free(l.rows), + .lsp_status => |t| lsp_allocator.free(t), .pipe => |response_value| { var response = response_value; response.deinit(gpa); @@ -1120,6 +1124,15 @@ const Queue = struct { } }; +/// The registered `lsp.setStatusSink` target, called from the protocol +/// client's reader threads: dupe with the concurrent lsp allocator, push to +/// the mutex queue. A push after close is disposed by the queue itself. +fn lspStatusSink(ctx: ?*anyopaque, text: []const u8) void { + const q: *Queue = @ptrCast(@alignCast(ctx orelse return)); + const copy = q.lsp_allocator.dupe(u8, text) catch return; + q.push(.{ .lsp_status = copy }); +} + fn readPtyThread(gpa: std.mem.Allocator, fd: c_int, pane: u8, gen: u32, q: *Queue) void { var buf: [0x10000]u8 = undefined; while (true) { @@ -2158,6 +2171,10 @@ fn localSession( if (test_mode) setStdinRaw() catch {}; shell.threads_ok = true; + // Server state narration: reader threads → queue → drainQueue → the + // message row. Unset before the queue closes (see the defer above it). + pardes.lsp.setStatusSink(&queue, lspStatusSink); + defer pardes.lsp.setStatusSink(null, null); // The core owns the loop. This owns the two things a pump cannot do from // inside itself, because both replace the whole session and are only safe @@ -2580,6 +2597,8 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void { while (core.nextEffect()) |e| core.perform(e); for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), gens[id], &queue); shell.threads_ok = true; + pardes.lsp.setStatusSink(&queue, lspStatusSink); + defer pardes.lsp.setStatusSink(null, null); setStdinRaw() catch {}; // stdin may be a pipe, not a pty — best effort @@ -3696,6 +3715,14 @@ const Shell = struct { s.lsp_allocator.free(l.rows); s.saw_event = true; }, + // Server state on the transient message row of the ACTIVE pane — + // session news, same row and same stamp a completed save uses. + .lsp_status => |text| { + var mbuf: [256]u8 = undefined; + s.core.setMessage(s.core.active, message.stamp(&mbuf, "lsp", text)); + s.lsp_allocator.free(text); + s.saw_event = true; + }, .pipe => |response_value| { var response = response_value; s.core.update(.{ .pipe_resp = .{ |
