ソースを参照

Add line to JSON search output

dan mackinlay 1 ヶ月 前
コミット
c22d00829b
3 ファイル変更21 行追加1 行削除
  1. 2 0
      CHANGELOG.md
  2. 5 1
      src/cli/formatter.ts
  3. 14 0
      test/formatter.test.ts

+ 2 - 0
CHANGELOG.md

@@ -20,6 +20,8 @@
 - Sync stale `bun.lock` (`better-sqlite3` 11.x → 12.x). CI and release
   script now use `--frozen-lockfile` to prevent recurrence. #386
   (thanks @Mic92)
+- Include `line` in `--json` search output so editor integrations can jump
+  directly to `file:line`. Closes #505 (thanks @danmackinlay)
 
 ## [2.0.1] - 2026-03-10
 

+ 5 - 1
src/cli/formatter.ts

@@ -101,8 +101,11 @@ export function searchResultsToJson(
   const query = opts.query || "";
   const output = results.map(row => {
     const bodyStr = row.body || "";
+    const snippetInfo = bodyStr
+      ? extractSnippet(bodyStr, query, 300, row.chunkPos, undefined, opts.intent)
+      : undefined;
     let body = opts.full ? bodyStr : undefined;
-    let snippet = !opts.full ? extractSnippet(bodyStr, query, 300, row.chunkPos, undefined, opts.intent).snippet : undefined;
+    let snippet = !opts.full ? snippetInfo?.snippet : undefined;
 
     if (opts.lineNumbers) {
       if (body) body = addLineNumbers(body);
@@ -113,6 +116,7 @@ export function searchResultsToJson(
       docid: `#${row.docid}`,
       score: Math.round(row.score * 100) / 100,
       file: row.displayPath,
+      ...(snippetInfo && { line: snippetInfo.line }),
       title: row.title,
       ...(row.context && { context: row.context }),
       ...(body && { body }),

+ 14 - 0
test/formatter.test.ts

@@ -95,6 +95,20 @@ describe("search results include context in all formats", () => {
     expect(parsed[0].context).toBe(TEST_CONTEXT);
   });
 
+  test("JSON format includes line", () => {
+    const output = searchResultsToJson(results, { query: "keynote" });
+    const parsed = JSON.parse(output);
+    expect(parsed[0].line).toBeTypeOf("number");
+    expect(parsed[0].line).toBeGreaterThan(0);
+  });
+
+  test("JSON format includes line with --full", () => {
+    const output = searchResultsToJson(results, { query: "keynote", full: true });
+    const parsed = JSON.parse(output);
+    expect(parsed[0].line).toBeTypeOf("number");
+    expect(parsed[0].line).toBeGreaterThan(0);
+  });
+
   test("CSV format includes context", () => {
     const output = searchResultsToCsv(results, { query: "keynote" });
     // Header should have context column