@henryqw/pi-open-in 0.2.2 → 0.2.3
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/README.md +2 -0
- package/extensions/open.ts +25 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,8 @@ pi install npm:@henryqw/pi-open-in
|
|
|
27
27
|
|
|
28
28
|
The command is split on whitespace; tokens cannot contain spaces (no quoting). Use a wrapper script for executables in spaced paths.
|
|
29
29
|
|
|
30
|
+
A missing config file falls back to `code`. An existing file must be a JSON object with exactly one non-empty string `command` property; otherwise `/open` fails with a visible error. The file is never rewritten by this extension except via `/set-open-in`. When the config is invalid, no open URI is offered.
|
|
31
|
+
|
|
30
32
|
## Remove
|
|
31
33
|
|
|
32
34
|
```bash
|
package/extensions/open.ts
CHANGED
|
@@ -10,21 +10,36 @@ import {
|
|
|
10
10
|
const DEFAULT_COMMAND = "code";
|
|
11
11
|
const configPath = () => join(getAgentDir(), "config", "pi-open-in.json");
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function loadCommand(): string {
|
|
14
|
+
let raw: string;
|
|
14
15
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
raw = readFileSync(configPath(), "utf8");
|
|
17
|
+
} catch (error) {
|
|
18
|
+
// Only a missing file falls back to the default command.
|
|
19
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return DEFAULT_COMMAND;
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
let config: unknown;
|
|
23
|
+
try {
|
|
24
|
+
config = JSON.parse(raw);
|
|
20
25
|
} catch {
|
|
21
|
-
|
|
26
|
+
throw new Error(`Invalid ${configPath()}: not valid JSON`);
|
|
27
|
+
}
|
|
28
|
+
const isObject = (value: unknown): value is Record<string, unknown> =>
|
|
29
|
+
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30
|
+
if (!isObject(config) || Object.keys(config).length !== 1 || typeof config.command !== "string" || !config.command.trim()) {
|
|
31
|
+
throw new Error(`Invalid ${configPath()}: expected exactly one non-empty string "command" property`);
|
|
22
32
|
}
|
|
23
|
-
return
|
|
33
|
+
return config.command.trim();
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
export function configuredOpenUri(path: string): string | undefined {
|
|
27
|
-
|
|
37
|
+
try {
|
|
38
|
+
if (loadCommand() !== "code") return undefined;
|
|
39
|
+
} catch {
|
|
40
|
+
// Invalid config must not break footer render; just omit the URI.
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
28
43
|
if (path.startsWith("\\\\")) {
|
|
29
44
|
const [host, ...parts] = path.slice(2).split("\\");
|
|
30
45
|
const uri = new URL(`file://${host}`);
|
|
@@ -47,7 +62,7 @@ export default function openInExtension(pi: ExtensionAPI): void {
|
|
|
47
62
|
pi.registerCommand("open", {
|
|
48
63
|
description: "Open the current path with the configured command",
|
|
49
64
|
handler: async (_args, ctx) => {
|
|
50
|
-
const [executable, ...args] =
|
|
65
|
+
const [executable, ...args] = loadCommand().split(/\s+/);
|
|
51
66
|
const result = await pi.exec(executable, [...args, ctx.cwd]);
|
|
52
67
|
if (result.code !== 0) {
|
|
53
68
|
throw new Error(`Open command failed: ${result.stderr.trim() || `exit code ${result.code}`}`);
|