@jals1212/pi-spaces-cli 0.3.0 → 0.3.1

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cli.js +15 -22
  3. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -6,6 +6,20 @@ commands and options and a patch version fixes.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.3.1
10
+
11
+ ### Fixed
12
+
13
+ - On Windows the program is started through `cross-spawn`. npm shims such as
14
+ `pi.cmd`, paths with spaces, a trailing backslash, `%` and other `cmd.exe`
15
+ characters in the command or in Pi's arguments are passed as written.
16
+ - The picker reports a bad command (an unclosed quote) before it lists the
17
+ spaces, not after you have chosen one.
18
+
19
+ ### Changed
20
+
21
+ - Depends on `cross-spawn`.
22
+
9
23
  ## 0.3.0
10
24
 
11
25
  ### Added
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // The optional `pi-space` command: pick a space and start Pi in it.
2
2
  // It only passes `--space <name>`; the extension does the switch, so it never sets PI_CODING_AGENT_DIR.
3
- import { spawn as nodeSpawn } from "node:child_process";
4
3
  import { readFileSync } from "node:fs";
5
4
  import { homedir } from "node:os";
6
5
  import { dirname, join, resolve } from "node:path";
7
6
  import { createInterface } from "node:readline";
8
7
  import { fileURLToPath } from "node:url";
8
+ import crossSpawn from "cross-spawn";
9
9
  import {
10
10
  BACKUPS,
11
11
  BASE,
@@ -139,15 +139,6 @@ export function splitCommand(text ) {
139
139
  return words;
140
140
  }
141
141
 
142
- /**
143
- * One word for the single command line cmd.exe gets when the child runs with shell: true on Windows:
144
- * wrapped in double quotes unless it is plain, with inner double quotes doubled.
145
- */
146
- export function quoteForCmd(word ) {
147
- if (word !== "" && !/[\s"&|<>^()%!,;=]/.test(word)) return word;
148
- return `"${word.replaceAll('"', '""')}"`;
149
- }
150
-
151
142
  const EXTENSION = "@jals1212/pi-spaces";
152
143
 
153
144
  /**
@@ -172,7 +163,6 @@ function agentHome(env , home ) {
172
163
 
173
164
 
174
165
 
175
-
176
166
 
177
167
 
178
168
 
@@ -190,19 +180,20 @@ function agentHome(env , home ) {
190
180
 
191
181
 
192
182
 
193
-
194
-
195
183
 
196
184
 
197
185
 
198
186
 
199
- /** The real child process: stdio inherited, the environment unchanged, a shell on Windows so .cmd shims work. */
187
+ /**
188
+ * The real child process: stdio inherited, the environment unchanged. cross-spawn is plain child_process.spawn
189
+ * except on Windows, where it finds .cmd and .bat shims such as pi.cmd and escapes the arguments for them.
190
+ */
200
191
  export function spawnChild(program , args , options ) {
201
192
  // Ctrl-C belongs to Pi while it runs; this process waits for it instead of dying first.
202
193
  const ignore = () => {};
203
194
  process.on("SIGINT", ignore);
204
195
  return new Promise ((resolve) => {
205
- const child = nodeSpawn(program, args, options);
196
+ const child = crossSpawn(program, args, options);
206
197
  child.once("error", (error) => resolve({ status: null, error }));
207
198
  child.once("close", (status) => resolve({ status }));
208
199
  }).finally(() => process.off("SIGINT", ignore));
@@ -216,7 +207,6 @@ export function processIo(proc = process) {
216
207
  stderr: proc.stderr,
217
208
  env: proc.env,
218
209
  home: homedir(),
219
- platform: process.platform,
220
210
  spawn: spawnChild,
221
211
  exit: (code) => proc.exit(code),
222
212
  };
@@ -376,13 +366,9 @@ async function launch(name , args , dir , io , comm
376
366
  return io.exit(2);
377
367
  }
378
368
  const { program, args: programArgs } = launched;
379
- const windows = (io.platform ?? process.platform) === "win32";
380
- const options = { stdio: "inherit", shell: windows };
369
+ const options = { stdio: "inherit" };
381
370
  if (io.childEnv) options.env = io.childEnv;
382
- // With a shell, Node joins the program and arguments into one line without quoting them.
383
- const result = windows
384
- ? await io.spawn(quoteForCmd(program), programArgs.map(quoteForCmd), options)
385
- : await io.spawn(program, programArgs, options);
371
+ const result = await io.spawn(program, programArgs, options);
386
372
  if (result.error) {
387
373
  io.stderr.write(`pi-space: could not start ${program}: ${result.error.message}\n`);
388
374
  return io.exit(1);
@@ -395,6 +381,13 @@ async function pick(dir , io , commandSource )
395
381
  io.stderr.write(USAGE);
396
382
  return io.exit(2);
397
383
  }
384
+ // A bad command is reported before the list, not after the user has chosen.
385
+ try {
386
+ splitCommand(io.env.PI_SPACES_COMMAND ?? "");
387
+ } catch (error) {
388
+ io.stderr.write(`pi-space: ${commandSource}: ${(error ).message}.\n`);
389
+ return io.exit(2);
390
+ }
398
391
  const names = [BASE, ...listSpaces(dir)];
399
392
  io.stdout.write(`${[`Spaces in ${dir}:`, ...names.map((name, index) => `${index + 1}) ${name}`)].join("\n")}\nSpace number: `);
400
393
  const line = await readLine(io.stdin);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jals1212/pi-spaces-cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "The pi-space command: pick a space and start Pi in it. Companion to the Pi extension @jals1212/pi-spaces.",
5
5
  "license": "MIT",
6
6
  "author": "jals1212",
@@ -35,9 +35,10 @@
35
35
  "scripts": {
36
36
  "build": "node --disable-warning=ExperimentalWarning scripts/build.mjs",
37
37
  "prepack": "npm run build",
38
- "test": "node ../scripts/link-self.mjs && npm run build --prefix .. && npm run build && node --test 'test/*.test.ts'"
38
+ "test": "node ../scripts/link-self.mjs && npm run build --prefix .. && npm run build && node --test \"test/*.test.ts\""
39
39
  },
40
40
  "dependencies": {
41
+ "cross-spawn": "^7.0.6",
41
42
  "@jals1212/pi-spaces": "^0.2.0"
42
43
  },
43
44
  "publishConfig": {