summaryrefslogtreecommitdiff
path: root/src/lsp/lsp.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 12:10:51 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commite27ec50ecad669a21b33c2c2e7c591828ba97e1b (patch)
tree384da9de703616a9e1aca3480dbf9c6f189b9794 /src/lsp/lsp.zig
parent996f4d256b95134b0b3d0fc8e8b558792f8f6c61 (diff)
downloadpardes-e27ec50ecad669a21b33c2c2e7c591828ba97e1b.tar.gz
pardes-e27ec50ecad669a21b33c2c2e7c591828ba97e1b.zip
Lspwhy explains the last language server query asked, its kind, argument and place, not always a definition at the cursor
Lspwhy said it explains how the last request was answered, but it always replayed a definition query at the current cursor. So after a failed Hover it narrated a gd somewhere else, which told nothing about the failure. Now the core remembers the last query (kind, argument, pane, offset), and Lspwhy sends it as `<kind> <arg>`, at the query's offset when asked from the same pane. The client narrates that kind: lsp.explaining reads it, and the heading names it ("the hover query at byte N"). With nothing asked yet it is a definition, as before. The effect's arg grows to 160 bytes so a 128-byte argument fits with its kind. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/lsp/lsp.zig')
-rw-r--r--src/lsp/lsp.zig26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/lsp/lsp.zig b/src/lsp/lsp.zig
index 43f94f95..33e95570 100644
--- a/src/lsp/lsp.zig
+++ b/src/lsp/lsp.zig
@@ -31,8 +31,34 @@ pub const Req = struct {
offset: u32,
arg: []const u8 = "",
root: []const u8 = "",
+ /// For `explain`: the query it narrates, read from `arg` (`<kind>
+ /// <arg>`) by `explaining`; a definition when none was asked before.
+ explains: Kind = .definition,
};
+/// An `explain` request made the one it narrates: `explains` and `arg` set
+/// from its `<kind> <arg>`; any other request as it is.
+pub fn explaining(req: Req) Req {
+ if (req.kind != .explain) return req;
+ var r = req;
+ const sp = std.mem.indexOfScalar(u8, req.arg, ' ') orelse req.arg.len;
+ const named = std.meta.stringToEnum(Kind, req.arg[0..sp]) orelse .definition;
+ r.explains = if (named == .explain or named == .status) .definition else named;
+ r.arg = if (sp < req.arg.len) req.arg[sp + 1 ..] else "";
+ return r;
+}
+
+test "an explain request narrates the query named in its arg, a definition by default" {
+ const base: Req = .{ .kind = .explain, .path = "/x.zig", .source = "", .offset = 0 };
+ var r = base;
+ r.arg = "hover ";
+ try std.testing.expectEqual(Kind.hover, explaining(r).explains);
+ r.arg = "rename newName";
+ try std.testing.expectEqual(Kind.rename, explaining(r).explains);
+ try std.testing.expectEqualStrings("newName", explaining(r).arg);
+ try std.testing.expectEqual(Kind.definition, explaining(base).explains);
+}
+
/// Every language, Zig's (zls) included, through the protocol client, which
/// runs its server as a child process. None on the web or the board.
const backends = if (@import("pardes_config").platform == .web or @import("pardes_config").platform == .esp32p4)