sourcemonkey 0.0.0-stage → 0.5.0
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/LICENSE +21 -0
- package/README.md +87 -2
- package/dist/bytes.js +37 -0
- package/dist/channel-placeholder.js +5 -0
- package/dist/collection-scan.js +17 -0
- package/dist/collections.html +353 -0
- package/dist/compare.html +358 -0
- package/dist/composed-source.js +205 -0
- package/dist/connect-prompt.html +47 -0
- package/dist/debug/icons.html +211 -0
- package/dist/debug/storage.html +163 -0
- package/dist/debug-log.js +75 -0
- package/dist/diagnostic-location.js +64 -0
- package/dist/eval-hook.js +308 -0
- package/dist/extension/background.js +5263 -0
- package/dist/extension/channel.js +133 -0
- package/dist/extension/code-links.js +187 -0
- package/dist/extension/code-tabs.js +460 -0
- package/dist/extension/collection-dialog.js +619 -0
- package/dist/extension/collection-display.js +322 -0
- package/dist/extension/collections.js +2905 -0
- package/dist/extension/compare.js +867 -0
- package/dist/extension/concurrency.js +186 -0
- package/dist/extension/connect-grants.js +109 -0
- package/dist/extension/connect-prompt-page.js +70 -0
- package/dist/extension/connect-prompt.js +266 -0
- package/dist/extension/copy-button.js +63 -0
- package/dist/extension/copy-dialog.js +502 -0
- package/dist/extension/copy-preference.js +66 -0
- package/dist/extension/debug/icons.js +203 -0
- package/dist/extension/debug/storage.js +365 -0
- package/dist/extension/deep-link.js +77 -0
- package/dist/extension/delete-dialog.js +432 -0
- package/dist/extension/delete-icon.js +40 -0
- package/dist/extension/details-tooltips.js +66 -0
- package/dist/extension/directories.js +679 -0
- package/dist/extension/export-backup.js +407 -0
- package/dist/extension/export-dialog.js +142 -0
- package/dist/extension/file-access.js +74 -0
- package/dist/extension/file-changes.js +346 -0
- package/dist/extension/frame-info.js +85 -0
- package/dist/extension/github-provider.js +336 -0
- package/dist/extension/glyph.js +84 -0
- package/dist/extension/gm-bindings.js +601 -0
- package/dist/extension/gm-download.js +419 -0
- package/dist/extension/gm-menu.js +228 -0
- package/dist/extension/gm-notification.js +141 -0
- package/dist/extension/gm-originator-map.js +23 -0
- package/dist/extension/gm-tab-data.js +121 -0
- package/dist/extension/gm-tab.js +160 -0
- package/dist/extension/gm-url-change.js +111 -0
- package/dist/extension/gm-url-scheme.js +27 -0
- package/dist/extension/gm-values.js +176 -0
- package/dist/extension/gm-window-control.js +104 -0
- package/dist/extension/gm-xhr-headers.js +333 -0
- package/dist/extension/gm-xhr.js +584 -0
- package/dist/extension/injector.js +3145 -0
- package/dist/extension/install-capture.js +277 -0
- package/dist/extension/line-diff.js +233 -0
- package/dist/extension/local-copy.js +560 -0
- package/dist/extension/local-delete.js +276 -0
- package/dist/extension/location-kinds.js +108 -0
- package/dist/extension/log-format.js +158 -0
- package/dist/extension/managed-changes.js +361 -0
- package/dist/extension/managed-items.js +57 -0
- package/dist/extension/match-index.js +375 -0
- package/dist/extension/missing-scripts.js +66 -0
- package/dist/extension/more-menu.js +109 -0
- package/dist/extension/move-dialog.js +197 -0
- package/dist/extension/offscreen.js +37 -0
- package/dist/extension/options.js +504 -0
- package/dist/extension/page-heading.js +170 -0
- package/dist/extension/page-links.js +199 -0
- package/dist/extension/parse-check-client.js +70 -0
- package/dist/extension/parse-check.js +161 -0
- package/dist/extension/parse-sandbox-host.js +172 -0
- package/dist/extension/parse-sandbox.js +175 -0
- package/dist/extension/popup-commands-open.js +41 -0
- package/dist/extension/popup-view.js +387 -0
- package/dist/extension/popup.js +703 -0
- package/dist/extension/prism-userscript.js +53 -0
- package/dist/extension/refresh-error.js +136 -0
- package/dist/extension/refresh-targets.js +160 -0
- package/dist/extension/related-versions.js +1144 -0
- package/dist/extension/resize-observer-loop.js +19 -0
- package/dist/extension/row-cache.js +387 -0
- package/dist/extension/script-blobs.js +413 -0
- package/dist/extension/script-details.js +658 -0
- package/dist/extension/script-enablement.js +285 -0
- package/dist/extension/script-identity.js +310 -0
- package/dist/extension/script-keys.js +54 -0
- package/dist/extension/script-log-id.js +155 -0
- package/dist/extension/script-log.js +290 -0
- package/dist/extension/script-rejection.js +104 -0
- package/dist/extension/script-sites.js +158 -0
- package/dist/extension/script-store.js +3507 -0
- package/dist/extension/script-updater.js +991 -0
- package/dist/extension/script-url-hash.js +61 -0
- package/dist/extension/select-all.js +37 -0
- package/dist/extension/select-open-guard.js +90 -0
- package/dist/extension/site-icon.js +1261 -0
- package/dist/extension/sm-dev-link.js +302 -0
- package/dist/extension/solo-click.js +58 -0
- package/dist/extension/sticky-numbers.js +188 -0
- package/dist/extension/storage-breakdown.js +253 -0
- package/dist/extension/storage-scan.js +86 -0
- package/dist/extension/storage-usage.js +194 -0
- package/dist/extension/structural-keys.js +29 -0
- package/dist/extension/sw-teardown.js +36 -0
- package/dist/extension/tab-status.js +403 -0
- package/dist/extension/toolbar-summary.js +105 -0
- package/dist/extension/user-scripts-access.js +43 -0
- package/dist/extension/userscript.js +3672 -0
- package/dist/extension/value-store.js +204 -0
- package/dist/extension/version-probe-fetch.js +68 -0
- package/dist/extension/worker-client.js +109 -0
- package/dist/extension/worker-ops.js +171 -0
- package/dist/extension/zip-writer.js +24 -0
- package/dist/external-files.js +878 -0
- package/dist/file-loader.js +436 -0
- package/dist/file-locations.js +439 -0
- package/dist/generated-wrappers.js +5 -0
- package/dist/github-auth.js +148 -0
- package/dist/github-urls.js +46 -0
- package/dist/gm-api-catalog.js +217 -0
- package/dist/gm-connect.js +273 -0
- package/dist/gm-xhr-types.js +5 -0
- package/dist/http-read.js +142 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/local-file-overrides.js +558 -0
- package/dist/manifest.json +38 -0
- package/dist/markup-response.js +126 -0
- package/dist/match-targets.js +305 -0
- package/dist/menu-captions.js +22 -0
- package/dist/offscreen.html +39 -0
- package/dist/options.html +197 -0
- package/dist/parse-check-protocol.js +51 -0
- package/dist/parse-location.js +171 -0
- package/dist/parse-sandbox.html +56 -0
- package/dist/phase-timing.js +155 -0
- package/dist/popup.html +197 -0
- package/dist/public-suffixes.js +6957 -0
- package/dist/run-context.js +31 -0
- package/dist/runtime-messages.js +34 -0
- package/dist/sandboxed-page.js +35 -0
- package/dist/script-build.js +787 -0
- package/dist/script-display.js +383 -0
- package/dist/script-icon.js +43 -0
- package/dist/script-links.js +204 -0
- package/dist/script-source-url.js +214 -0
- package/dist/script-world.js +65 -0
- package/dist/sm-dev-protocol.js +84 -0
- package/dist/source-map.js +177 -0
- package/dist/stack-link.js +138 -0
- package/dist/styles.css +825 -0
- package/dist/unsafe-window-use.js +229 -0
- package/dist/url-match.js +734 -0
- package/dist/userscript-header.js +248 -0
- package/dist/userscript.html +1165 -0
- package/dist/vendor/fflate.LICENSE +21 -0
- package/dist/vendor/fflate.js +2692 -0
- package/dist/vendor/prism/prism-line-numbers.css +1 -0
- package/dist/vendor/prism/prism-line-numbers.js +1 -0
- package/dist/vendor/prism/prism.css +1 -0
- package/dist/vendor/prism/prism.js +1946 -0
- package/dist/version-compare.js +141 -0
- package/dist/version-probe.js +120 -0
- package/lib/build-info.json +1 -0
- package/lib/bytes.d.ts +3 -0
- package/lib/bytes.js +37 -0
- package/lib/channel-placeholder.d.ts +1 -0
- package/lib/channel-placeholder.js +5 -0
- package/lib/collection-scan.d.ts +8 -0
- package/lib/collection-scan.js +17 -0
- package/lib/composed-source.d.ts +28 -0
- package/lib/composed-source.js +205 -0
- package/lib/debug-log.d.ts +9 -0
- package/lib/debug-log.js +75 -0
- package/lib/diagnostic-location.d.ts +8 -0
- package/lib/diagnostic-location.js +64 -0
- package/lib/eval-hook.d.ts +34 -0
- package/lib/eval-hook.js +308 -0
- package/lib/external-files.d.ts +111 -0
- package/lib/external-files.js +878 -0
- package/lib/file-loader.d.ts +48 -0
- package/lib/file-loader.js +436 -0
- package/lib/file-locations.d.ts +44 -0
- package/lib/file-locations.js +439 -0
- package/lib/generated-wrappers.d.ts +11 -0
- package/lib/generated-wrappers.js +5 -0
- package/lib/github-auth.d.ts +12 -0
- package/lib/github-auth.js +148 -0
- package/lib/github-urls.d.ts +1 -0
- package/lib/github-urls.js +46 -0
- package/lib/gm-api-catalog.d.ts +24 -0
- package/lib/gm-api-catalog.js +217 -0
- package/lib/gm-connect.d.ts +34 -0
- package/lib/gm-connect.js +273 -0
- package/lib/gm-xhr-types.d.ts +68 -0
- package/lib/gm-xhr-types.js +5 -0
- package/lib/harness/browser-extensions.d.ts +73 -0
- package/lib/harness/browser-extensions.js +285 -0
- package/lib/harness/browser-lang.d.ts +20 -0
- package/lib/harness/browser-lang.js +86 -0
- package/lib/harness/browser-launch.d.ts +14 -0
- package/lib/harness/browser-launch.js +184 -0
- package/lib/harness/checks.d.ts +110 -0
- package/lib/harness/checks.js +321 -0
- package/lib/harness/cli.d.ts +2 -0
- package/lib/harness/cli.js +2259 -0
- package/lib/harness/command-args.d.ts +91 -0
- package/lib/harness/command-args.js +369 -0
- package/lib/harness/command-lines.d.ts +80 -0
- package/lib/harness/command-lines.js +180 -0
- package/lib/harness/command-list.d.ts +206 -0
- package/lib/harness/command-list.js +1475 -0
- package/lib/harness/console-commands.d.ts +463 -0
- package/lib/harness/console-commands.js +3216 -0
- package/lib/harness/download-watch.d.ts +21 -0
- package/lib/harness/download-watch.js +156 -0
- package/lib/harness/extension-backend.d.ts +41 -0
- package/lib/harness/extension-backend.js +100 -0
- package/lib/harness/extension-host.d.ts +112 -0
- package/lib/harness/extension-host.js +552 -0
- package/lib/harness/extension-launch.d.ts +67 -0
- package/lib/harness/extension-launch.js +285 -0
- package/lib/harness/extension-link.d.ts +315 -0
- package/lib/harness/extension-link.js +607 -0
- package/lib/harness/external-manager.d.ts +146 -0
- package/lib/harness/external-manager.js +414 -0
- package/lib/harness/fixture.d.ts +165 -0
- package/lib/harness/fixture.js +461 -0
- package/lib/harness/frame-sessions.d.ts +71 -0
- package/lib/harness/frame-sessions.js +248 -0
- package/lib/harness/frames.d.ts +68 -0
- package/lib/harness/frames.js +216 -0
- package/lib/harness/help-format.d.ts +17 -0
- package/lib/harness/help-format.js +127 -0
- package/lib/harness/host.d.ts +352 -0
- package/lib/harness/host.js +423 -0
- package/lib/harness/index.d.ts +8 -0
- package/lib/harness/index.js +10 -0
- package/lib/harness/input-file.d.ts +18 -0
- package/lib/harness/input-file.js +61 -0
- package/lib/harness/json-output.d.ts +565 -0
- package/lib/harness/json-output.js +71 -0
- package/lib/harness/manager-actions.d.ts +21 -0
- package/lib/harness/manager-actions.js +129 -0
- package/lib/harness/manager-commands.d.ts +142 -0
- package/lib/harness/manager-commands.js +1196 -0
- package/lib/harness/manager-fetch.d.ts +33 -0
- package/lib/harness/manager-fetch.js +239 -0
- package/lib/harness/managers.d.ts +24 -0
- package/lib/harness/managers.js +27 -0
- package/lib/harness/output-style.d.ts +125 -0
- package/lib/harness/output-style.js +322 -0
- package/lib/harness/page-commands.d.ts +134 -0
- package/lib/harness/page-commands.js +1141 -0
- package/lib/harness/page-output.d.ts +67 -0
- package/lib/harness/page-output.js +139 -0
- package/lib/harness/page-watch.d.ts +171 -0
- package/lib/harness/page-watch.js +607 -0
- package/lib/harness/parse-check-node.d.ts +3 -0
- package/lib/harness/parse-check-node.js +132 -0
- package/lib/harness/path-args.d.ts +22 -0
- package/lib/harness/path-args.js +148 -0
- package/lib/harness/playwright-chromium.d.ts +16 -0
- package/lib/harness/playwright-chromium.js +86 -0
- package/lib/harness/prepare.d.ts +168 -0
- package/lib/harness/prepare.js +364 -0
- package/lib/harness/prompt-editor.d.ts +17 -0
- package/lib/harness/prompt-editor.js +354 -0
- package/lib/harness/prompt-history.d.ts +13 -0
- package/lib/harness/prompt-history.js +89 -0
- package/lib/harness/rebuild-advice.d.ts +6 -0
- package/lib/harness/rebuild-advice.js +39 -0
- package/lib/harness/run-log.d.ts +47 -0
- package/lib/harness/run-log.js +140 -0
- package/lib/harness/run-logs.d.ts +132 -0
- package/lib/harness/run-logs.js +241 -0
- package/lib/harness/run.d.ts +194 -0
- package/lib/harness/run.js +1973 -0
- package/lib/harness/runs.d.ts +229 -0
- package/lib/harness/runs.js +726 -0
- package/lib/harness/save-html.d.ts +39 -0
- package/lib/harness/save-html.js +89 -0
- package/lib/harness/saved-pages.d.ts +120 -0
- package/lib/harness/saved-pages.js +275 -0
- package/lib/harness/script-mark.d.ts +17 -0
- package/lib/harness/script-mark.js +56 -0
- package/lib/harness/snapshot.d.ts +143 -0
- package/lib/harness/snapshot.js +474 -0
- package/lib/harness/stuck-tabs.d.ts +19 -0
- package/lib/harness/stuck-tabs.js +131 -0
- package/lib/harness/tab-refs.d.ts +20 -0
- package/lib/harness/tab-refs.js +80 -0
- package/lib/harness/tampermonkey.d.ts +71 -0
- package/lib/harness/tampermonkey.js +356 -0
- package/lib/harness/tm-ids.d.ts +18 -0
- package/lib/harness/tm-ids.js +88 -0
- package/lib/harness/violentmonkey.d.ts +34 -0
- package/lib/harness/violentmonkey.js +162 -0
- package/lib/harness/wait.d.ts +77 -0
- package/lib/harness/wait.js +458 -0
- package/lib/http-read.d.ts +30 -0
- package/lib/http-read.js +142 -0
- package/lib/local-file-overrides.d.ts +35 -0
- package/lib/local-file-overrides.js +558 -0
- package/lib/manifest.json +38 -0
- package/lib/markup-response.d.ts +11 -0
- package/lib/markup-response.js +126 -0
- package/lib/match-targets.d.ts +18 -0
- package/lib/match-targets.js +305 -0
- package/lib/menu-captions.d.ts +1 -0
- package/lib/menu-captions.js +22 -0
- package/lib/parse-check-protocol.d.ts +27 -0
- package/lib/parse-check-protocol.js +51 -0
- package/lib/parse-location.d.ts +12 -0
- package/lib/parse-location.js +171 -0
- package/lib/phase-timing.d.ts +12 -0
- package/lib/phase-timing.js +155 -0
- package/lib/public-suffixes.d.ts +1 -0
- package/lib/public-suffixes.js +6957 -0
- package/lib/run-context.d.ts +2 -0
- package/lib/run-context.js +31 -0
- package/lib/runtime-messages.d.ts +10 -0
- package/lib/runtime-messages.js +34 -0
- package/lib/sandboxed-page.d.ts +5 -0
- package/lib/sandboxed-page.js +35 -0
- package/lib/script-build.d.ts +111 -0
- package/lib/script-build.js +787 -0
- package/lib/script-display.d.ts +51 -0
- package/lib/script-display.js +383 -0
- package/lib/script-icon.d.ts +16 -0
- package/lib/script-icon.js +43 -0
- package/lib/script-links.d.ts +24 -0
- package/lib/script-links.js +204 -0
- package/lib/script-source-url.d.ts +8 -0
- package/lib/script-source-url.js +214 -0
- package/lib/script-world.d.ts +6 -0
- package/lib/script-world.js +65 -0
- package/lib/sm-dev-protocol.d.ts +251 -0
- package/lib/sm-dev-protocol.js +84 -0
- package/lib/source-map.d.ts +32 -0
- package/lib/source-map.js +177 -0
- package/lib/stack-link.d.ts +15 -0
- package/lib/stack-link.js +138 -0
- package/lib/unsafe-window-use.d.ts +1 -0
- package/lib/unsafe-window-use.js +229 -0
- package/lib/url-match.d.ts +40 -0
- package/lib/url-match.js +734 -0
- package/lib/userscript-header.d.ts +33 -0
- package/lib/userscript-header.js +248 -0
- package/lib/version-compare.d.ts +6 -0
- package/lib/version-compare.js +141 -0
- package/lib/version-probe.d.ts +17 -0
- package/lib/version-probe.js +120 -0
- package/package.json +55 -3
- package/skills/SourceMonkey-dev/SKILL.md +868 -0
- package/skills/SourceMonkey-dev/references/cdp.md +293 -0
- package/skills/SourceMonkey-dev/references/commands.md +297 -0
- package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
- package/skills/SourceMonkey-dev/references/specs.md +46 -0
- package/skills/SourceMonkey-friction/SKILL.md +103 -0
- package/skills/SourceMonkey-friction/references/template.md +59 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** A word of a line, where it is in the line, and whether it was quoted. */
|
|
2
|
+
export interface Word {
|
|
3
|
+
text: string;
|
|
4
|
+
start: number;
|
|
5
|
+
end: number;
|
|
6
|
+
/** Starts with a quote, so it's the word's content, never a flag. */
|
|
7
|
+
quoted: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Splits a typed line into words as a shell would: 'single' and
|
|
11
|
+
* "double" quotes group words, a backslash in double quotes escapes the
|
|
12
|
+
* next character. So a selector or text with spaces can be one word.
|
|
13
|
+
* Unlike a shell, quotes that open inside a word stay in it (they still
|
|
14
|
+
* keep its spaces together): they are the selector's own, as in
|
|
15
|
+
* `a[href="x.html"]`, which means something else without them.
|
|
16
|
+
*/
|
|
17
|
+
export declare function splitWords(line: string): Word[];
|
|
18
|
+
/**
|
|
19
|
+
* Text taken whole, as typed, spaces and all, unless it's one quoted
|
|
20
|
+
* span, which is unquoted: 'a b' or "a b" (a backslash escaping in
|
|
21
|
+
* double quotes). `single`: only single quotes, for JSON, whose strings
|
|
22
|
+
* are double-quoted.
|
|
23
|
+
*/
|
|
24
|
+
export declare function unquoteWhole(text: string, which?: 'any' | 'single'): {
|
|
25
|
+
text: string;
|
|
26
|
+
quoted: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** What a command's words hold, as its syntax reads them. */
|
|
29
|
+
export interface ParsedArgs {
|
|
30
|
+
/** Each flag given, by name: its value, or true. */
|
|
31
|
+
flags: Record<string, string | true>;
|
|
32
|
+
/** The tab that led, as written (`T2`, `targetId=...`). */
|
|
33
|
+
tab?: string;
|
|
34
|
+
/** The keyword of the form it took (`wait log`), if any. */
|
|
35
|
+
form?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The word before the form's keyword, for a form that names what it
|
|
38
|
+
* acts on first (`script E4 enable`): absent when it was left out.
|
|
39
|
+
*/
|
|
40
|
+
subject?: string;
|
|
41
|
+
/** Its arguments: all of them, or for text, the ones before it. */
|
|
42
|
+
words: string[];
|
|
43
|
+
/** For a text or selector syntax: the rest of the line, as its syntax unquotes it. */
|
|
44
|
+
text?: string;
|
|
45
|
+
/** The lines of a `{{` block, after the command's own. */
|
|
46
|
+
block?: string;
|
|
47
|
+
/** `--help` was given: show the command's help rather than run it. */
|
|
48
|
+
help?: true;
|
|
49
|
+
}
|
|
50
|
+
export type ParseResult = ParsedArgs | {
|
|
51
|
+
error: string;
|
|
52
|
+
flag?: string;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* A command's words read by its syntax, or what's wrong with them.
|
|
56
|
+
* `line`: the words after the command's name as typed (a block's lines
|
|
57
|
+
* after a line break), split here. `words`: the same as a sender's shell
|
|
58
|
+
* split them, for which quotes are already gone.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseCommandArgs(command: string, input: {
|
|
61
|
+
line: string;
|
|
62
|
+
} | {
|
|
63
|
+
words: string[];
|
|
64
|
+
}): ParseResult;
|
|
65
|
+
/**
|
|
66
|
+
* What `<command> ... --help` asks help for, from its parsed words: the
|
|
67
|
+
* subcommand named, `''` for the forms with none when they were given
|
|
68
|
+
* arguments (`script E4 --help`, `wait 2s --help`), or undefined for
|
|
69
|
+
* the whole command. An error for a word shaped like a subcommand's
|
|
70
|
+
* name that is none (`script savexx --help`), unless those forms spell
|
|
71
|
+
* it out (`wait all`). Another word, for a command with only
|
|
72
|
+
* subcommands, asks for the whole command (`collection C1 --help`).
|
|
73
|
+
*/
|
|
74
|
+
export declare function helpSubcommand(command: string, parsed: ParsedArgs): string | undefined | {
|
|
75
|
+
error: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* What `<command> <words> --help` asks help for: the command its words
|
|
79
|
+
* make it (`scripts E4 save` is `script`'s), and the subcommand, as
|
|
80
|
+
* `helpSubcommand` says. Words it can't read ask for the whole command.
|
|
81
|
+
*/
|
|
82
|
+
export declare function helpRequest(command: string, input: {
|
|
83
|
+
line: string;
|
|
84
|
+
} | {
|
|
85
|
+
words: string[];
|
|
86
|
+
}): {
|
|
87
|
+
command: string;
|
|
88
|
+
subcommand?: string;
|
|
89
|
+
} | {
|
|
90
|
+
error: string;
|
|
91
|
+
};
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
// Reading a command's words: its flags, a tab, its arguments, and a
|
|
2
|
+
// `{{` block. The one parser for every sm-dev command, sm-dev's own
|
|
3
|
+
// (start, stop, ...) and a run's (click, eval, ...), so flags and quotes
|
|
4
|
+
// mean the same thing everywhere.
|
|
5
|
+
//
|
|
6
|
+
// Each command declares its shape in its help entry (`syntax` in
|
|
7
|
+
// command-list.ts): what its arguments are, whether a tab can lead,
|
|
8
|
+
// whether it takes a block. Its flags, and which take a value, are its
|
|
9
|
+
// help's options (`--out FILE` takes one).
|
|
10
|
+
//
|
|
11
|
+
// - A flag is `--name`, or `--name value` / `--name=value` for one that
|
|
12
|
+
// takes a value. One whose value is optional (`--script[=<script>]`)
|
|
13
|
+
// takes it only as `--name=value`. An unknown flag, a value on one
|
|
14
|
+
// that takes none, and a flag given twice are refused.
|
|
15
|
+
// - Flags can go anywhere, a command's free text (eval's JavaScript)
|
|
16
|
+
// included: there, a word of its own shaped like one (`--name`,
|
|
17
|
+
// `--name=...`) is a flag, and an unknown or global one is refused
|
|
18
|
+
// rather than run as code. A `/regex/` starting the text is all text.
|
|
19
|
+
// - A quoted word is never a flag, so `'--x'` is an argument.
|
|
20
|
+
// - Each subcommand (`script save`) takes only its own flags and the
|
|
21
|
+
// command's shared ones, as its help lists them.
|
|
22
|
+
// - `--help`, where a flag can go, asks for the command's help, as
|
|
23
|
+
// `help <command>` does, rather than running it: the subcommand's,
|
|
24
|
+
// when one is named (`helpRequest`).
|
|
25
|
+
// - Arguments a command doesn't take are refused.
|
|
26
|
+
import { commandSyntax, GLOBAL_FLAGS, globalFlagMistake, hasPlainForm, noSuchFlag, noSuchSubcommand, plainFormWords, SAME_COMMANDS, subcommandsOf, TIMEOUT_FLAG, TIMEOUT_NEEDS_SECONDS, timeoutSecondsMs, } from './command-list.js';
|
|
27
|
+
import { TAB_ARG } from './tab-refs.js';
|
|
28
|
+
import { quoted } from './output-style.js';
|
|
29
|
+
/**
|
|
30
|
+
* Splits a typed line into words as a shell would: 'single' and
|
|
31
|
+
* "double" quotes group words, a backslash in double quotes escapes the
|
|
32
|
+
* next character. So a selector or text with spaces can be one word.
|
|
33
|
+
* Unlike a shell, quotes that open inside a word stay in it (they still
|
|
34
|
+
* keep its spaces together): they are the selector's own, as in
|
|
35
|
+
* `a[href="x.html"]`, which means something else without them.
|
|
36
|
+
*/
|
|
37
|
+
export function splitWords(line) {
|
|
38
|
+
const words = [];
|
|
39
|
+
let i = 0;
|
|
40
|
+
while (i < line.length) {
|
|
41
|
+
while (i < line.length && /\s/.test(line[i]))
|
|
42
|
+
i++;
|
|
43
|
+
if (i >= line.length)
|
|
44
|
+
break;
|
|
45
|
+
const start = i;
|
|
46
|
+
let text = '';
|
|
47
|
+
while (i < line.length && !/\s/.test(line[i])) {
|
|
48
|
+
const c = line[i];
|
|
49
|
+
const keep = i > start;
|
|
50
|
+
if (c === '\'') {
|
|
51
|
+
const close = line.indexOf(c, i + 1);
|
|
52
|
+
const stop = close < 0 ? line.length : close;
|
|
53
|
+
text += keep ? line.slice(i, stop + 1) : line.slice(i + 1, stop);
|
|
54
|
+
i = stop + 1;
|
|
55
|
+
}
|
|
56
|
+
else if (c === '"') {
|
|
57
|
+
// To the next unescaped quote, a backslash escaping what follows.
|
|
58
|
+
const open = i;
|
|
59
|
+
i++;
|
|
60
|
+
while (i < line.length && line[i] !== '"') {
|
|
61
|
+
if (line[i] === '\\' && i + 1 < line.length)
|
|
62
|
+
i++;
|
|
63
|
+
text += keep ? '' : line[i];
|
|
64
|
+
i++;
|
|
65
|
+
}
|
|
66
|
+
i++;
|
|
67
|
+
if (keep)
|
|
68
|
+
text += line.slice(open, Math.min(i, line.length));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
text += c;
|
|
72
|
+
i++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
words.push({ text, start, end: i, quoted: line[start] === '\'' || line[start] === '"' });
|
|
76
|
+
}
|
|
77
|
+
return words;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Text taken whole, as typed, spaces and all, unless it's one quoted
|
|
81
|
+
* span, which is unquoted: 'a b' or "a b" (a backslash escaping in
|
|
82
|
+
* double quotes). `single`: only single quotes, for JSON, whose strings
|
|
83
|
+
* are double-quoted.
|
|
84
|
+
*/
|
|
85
|
+
export function unquoteWhole(text, which = 'any') {
|
|
86
|
+
const trimmed = text.trim();
|
|
87
|
+
const single = /^'([^']*)'$/.exec(trimmed);
|
|
88
|
+
if (single)
|
|
89
|
+
return { text: single[1], quoted: true };
|
|
90
|
+
const double = which === 'any' ? /^"((?:[^"\\]|\\.)*)"$/.exec(trimmed) : null;
|
|
91
|
+
if (double)
|
|
92
|
+
return { text: double[1].replace(/\\(.)/g, '$1'), quoted: true };
|
|
93
|
+
return { text: trimmed, quoted: false };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A command's words read by its syntax, or what's wrong with them.
|
|
97
|
+
* `line`: the words after the command's name as typed (a block's lines
|
|
98
|
+
* after a line break), split here. `words`: the same as a sender's shell
|
|
99
|
+
* split them, for which quotes are already gone.
|
|
100
|
+
*/
|
|
101
|
+
export function parseCommandArgs(command, input) {
|
|
102
|
+
const syntax = commandSyntax(command);
|
|
103
|
+
let head;
|
|
104
|
+
let block;
|
|
105
|
+
let list;
|
|
106
|
+
const typed = 'line' in input;
|
|
107
|
+
if (typed) {
|
|
108
|
+
const at = input.line.indexOf('\n');
|
|
109
|
+
head = at < 0 ? input.line : input.line.slice(0, at);
|
|
110
|
+
block = at < 0 ? undefined : input.line.slice(at + 1);
|
|
111
|
+
list = splitWords(head);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
head = input.words.join(' ');
|
|
115
|
+
list = input.words.map((text) => ({ text, start: -1, end: -1, quoted: false }));
|
|
116
|
+
}
|
|
117
|
+
const parsed = { flags: {}, words: [] };
|
|
118
|
+
if (block !== undefined) {
|
|
119
|
+
if (!syntax.base.block)
|
|
120
|
+
return { error: `The ${quoted(command)} command takes no {{ block` };
|
|
121
|
+
parsed.block = block;
|
|
122
|
+
}
|
|
123
|
+
// Flags anywhere; the rest are arguments.
|
|
124
|
+
let shape = syntax.base;
|
|
125
|
+
const args = [];
|
|
126
|
+
// The arguments so far that are the command's own, past a tab, a
|
|
127
|
+
// form's keyword, and the subject before it.
|
|
128
|
+
const ownCount = () => args.length - (parsed.tab !== undefined ? 1 : 0) - (parsed.form !== undefined ? 1 : 0)
|
|
129
|
+
- (parsed.subject !== undefined ? 1 : 0);
|
|
130
|
+
// Once the text has started (its first word after the ones before
|
|
131
|
+
// it), only a word shaped like a flag is one, and none in a `/regex/`
|
|
132
|
+
// that starts it: up to word `regexEnd`.
|
|
133
|
+
let inText = false;
|
|
134
|
+
let regexEnd = -1;
|
|
135
|
+
for (let i = 0; i < list.length; i++) {
|
|
136
|
+
const word = list[i];
|
|
137
|
+
// In a command that takes text, only a flag-shaped word (the text's
|
|
138
|
+
// first word could be code); elsewhere any `--` word.
|
|
139
|
+
const flagShaped = shape.args === 'text' ? i > regexEnd && FLAG_WORD.test(word.text) : /^--./.test(word.text);
|
|
140
|
+
if (!word.quoted && flagShaped) {
|
|
141
|
+
if (word.text === '--help') {
|
|
142
|
+
parsed.help = true;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const taken = takeFlag(command, syntax, parsed, list, i);
|
|
146
|
+
if (typeof taken === 'object')
|
|
147
|
+
return taken;
|
|
148
|
+
i = taken;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// A tab first, before any other argument.
|
|
152
|
+
if (shape.tab && args.length === 0 && parsed.tab === undefined && !word.quoted && TAB_ARG.test(word.text)) {
|
|
153
|
+
parsed.tab = word.text;
|
|
154
|
+
args.push(word);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
// The form's keyword, first among the arguments after a tab, or
|
|
158
|
+
// second, after the subject, for a form that names one first.
|
|
159
|
+
if (parsed.form === undefined && !word.quoted && Object.hasOwn(syntax.forms, word.text)
|
|
160
|
+
&& (ownCount() === 0 || (ownCount() === 1 && syntax.subjectForms.has(word.text)))) {
|
|
161
|
+
if (ownCount() === 1)
|
|
162
|
+
parsed.subject = args[args.length - 1].text;
|
|
163
|
+
parsed.form = word.text;
|
|
164
|
+
shape = syntax.forms[word.text];
|
|
165
|
+
args.push(word);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (shape.args === 'text' && ownCount() >= (shape.before ?? 0) && !inText) {
|
|
169
|
+
inText = true;
|
|
170
|
+
// Text starting with a regex (`wait log /a --b/`): its words are
|
|
171
|
+
// its own, to the first word that closes it. Flags can follow it.
|
|
172
|
+
if (!word.quoted && word.text.startsWith('/')) {
|
|
173
|
+
for (let j = i; j < list.length; j++) {
|
|
174
|
+
const span = typed ? head.slice(word.start, list[j].end) : list.slice(i, j + 1).map((w) => w.text).join(' ');
|
|
175
|
+
if (REGEX_TEXT.test(span)) {
|
|
176
|
+
regexEnd = j;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
args.push(word);
|
|
183
|
+
}
|
|
184
|
+
const own = args.slice((parsed.tab !== undefined ? 1 : 0) + (parsed.form !== undefined ? 1 : 0) + (parsed.subject !== undefined ? 1 : 0));
|
|
185
|
+
// The verb first and what it acts on after (`script enable E4`), the
|
|
186
|
+
// other way round from how a subject form is written.
|
|
187
|
+
const max = shape.args === 'none' ? 0 : shape.args === 'words' ? shape.max : undefined;
|
|
188
|
+
if (parsed.form !== undefined && parsed.subject === undefined && syntax.subjectForms.has(parsed.form) && max !== undefined && own.length > max) {
|
|
189
|
+
return { error: `Name the ${command} before the verb: ${quoted(`${command} ${own[0].text} ${parsed.form}${own.length > 1 ? ' ...' : ''}`)}` };
|
|
190
|
+
}
|
|
191
|
+
switch (shape.args) {
|
|
192
|
+
case 'none':
|
|
193
|
+
if (own.length > 0)
|
|
194
|
+
return { error: `The ${quoted(command)} command takes ${shape.tab ? 'nothing besides a tab' : 'no arguments'}` };
|
|
195
|
+
break;
|
|
196
|
+
case 'words':
|
|
197
|
+
if (shape.max !== undefined && own.length > shape.max) {
|
|
198
|
+
const count = COUNTS[shape.max] ?? String(shape.max);
|
|
199
|
+
return { error: `The ${quoted(command)} command takes at most ${count} argument${shape.max === 1 ? '' : 's'}${shape.tab ? ' besides a tab' : ''} (${syntax.usage.join(' | ')})` };
|
|
200
|
+
}
|
|
201
|
+
parsed.words = own.map((w) => w.text);
|
|
202
|
+
break;
|
|
203
|
+
case 'selector': {
|
|
204
|
+
// As typed, less its flags and the words before it: quotes inside
|
|
205
|
+
// a selector are its own (`a[href="x"]`).
|
|
206
|
+
parsed.text = typed ? unquoteWhole(rawOf(head, own, list)).text : own.map((w) => w.text).join(' ');
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 'text': {
|
|
210
|
+
const before = shape.before ?? 0;
|
|
211
|
+
parsed.words = own.slice(0, before).map((w) => w.text);
|
|
212
|
+
const rest = own.slice(before);
|
|
213
|
+
let text = typed ? rawOf(head, rest, list) : rest.map((w) => w.text).join(' ');
|
|
214
|
+
if (typed && shape.unquote !== 'none')
|
|
215
|
+
text = unquoteWhole(text, shape.unquote).text;
|
|
216
|
+
parsed.text = text;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Each flag one the subcommand takes. Not for help, which a slip
|
|
221
|
+
// shouldn't stand in the way of.
|
|
222
|
+
if (!parsed.help) {
|
|
223
|
+
const { name, flags } = flagScope(command, syntax, parsed.form, true);
|
|
224
|
+
// One that doesn't list `--timeout-seconds` takes it as any command
|
|
225
|
+
// does: checked, then left out.
|
|
226
|
+
const timeout = parsed.flags[TIMEOUT_FLAG];
|
|
227
|
+
if (timeout !== undefined && !flags.includes(TIMEOUT_FLAG)) {
|
|
228
|
+
if (timeoutSecondsMs(timeout) === null)
|
|
229
|
+
return { error: TIMEOUT_NEEDS_SECONDS, flag: TIMEOUT_FLAG };
|
|
230
|
+
delete parsed.flags[TIMEOUT_FLAG];
|
|
231
|
+
}
|
|
232
|
+
const wrong = Object.keys(parsed.flags).find((flag) => !flags.includes(flag));
|
|
233
|
+
if (wrong !== undefined)
|
|
234
|
+
return { error: noSuchFlag(name, wrong, flags) + forOthers(command, syntax, wrong), flag: wrong };
|
|
235
|
+
}
|
|
236
|
+
return parsed;
|
|
237
|
+
}
|
|
238
|
+
// The flags `command` takes as its subcommand `form` (`script save`),
|
|
239
|
+
// and the name messages give it. With no subcommand named yet, any
|
|
240
|
+
// subcommand's, unless `final`: then those of its forms with none.
|
|
241
|
+
function flagScope(command, syntax, form, final = false) {
|
|
242
|
+
if (form !== undefined)
|
|
243
|
+
return { name: `${command} ${form}`, flags: syntax.formFlags[form] ?? [] };
|
|
244
|
+
return { name: command, flags: final || Object.keys(syntax.forms).length === 0 ? syntax.formFlags[''] : Object.keys(syntax.flags) };
|
|
245
|
+
}
|
|
246
|
+
// For a flag only other subcommands take, which they are: ` The
|
|
247
|
+
// `--frame` flag is for `wait selector` and `wait selector-gone`.`
|
|
248
|
+
function forOthers(command, syntax, flag) {
|
|
249
|
+
const takers = Object.keys(syntax.forms).filter((form) => syntax.formFlags[form]?.includes(flag)).map((form) => quoted(`${command} ${form}`));
|
|
250
|
+
if (takers.length === 0)
|
|
251
|
+
return '';
|
|
252
|
+
const list = takers.length === 1 ? takers[0] : `${takers.slice(0, -1).join(', ')} and ${takers.at(-1)}`;
|
|
253
|
+
return ` The ${quoted(flag)} flag is for ${list}.`;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* What `<command> ... --help` asks help for, from its parsed words: the
|
|
257
|
+
* subcommand named, `''` for the forms with none when they were given
|
|
258
|
+
* arguments (`script E4 --help`, `wait 2s --help`), or undefined for
|
|
259
|
+
* the whole command. An error for a word shaped like a subcommand's
|
|
260
|
+
* name that is none (`script savexx --help`), unless those forms spell
|
|
261
|
+
* it out (`wait all`). Another word, for a command with only
|
|
262
|
+
* subcommands, asks for the whole command (`collection C1 --help`).
|
|
263
|
+
*/
|
|
264
|
+
export function helpSubcommand(command, parsed) {
|
|
265
|
+
if (parsed.form !== undefined)
|
|
266
|
+
return parsed.form;
|
|
267
|
+
const given = parsed.words[0] ?? parsed.text?.split(/\s+/)[0];
|
|
268
|
+
if (!given || subcommandsOf(command).length === 0)
|
|
269
|
+
return undefined;
|
|
270
|
+
const named = /^[a-z][a-z-]*$/.test(given) && !plainFormWords(command).includes(given);
|
|
271
|
+
if (named)
|
|
272
|
+
return { error: noSuchSubcommand(command, given) };
|
|
273
|
+
// What a subcommand acts on (`collection C1 --help`), or the plain forms' argument.
|
|
274
|
+
return hasPlainForm(command) ? '' : undefined;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* What `<command> <words> --help` asks help for: the command its words
|
|
278
|
+
* make it (`scripts E4 save` is `script`'s), and the subcommand, as
|
|
279
|
+
* `helpSubcommand` says. Words it can't read ask for the whole command.
|
|
280
|
+
*/
|
|
281
|
+
export function helpRequest(command, input) {
|
|
282
|
+
for (const single of Object.keys(SAME_COMMANDS).filter((name) => SAME_COMMANDS[name] === command)) {
|
|
283
|
+
const parsed = parseCommandArgs(single, input);
|
|
284
|
+
if (!('error' in parsed) && parsed.form !== undefined)
|
|
285
|
+
return { command: single, subcommand: parsed.form };
|
|
286
|
+
}
|
|
287
|
+
const parsed = parseCommandArgs(command, input);
|
|
288
|
+
if ('error' in parsed)
|
|
289
|
+
return { command };
|
|
290
|
+
const subcommand = helpSubcommand(command, parsed);
|
|
291
|
+
if (typeof subcommand === 'object')
|
|
292
|
+
return subcommand;
|
|
293
|
+
return { command, ...(subcommand !== undefined ? { subcommand } : {}) };
|
|
294
|
+
}
|
|
295
|
+
// The flag at `list[i]`, recorded in `parsed`: the index of its last
|
|
296
|
+
// word, or what's wrong.
|
|
297
|
+
function takeFlag(command, syntax, parsed, list, i) {
|
|
298
|
+
const text = list[i].text;
|
|
299
|
+
const eq = text.indexOf('=');
|
|
300
|
+
const name = eq > 0 ? text.slice(0, eq) : text;
|
|
301
|
+
const kind = Object.hasOwn(syntax.flags, name) ? syntax.flags[name] : undefined;
|
|
302
|
+
// Any command takes `--timeout-seconds`, unlisted where it waits for
|
|
303
|
+
// nothing (`accept`), so a timeout given out of habit isn't a mistake.
|
|
304
|
+
// Checked, then left out.
|
|
305
|
+
if (!kind && name === TIMEOUT_FLAG) {
|
|
306
|
+
const value = eq > 0 ? text.slice(eq + 1) : list[i + 1]?.text;
|
|
307
|
+
if (value === undefined || timeoutSecondsMs(value) === null)
|
|
308
|
+
return { error: TIMEOUT_NEEDS_SECONDS, flag: name };
|
|
309
|
+
return eq > 0 ? i : i + 1;
|
|
310
|
+
}
|
|
311
|
+
if (!kind && GLOBAL_FLAGS.includes(name))
|
|
312
|
+
return { error: globalFlagMistake(name), flag: name };
|
|
313
|
+
if (!kind) {
|
|
314
|
+
const scope = flagScope(command, syntax, parsed.form);
|
|
315
|
+
return { error: noSuchFlag(scope.name, name, scope.flags), flag: name };
|
|
316
|
+
}
|
|
317
|
+
if (Object.hasOwn(parsed.flags, name))
|
|
318
|
+
return { error: `The ${name} flag can be given once`, flag: name };
|
|
319
|
+
if (kind === 'bool' || (kind === 'optional' && eq < 0)) {
|
|
320
|
+
if (eq > 0)
|
|
321
|
+
return { error: `The ${name} flag takes no value`, flag: name };
|
|
322
|
+
parsed.flags[name] = true;
|
|
323
|
+
return i;
|
|
324
|
+
}
|
|
325
|
+
const what = syntax.values[name];
|
|
326
|
+
const needsValue = {
|
|
327
|
+
error: `The ${quoted(name)} flag needs a value${what ? `: ${quoted(`${name}${kind === 'optional' ? '=' : ' '}${what}`)}` : ''}`,
|
|
328
|
+
flag: name,
|
|
329
|
+
};
|
|
330
|
+
if (eq > 0) {
|
|
331
|
+
// `--out=` gives none.
|
|
332
|
+
if (eq === text.length - 1)
|
|
333
|
+
return needsValue;
|
|
334
|
+
parsed.flags[name] = text.slice(eq + 1);
|
|
335
|
+
return i;
|
|
336
|
+
}
|
|
337
|
+
const value = list[i + 1];
|
|
338
|
+
// Not the next flag taken for its value; a quoted one can be.
|
|
339
|
+
if (value === undefined || value.text === '' || (!value.quoted && /^--./.test(value.text)))
|
|
340
|
+
return needsValue;
|
|
341
|
+
parsed.flags[name] = value.text;
|
|
342
|
+
return i + 1;
|
|
343
|
+
}
|
|
344
|
+
// The typed line from the first of `words` to the last, as typed: its
|
|
345
|
+
// quotes and spaces kept, the flags among them taken out.
|
|
346
|
+
function rawOf(head, words, all) {
|
|
347
|
+
if (words.length === 0)
|
|
348
|
+
return '';
|
|
349
|
+
const from = words[0].start;
|
|
350
|
+
const to = words[words.length - 1].end;
|
|
351
|
+
let text = '';
|
|
352
|
+
let at = from;
|
|
353
|
+
for (const word of all) {
|
|
354
|
+
if (word.start < from || word.end > to || words.includes(word))
|
|
355
|
+
continue;
|
|
356
|
+
// A flag (or its value) inside the span: left out, with the space
|
|
357
|
+
// before it, so `a --flag b` leaves `a b`.
|
|
358
|
+
text += head.slice(at, word.start).trimEnd();
|
|
359
|
+
at = word.end;
|
|
360
|
+
}
|
|
361
|
+
return (text + head.slice(at, to)).trim();
|
|
362
|
+
}
|
|
363
|
+
// A word in a command's text that is a flag: `--name`, `--name=...`.
|
|
364
|
+
// Code rarely has one (`--i` alone, say); quoting it keeps it text.
|
|
365
|
+
const FLAG_WORD = /^--[A-Za-z][\w-]*(?:=[\s\S]*)?$/;
|
|
366
|
+
// A regex, `/.../flags`.
|
|
367
|
+
const REGEX_TEXT = /^\/.+\/[a-z]*$/;
|
|
368
|
+
// How a message says a small count.
|
|
369
|
+
const COUNTS = ['no', 'one', 'two', 'three'];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** One command, ready for `runConsoleCommand`. */
|
|
2
|
+
export interface AssembledCommand {
|
|
3
|
+
/**
|
|
4
|
+
* The command as `runConsoleCommand` takes it. For a block, its first
|
|
5
|
+
* line without the `{{`, then the block's lines after a newline.
|
|
6
|
+
*/
|
|
7
|
+
text: string;
|
|
8
|
+
/** The lines it was written as, `{{` and `}}` included, for echoing. */
|
|
9
|
+
source: string[];
|
|
10
|
+
/** The line number (from 1) it started on. */
|
|
11
|
+
line: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A `{{` after a command that takes no block. Its lines up to `}}` are
|
|
15
|
+
* skipped, not run one by one as commands.
|
|
16
|
+
*/
|
|
17
|
+
export declare const NOT_A_BLOCK_COMMAND: string;
|
|
18
|
+
/**
|
|
19
|
+
* A `}}` line with more after it (`}} --nowait`). Only a line of just
|
|
20
|
+
* `}}` closes a block, so the line would otherwise be taken as the
|
|
21
|
+
* block's, leaving it open. Not `}});` or `}},`, which end JavaScript
|
|
22
|
+
* calls and JSON objects: only words after a space.
|
|
23
|
+
*/
|
|
24
|
+
export declare const TEXT_AFTER_CLOSE = "Nothing can follow }} on its line, so the block is dropped (put flags before the {{)";
|
|
25
|
+
/**
|
|
26
|
+
* A `{{` with code after it on its line (`eval {{ const x = 1`). The
|
|
27
|
+
* block's lines would otherwise each run as a command.
|
|
28
|
+
*/
|
|
29
|
+
export declare const OPEN_NOT_LAST = "A {{ block's content starts on the line after the {{, and its }} goes on a line of its own";
|
|
30
|
+
/** `a, b and c`. */
|
|
31
|
+
export declare function listed(names: string[]): string;
|
|
32
|
+
/** A block the input ended inside of. */
|
|
33
|
+
export declare function unclosedBlockMessage(line: number): string;
|
|
34
|
+
/**
|
|
35
|
+
* Collects lines into commands, one line at a time: each line gives a
|
|
36
|
+
* command, nothing (a blank, a comment, or a line inside a block), or
|
|
37
|
+
* an error for a line that can't be taken.
|
|
38
|
+
*/
|
|
39
|
+
export declare class CommandAssembler {
|
|
40
|
+
private block;
|
|
41
|
+
private refused;
|
|
42
|
+
private body;
|
|
43
|
+
private count;
|
|
44
|
+
/** Whether a block is open, waiting for its `}}`. */
|
|
45
|
+
get open(): boolean;
|
|
46
|
+
push(raw: string): {
|
|
47
|
+
command: AssembledCommand;
|
|
48
|
+
} | {
|
|
49
|
+
error: string;
|
|
50
|
+
} | null;
|
|
51
|
+
/**
|
|
52
|
+
* Drops an open block, returning the line it started on, or null when
|
|
53
|
+
* none was open.
|
|
54
|
+
*/
|
|
55
|
+
drop(): number | null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether the lines of `text` end outside a `{{` block, so are ready to
|
|
59
|
+
* run, rather than waiting for a `}}` line.
|
|
60
|
+
*/
|
|
61
|
+
export declare function endsOutsideBlock(text: string): boolean;
|
|
62
|
+
export declare const NONE_RUN = "None of the commands were run.";
|
|
63
|
+
/**
|
|
64
|
+
* A whole list of commands, as sent in one go or read from a file.
|
|
65
|
+
* Checked in full before any runs, so a mistake anywhere in it (a `{{`
|
|
66
|
+
* after the wrong command, a block never closed) runs none of it
|
|
67
|
+
* rather than half.
|
|
68
|
+
*/
|
|
69
|
+
export declare function parseCommandList(text: string): {
|
|
70
|
+
commands: AssembledCommand[];
|
|
71
|
+
} | {
|
|
72
|
+
error: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A command as it was written, for heading its output: `mark` before
|
|
76
|
+
* the first line and `...` before the rest, as the prompt shows them.
|
|
77
|
+
*/
|
|
78
|
+
export declare function echoCommand(command: AssembledCommand, mark?: string): string[];
|
|
79
|
+
/** A word as a shell would need it written, for echoing a command. */
|
|
80
|
+
export declare function shellWord(word: string): string;
|