pi-readseek 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/grep.ts +4 -4
- package/src/map-cache.ts +16 -3
- package/src/readseek-client.ts +20 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-readseek",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "Pi extension for readseek-backed hash-anchored read/edit/grep, structural code maps, structural search, and file exploration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=20.0.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@jarkkojs/readseek": "^0.3.
|
|
42
|
+
"@jarkkojs/readseek": "^0.3.14",
|
|
43
43
|
"diff": "^8.0.3",
|
|
44
44
|
"ignore": "^7.0.5",
|
|
45
45
|
"picomatch": "^4.0.4",
|
package/src/grep.ts
CHANGED
|
@@ -69,8 +69,8 @@ interface GrepParams {
|
|
|
69
69
|
scopeContext?: number | string;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
const MATCH_LINE_RE = /^(
|
|
73
|
-
const CONTEXT_LINE_RE = /^(
|
|
72
|
+
const MATCH_LINE_RE = /^(.*?):(\d+): (.*)$/;
|
|
73
|
+
const CONTEXT_LINE_RE = /^(.*?)-(\d+)- (.*)$/;
|
|
74
74
|
|
|
75
75
|
function parseGrepOutputLine(line: string):
|
|
76
76
|
| { kind: "match"; displayPath: string; lineNumber: number; text: string }
|
|
@@ -406,8 +406,8 @@ export function registerGrepTool(pi: ExtensionAPI, options: GrepToolOptions = {}
|
|
|
406
406
|
fileCache.set(absolutePath, lines);
|
|
407
407
|
return lines;
|
|
408
408
|
} catch {
|
|
409
|
-
fileCache.set(absolutePath,
|
|
410
|
-
return
|
|
409
|
+
fileCache.set(absolutePath, undefined);
|
|
410
|
+
return undefined;
|
|
411
411
|
}
|
|
412
412
|
};
|
|
413
413
|
|
package/src/map-cache.ts
CHANGED
|
@@ -11,6 +11,7 @@ export const MAP_CACHE_MAX_SIZE = 500;
|
|
|
11
11
|
|
|
12
12
|
interface MapCacheGlobalState {
|
|
13
13
|
cache: Map<string, CacheEntry>;
|
|
14
|
+
inflight: Map<string, Promise<FileMap | null>>;
|
|
14
15
|
maxSize: number;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -20,6 +21,7 @@ function getMapCacheState(): MapCacheGlobalState {
|
|
|
20
21
|
const globalObject = globalThis as any;
|
|
21
22
|
globalObject[MAP_CACHE_STATE_KEY] ??= {
|
|
22
23
|
cache: new Map<string, CacheEntry>(),
|
|
24
|
+
inflight: new Map<string, Promise<FileMap | null>>(),
|
|
23
25
|
maxSize: MAP_CACHE_MAX_SIZE,
|
|
24
26
|
} satisfies MapCacheGlobalState;
|
|
25
27
|
return globalObject[MAP_CACHE_STATE_KEY] as MapCacheGlobalState;
|
|
@@ -54,9 +56,20 @@ export async function getOrGenerateMap(absPath: string): Promise<FileMap | null>
|
|
|
54
56
|
state.cache.set(absPath, cached);
|
|
55
57
|
return cached.map;
|
|
56
58
|
}
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
const inflight = state.inflight.get(absPath);
|
|
60
|
+
if (inflight) return inflight;
|
|
61
|
+
|
|
62
|
+
const generation = (async () => {
|
|
63
|
+
const map = await generateMap(absPath);
|
|
64
|
+
rememberInMemory(absPath, { mtimeMs, map });
|
|
65
|
+
return map;
|
|
66
|
+
})()
|
|
67
|
+
.catch(() => null)
|
|
68
|
+
.finally(() => {
|
|
69
|
+
state.inflight.delete(absPath);
|
|
70
|
+
});
|
|
71
|
+
state.inflight.set(absPath, generation);
|
|
72
|
+
return generation;
|
|
60
73
|
} catch {
|
|
61
74
|
return null;
|
|
62
75
|
}
|
package/src/readseek-client.ts
CHANGED
|
@@ -170,6 +170,18 @@ interface RunReadseekOptions {
|
|
|
170
170
|
|
|
171
171
|
async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}): Promise<string> {
|
|
172
172
|
return new Promise<string>((resolve, reject) => {
|
|
173
|
+
let settled = false;
|
|
174
|
+
const fail = (error: Error): void => {
|
|
175
|
+
if (settled) return;
|
|
176
|
+
settled = true;
|
|
177
|
+
reject(error);
|
|
178
|
+
};
|
|
179
|
+
const succeed = (value: string): void => {
|
|
180
|
+
if (settled) return;
|
|
181
|
+
settled = true;
|
|
182
|
+
resolve(value);
|
|
183
|
+
};
|
|
184
|
+
|
|
173
185
|
const stdin = options.stdin;
|
|
174
186
|
const stdio: StdioOptions = [stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"];
|
|
175
187
|
const child = spawn(readseekBinaryPath(), args, { stdio, signal: options.signal });
|
|
@@ -178,7 +190,7 @@ async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}):
|
|
|
178
190
|
const childStdin = child.stdin;
|
|
179
191
|
if (!childStdout || !childStderr) {
|
|
180
192
|
child.kill();
|
|
181
|
-
|
|
193
|
+
fail(new Error("readseek stdio streams are unavailable"));
|
|
182
194
|
return;
|
|
183
195
|
}
|
|
184
196
|
const stdoutChunks: Buffer[] = [];
|
|
@@ -186,32 +198,33 @@ async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}):
|
|
|
186
198
|
let stdoutBytes = 0;
|
|
187
199
|
|
|
188
200
|
childStdout.on("data", (chunk: Buffer) => {
|
|
201
|
+
if (settled) return;
|
|
189
202
|
stdoutBytes += chunk.length;
|
|
190
203
|
if (stdoutBytes > 32 * 1024 * 1024) {
|
|
191
204
|
child.kill();
|
|
192
|
-
|
|
205
|
+
fail(new Error("readseek output exceeded 32 MiB"));
|
|
193
206
|
return;
|
|
194
207
|
}
|
|
195
208
|
stdoutChunks.push(chunk);
|
|
196
209
|
});
|
|
197
210
|
childStderr.on("data", (chunk: Buffer) => stderrChunks.push(chunk));
|
|
198
|
-
child.on("error", (error: any) =>
|
|
211
|
+
child.on("error", (error: any) => fail(error));
|
|
199
212
|
if (stdin !== undefined) {
|
|
200
213
|
if (!childStdin) {
|
|
201
214
|
child.kill();
|
|
202
|
-
|
|
215
|
+
fail(new Error("readseek stdin stream is unavailable"));
|
|
203
216
|
return;
|
|
204
217
|
}
|
|
205
218
|
childStdin.on("error", (error: any) => {
|
|
206
|
-
if (error?.code !== "EPIPE")
|
|
219
|
+
if (error?.code !== "EPIPE") fail(error);
|
|
207
220
|
});
|
|
208
221
|
childStdin.end(stdin, "utf-8");
|
|
209
222
|
}
|
|
210
223
|
child.on("close", (code) => {
|
|
211
224
|
const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
|
|
212
225
|
const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
|
|
213
|
-
if (code === 0)
|
|
214
|
-
else
|
|
226
|
+
if (code === 0) succeed(stdout);
|
|
227
|
+
else fail(new Error((stderr || `readseek exited with status ${code}`).replace(/^error:\s*/i, "")));
|
|
215
228
|
});
|
|
216
229
|
});
|
|
217
230
|
}
|