@kaynooo/cli-kit 0.8.0 → 0.8.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.
- package/package.json +1 -1
- package/src/shell.ts +10 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaynooo/cli-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.1",
|
|
5
5
|
"description": "What every @kaynooo CLI shares: argument parsing with --help, a command dispatcher with typo hints and shell completion, and output formatting.",
|
|
6
6
|
"author": "Kaynooo <kaynooo@kevyn.fr>",
|
|
7
7
|
"license": "MIT",
|
package/src/shell.ts
CHANGED
|
@@ -11,6 +11,7 @@ const LEADING_TILDE = /^~(?=\/|$)/
|
|
|
11
11
|
const LEADING_TABS = /^\t+/
|
|
12
12
|
const OPENERS = /^[({]+/
|
|
13
13
|
const CLOSERS = /[)}]+$/
|
|
14
|
+
const DOUBLE_QUOTED_ESCAPES = new Set(['$', '`', '"', '\\'])
|
|
14
15
|
const HEREDOC = /^<<(-?)[ \t]*(?:'([^']*)'|"([^"]*)"|([^\s;&|<>()-][^\s;&|<>()]*))/
|
|
15
16
|
// Programs that run the command following them, which is the one that counts.
|
|
16
17
|
const WRAPPERS = new Set(['command', 'env', 'sudo', 'exec', 'nohup', 'time'])
|
|
@@ -276,7 +277,10 @@ export function words(text: string): Word[] {
|
|
|
276
277
|
|
|
277
278
|
isStarted = true
|
|
278
279
|
|
|
279
|
-
|
|
280
|
+
// within double quotes a backslash escapes only `$`, a backtick, `"` and itself, and stays before anything else (`"v\d"`)
|
|
281
|
+
if (char === '\\' && quote === '"' && !DOUBLE_QUOTED_ESCAPES.has(text[i + 1] ?? ''))
|
|
282
|
+
current += char
|
|
283
|
+
else if (char === '\\' && quote !== '\'')
|
|
280
284
|
current += text[++i] ?? ''
|
|
281
285
|
else if (quote !== null && char === quote)
|
|
282
286
|
quote = null
|
|
@@ -329,8 +333,11 @@ export function parseCommand(text: string): Invocation {
|
|
|
329
333
|
break
|
|
330
334
|
}
|
|
331
335
|
}
|
|
332
|
-
// the closing of a subshell or a group, `(git stash)` or `{ cd x && npm i; }`, ends the last word
|
|
333
|
-
const
|
|
336
|
+
// the closing of a subshell or a group, `(git stash)` or `{ cd x && npm i; }`, ends the last word; a closer inside quotes (`-e "f(g(x))"`) is the word's own
|
|
337
|
+
const closers = CLOSERS.exec(text.trimEnd())?.[0].length ?? 0
|
|
338
|
+
const word = tokens.at(-1) ?? ''
|
|
339
|
+
const trimmed = word.length - (CLOSERS.exec(word)?.[0].length ?? 0)
|
|
340
|
+
const last = word.slice(0, Math.max(trimmed, word.length - closers))
|
|
334
341
|
|
|
335
342
|
if (tokens.length > 0)
|
|
336
343
|
tokens.splice(-1, 1, ...(last === '' ? [] : [last]))
|