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,354 @@
|
|
|
1
|
+
// Multi-line editing for the `--interactive` prompt. readline edits one
|
|
2
|
+
// line, but a `{{` block is several: here the whole block is one buffer
|
|
3
|
+
// holding newlines, typed and edited in place, and sent once complete.
|
|
4
|
+
//
|
|
5
|
+
// - Enter inserts a newline while the buffer holds an unclosed block,
|
|
6
|
+
// and sends it otherwise. Alt-Enter always inserts one.
|
|
7
|
+
// - Lines after the first are drawn after `... `.
|
|
8
|
+
// - A buffer taller than the terminal is drawn as a window of rows
|
|
9
|
+
// around the cursor, scrolled as it moves, and drawn whole once sent.
|
|
10
|
+
// - Up and Down move between the buffer's lines, and step through the
|
|
11
|
+
// history from its first and last line. Once they have brought back
|
|
12
|
+
// an entry, they step whole entries until another key is pressed, so
|
|
13
|
+
// a block is passed over in one step. Ctrl-P / Ctrl-N always do.
|
|
14
|
+
// - Home / End and Ctrl-A / Ctrl-E go to the start and end of the line,
|
|
15
|
+
// Ctrl-U and Ctrl-K delete to them (Ctrl-Y brings it back).
|
|
16
|
+
// - Esc clears the buffer, as Ctrl-C does.
|
|
17
|
+
// - With `paint`, the prompts and the typed text are drawn in color.
|
|
18
|
+
//
|
|
19
|
+
// readline has no hooks for this. It calls these methods through the
|
|
20
|
+
// instance (`_ttyWrite` for each key, `_refreshLine` to redraw,
|
|
21
|
+
// `getCursorPos` for where the cursor is drawn), so they are replaced
|
|
22
|
+
// on it. Its undo and kill ring are only reachable by symbol. All are
|
|
23
|
+
// internal, kept by Node for compatibility; checked on Node 22.
|
|
24
|
+
import readline from 'node:readline';
|
|
25
|
+
/**
|
|
26
|
+
* Makes `rl` edit several lines as one buffer. `complete` says whether
|
|
27
|
+
* a buffer is ready to send, rather than inside an unclosed block.
|
|
28
|
+
* `cleared` gets the text of a buffer emptied by `clear`. `paint`
|
|
29
|
+
* colors the prompts and the typed text as they are drawn.
|
|
30
|
+
*/
|
|
31
|
+
export function editMultiLine(rl, continuation, complete, cleared, paint) {
|
|
32
|
+
const r = rl;
|
|
33
|
+
const ttyWrite = r._ttyWrite.bind(r);
|
|
34
|
+
const beforeEdit = internal(r, '_beforeEdit');
|
|
35
|
+
const pushToKillRing = internal(r, '_pushToKillRing');
|
|
36
|
+
const shown = (text) => text.replaceAll('\n', '\n' + continuation);
|
|
37
|
+
// Screen columns, by readline's own measure of one character.
|
|
38
|
+
const widths = new Map();
|
|
39
|
+
const charWidth = (ch, col) => {
|
|
40
|
+
if (ch === '\t')
|
|
41
|
+
return r.tabSize - (col % r.tabSize);
|
|
42
|
+
let width = widths.get(ch);
|
|
43
|
+
if (width === undefined)
|
|
44
|
+
widths.set(ch, (width = r._getDisplayPos(ch).cols));
|
|
45
|
+
return width;
|
|
46
|
+
};
|
|
47
|
+
const textWidth = (text) => {
|
|
48
|
+
let width = 0;
|
|
49
|
+
for (const ch of text)
|
|
50
|
+
width += charWidth(ch, width);
|
|
51
|
+
return width;
|
|
52
|
+
};
|
|
53
|
+
// The screen rows `text` takes from column 0, as the terminal wraps
|
|
54
|
+
// it, and the row and column just after it. A full row is followed by
|
|
55
|
+
// an empty one, where the cursor goes, as readline counts it. A wide
|
|
56
|
+
// character that doesn't fit at a row's end starts the next row.
|
|
57
|
+
// `starts`: where in `text` each row starts, for painting it.
|
|
58
|
+
const layout = (text) => {
|
|
59
|
+
const width = r.columns;
|
|
60
|
+
const rows = [''];
|
|
61
|
+
const starts = [0];
|
|
62
|
+
let col = 0;
|
|
63
|
+
let at = 0;
|
|
64
|
+
const newRow = (start) => {
|
|
65
|
+
rows.push('');
|
|
66
|
+
starts.push(start);
|
|
67
|
+
col = 0;
|
|
68
|
+
};
|
|
69
|
+
for (const ch of text) {
|
|
70
|
+
const next = at + ch.length;
|
|
71
|
+
if (ch === '\n') {
|
|
72
|
+
newRow(next);
|
|
73
|
+
at = next;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const w = charWidth(ch, col);
|
|
77
|
+
if (col + w > width)
|
|
78
|
+
newRow(at);
|
|
79
|
+
rows[rows.length - 1] += ch;
|
|
80
|
+
col += w;
|
|
81
|
+
at = next;
|
|
82
|
+
if (col >= width)
|
|
83
|
+
newRow(at);
|
|
84
|
+
}
|
|
85
|
+
return { rows, starts, row: rows.length - 1, col };
|
|
86
|
+
};
|
|
87
|
+
// The rows of `text` (a prompt, then the shown buffer) in color: the
|
|
88
|
+
// prompt and each `... ` as prompts, the rest as typed text.
|
|
89
|
+
const painted = (text, rows, starts) => {
|
|
90
|
+
if (!paint)
|
|
91
|
+
return rows;
|
|
92
|
+
const isPrompt = new Array(text.length).fill(false);
|
|
93
|
+
const mark = (from, length) => {
|
|
94
|
+
for (let i = from; i < from + length && i < text.length; i++)
|
|
95
|
+
isPrompt[i] = true;
|
|
96
|
+
};
|
|
97
|
+
mark(0, r.getPrompt().length);
|
|
98
|
+
for (let i = text.indexOf('\n'); i >= 0; i = text.indexOf('\n', i + 1))
|
|
99
|
+
mark(i + 1, continuation.length);
|
|
100
|
+
return rows.map((row, n) => {
|
|
101
|
+
let out = '';
|
|
102
|
+
let run = '';
|
|
103
|
+
let prompt = false;
|
|
104
|
+
const flush = () => {
|
|
105
|
+
if (run)
|
|
106
|
+
out += prompt ? paint.prompt(run) : paint.text(run);
|
|
107
|
+
run = '';
|
|
108
|
+
};
|
|
109
|
+
let at = starts[n];
|
|
110
|
+
for (const ch of row) {
|
|
111
|
+
if (isPrompt[at] !== prompt) {
|
|
112
|
+
flush();
|
|
113
|
+
prompt = isPrompt[at];
|
|
114
|
+
}
|
|
115
|
+
run += ch;
|
|
116
|
+
at += ch.length;
|
|
117
|
+
}
|
|
118
|
+
flush();
|
|
119
|
+
return out;
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
// The first buffer row drawn, when it is taller than the terminal.
|
|
123
|
+
let top = 0;
|
|
124
|
+
// Set while a sent buffer is drawn whole.
|
|
125
|
+
let whole = false;
|
|
126
|
+
const cursorAt = () => layout(r.getPrompt() + shown(r.line.slice(0, r.cursor)));
|
|
127
|
+
// Rows count from the top row drawn, as readline and writeOutputLine
|
|
128
|
+
// take them.
|
|
129
|
+
r.getCursorPos = () => {
|
|
130
|
+
const at = cursorAt();
|
|
131
|
+
return { rows: at.row - top, cols: at.col };
|
|
132
|
+
};
|
|
133
|
+
// readline's own redraw, of the shown text and only the rows that fit.
|
|
134
|
+
r._refreshLine = () => {
|
|
135
|
+
const text = r.getPrompt() + shown(r.line);
|
|
136
|
+
const all = layout(text);
|
|
137
|
+
const at = cursorAt();
|
|
138
|
+
// One row spare, so the window never scrolls the terminal itself.
|
|
139
|
+
const height = whole ? Infinity : Math.max(1, (r.output.rows || 24) - 1);
|
|
140
|
+
if (all.rows.length <= height)
|
|
141
|
+
top = 0;
|
|
142
|
+
else {
|
|
143
|
+
if (at.row < top)
|
|
144
|
+
top = at.row;
|
|
145
|
+
if (at.row >= top + height)
|
|
146
|
+
top = at.row - height + 1;
|
|
147
|
+
top = Math.min(top, all.rows.length - height);
|
|
148
|
+
}
|
|
149
|
+
const rows = painted(text, all.rows, all.starts).slice(top, top + height);
|
|
150
|
+
const out = r.output;
|
|
151
|
+
if (r.prevRows)
|
|
152
|
+
readline.moveCursor(out, 0, -r.prevRows);
|
|
153
|
+
readline.cursorTo(out, 0);
|
|
154
|
+
readline.clearScreenDown(out);
|
|
155
|
+
// Rows are ended here rather than wrapped by the terminal, so where
|
|
156
|
+
// each starts doesn't depend on how the terminal wraps.
|
|
157
|
+
r._writeToOutput(rows.join('\r\n'));
|
|
158
|
+
readline.cursorTo(out, at.col);
|
|
159
|
+
const below = rows.length - 1 - (at.row - top);
|
|
160
|
+
if (below > 0)
|
|
161
|
+
readline.moveCursor(out, 0, -below);
|
|
162
|
+
r.prevRows = at.row - top;
|
|
163
|
+
};
|
|
164
|
+
const set = (text, cursor = text.length) => {
|
|
165
|
+
r.line = text;
|
|
166
|
+
r.cursor = cursor;
|
|
167
|
+
r._refreshLine();
|
|
168
|
+
};
|
|
169
|
+
// A change readline's undo (Ctrl-_) can take back, and deleted text
|
|
170
|
+
// its Ctrl-Y can bring back, as with its own edits.
|
|
171
|
+
const edit = (text, cursor, deleted) => {
|
|
172
|
+
beforeEdit(r.line, r.cursor);
|
|
173
|
+
if (deleted)
|
|
174
|
+
pushToKillRing(deleted);
|
|
175
|
+
set(text, cursor);
|
|
176
|
+
};
|
|
177
|
+
const insert = (text) => edit(r.line.slice(0, r.cursor) + text + r.line.slice(r.cursor), r.cursor + text.length);
|
|
178
|
+
// The start and end of the line holding `at` in the buffer.
|
|
179
|
+
const lineStart = (at = r.cursor) => (at === 0 ? 0 : r.line.lastIndexOf('\n', at - 1) + 1);
|
|
180
|
+
const lineEnd = (at = r.cursor) => {
|
|
181
|
+
const i = r.line.indexOf('\n', at);
|
|
182
|
+
return i < 0 ? r.line.length : i;
|
|
183
|
+
};
|
|
184
|
+
// The prompt's width before the line starting at `start`.
|
|
185
|
+
const promptWidth = (start) => textWidth(start === 0 ? r.getPrompt() : continuation);
|
|
186
|
+
// Up or Down a line, keeping the cursor's column on screen, and
|
|
187
|
+
// between characters. False when there is no line that way.
|
|
188
|
+
const moveLine = (up) => {
|
|
189
|
+
const start = lineStart();
|
|
190
|
+
if (up ? start === 0 : lineEnd() === r.line.length)
|
|
191
|
+
return false;
|
|
192
|
+
// Measured with the prompt, as tabs stop at screen columns.
|
|
193
|
+
const column = textWidth((start === 0 ? r.getPrompt() : continuation) + r.line.slice(start, r.cursor));
|
|
194
|
+
const target = up ? lineStart(start - 1) : lineEnd() + 1;
|
|
195
|
+
let at = target;
|
|
196
|
+
let col = promptWidth(target);
|
|
197
|
+
for (const ch of r.line.slice(target, lineEnd(target))) {
|
|
198
|
+
const w = charWidth(ch, col);
|
|
199
|
+
if (col + w > column)
|
|
200
|
+
break;
|
|
201
|
+
col += w;
|
|
202
|
+
at += ch.length;
|
|
203
|
+
}
|
|
204
|
+
set(r.line, at);
|
|
205
|
+
return true;
|
|
206
|
+
};
|
|
207
|
+
// The history, browsed here rather than by readline, which would
|
|
208
|
+
// replace a buffer with the text before the cursor when no older
|
|
209
|
+
// entry starts with it, and can't give back what was being typed.
|
|
210
|
+
// `index` is the entry shown, -1 for what was being typed (`draft`).
|
|
211
|
+
// Any other key makes the buffer, edited or not, the draft again. As
|
|
212
|
+
// readline does, a one-line draft only finds entries starting with
|
|
213
|
+
// its text before the cursor.
|
|
214
|
+
let index = -1;
|
|
215
|
+
let draft = '';
|
|
216
|
+
let prefix = '';
|
|
217
|
+
// Up / Down last brought back an entry, or the draft, and no other
|
|
218
|
+
// key since.
|
|
219
|
+
let browsing = false;
|
|
220
|
+
const browse = (older) => {
|
|
221
|
+
const entries = r.history;
|
|
222
|
+
if (index === -1) {
|
|
223
|
+
if (!older)
|
|
224
|
+
return;
|
|
225
|
+
draft = r.line;
|
|
226
|
+
prefix = draft.includes('\n') ? '' : draft.slice(0, r.cursor);
|
|
227
|
+
}
|
|
228
|
+
for (let i = index + (older ? 1 : -1); older ? i < entries.length : i >= 0; i += older ? 1 : -1) {
|
|
229
|
+
if (entries[i].startsWith(prefix) && entries[i] !== r.line) {
|
|
230
|
+
index = i;
|
|
231
|
+
browsing = true;
|
|
232
|
+
edit(entries[i], entries[i].length);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (!older) {
|
|
237
|
+
index = -1;
|
|
238
|
+
browsing = true;
|
|
239
|
+
edit(draft, draft.length);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
function clear() {
|
|
243
|
+
if (r.line)
|
|
244
|
+
cleared?.(r.line);
|
|
245
|
+
index = -1;
|
|
246
|
+
browsing = false;
|
|
247
|
+
edit('', 0);
|
|
248
|
+
}
|
|
249
|
+
// When the last key was Enter, for the \n of a \r\n pair.
|
|
250
|
+
let returnAt = 0;
|
|
251
|
+
// Pasted text put in the buffer but not yet drawn.
|
|
252
|
+
let undrawn = false;
|
|
253
|
+
r._ttyWrite = (s, key) => {
|
|
254
|
+
const name = key?.name;
|
|
255
|
+
if (name === 'enter' && returnAt && Date.now() - returnAt <= r.crlfDelay) {
|
|
256
|
+
returnAt = 0;
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
returnAt = name === 'return' ? Date.now() : 0;
|
|
260
|
+
const enter = name === 'return' || name === 'enter';
|
|
261
|
+
// Shift is let through: readline's own Shift-Up would browse the
|
|
262
|
+
// history its way.
|
|
263
|
+
const plain = !key?.ctrl && !key?.meta;
|
|
264
|
+
const arrow = (name === 'up' || name === 'down') && plain;
|
|
265
|
+
const historyKey = arrow || (key?.ctrl && !key.meta && (name === 'p' || name === 'n'));
|
|
266
|
+
if (!historyKey) {
|
|
267
|
+
browsing = false;
|
|
268
|
+
index = -1;
|
|
269
|
+
}
|
|
270
|
+
// readline turns `isCompletionEnabled` off for all but the last key
|
|
271
|
+
// of pasted text, and then writes each character straight out with
|
|
272
|
+
// no redraw, even when the line wraps, so its record of the rows
|
|
273
|
+
// drawn (`prevRows`) goes stale. So pasted text, and the newlines
|
|
274
|
+
// within a block, go in the buffer here, drawn once at the end.
|
|
275
|
+
const typed = typeof s === 'string' && s !== '' && !/[\x00-\x08\x0a-\x1f\x7f]/.test(s) && plain;
|
|
276
|
+
if (!r.isCompletionEnabled && (typed || (enter && plain && !complete(r.line)))) {
|
|
277
|
+
if (!undrawn)
|
|
278
|
+
beforeEdit(r.line, r.cursor);
|
|
279
|
+
const text = enter ? '\n' : s;
|
|
280
|
+
r.line = r.line.slice(0, r.cursor) + text + r.line.slice(r.cursor);
|
|
281
|
+
r.cursor += text.length;
|
|
282
|
+
undrawn = true;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (undrawn) {
|
|
286
|
+
undrawn = false;
|
|
287
|
+
r._refreshLine();
|
|
288
|
+
}
|
|
289
|
+
if (enter) {
|
|
290
|
+
if (key?.meta || !complete(r.line)) {
|
|
291
|
+
insert('\n');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// Drawn whole, cursor at the end, so the terminal's scrollback
|
|
295
|
+
// keeps all of what was sent.
|
|
296
|
+
whole = true;
|
|
297
|
+
r.cursor = r.line.length;
|
|
298
|
+
r._refreshLine();
|
|
299
|
+
ttyWrite(s, key);
|
|
300
|
+
whole = false;
|
|
301
|
+
top = 0;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (arrow) {
|
|
305
|
+
if (browsing || !moveLine(name === 'up'))
|
|
306
|
+
browse(name === 'up');
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (historyKey) {
|
|
310
|
+
browse(name === 'p');
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (name === 'escape') {
|
|
314
|
+
clear();
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if ((name === 'home' && plain) || (key?.ctrl && name === 'a')) {
|
|
318
|
+
set(r.line, lineStart());
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if ((name === 'end' && plain) || (key?.ctrl && name === 'e')) {
|
|
322
|
+
set(r.line, lineEnd());
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (key?.ctrl && name === 'u') {
|
|
326
|
+
const start = lineStart();
|
|
327
|
+
edit(r.line.slice(0, start) + r.line.slice(r.cursor), start, r.line.slice(start, r.cursor));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
// At a line's end, Ctrl-K joins the next line onto it, as in Emacs.
|
|
331
|
+
if (key?.ctrl && name === 'k') {
|
|
332
|
+
const end = r.cursor === lineEnd() && r.cursor < r.line.length ? r.cursor + 1 : lineEnd();
|
|
333
|
+
edit(r.line.slice(0, r.cursor) + r.line.slice(end), r.cursor, r.line.slice(r.cursor, end));
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// Typed at the buffer's end, readline writes the text straight out
|
|
337
|
+
// with no redraw, so in color it is redrawn to take the typed color.
|
|
338
|
+
const atEnd = typed && r.cursor === r.line.length;
|
|
339
|
+
ttyWrite(s, key);
|
|
340
|
+
if (paint && atEnd)
|
|
341
|
+
r._refreshLine();
|
|
342
|
+
};
|
|
343
|
+
return { clear };
|
|
344
|
+
}
|
|
345
|
+
// A readline method kept under a symbol, found by its name, or one that
|
|
346
|
+
// does nothing should a Node version not have it.
|
|
347
|
+
function internal(rl, name) {
|
|
348
|
+
for (let proto = Object.getPrototypeOf(rl); proto; proto = Object.getPrototypeOf(proto)) {
|
|
349
|
+
const symbol = Object.getOwnPropertySymbols(proto).find((s) => s.description === name);
|
|
350
|
+
if (symbol)
|
|
351
|
+
return (...args) => rl[symbol](...args);
|
|
352
|
+
}
|
|
353
|
+
return () => undefined;
|
|
354
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** How many entries a session loads, and the file keeps. */
|
|
2
|
+
export declare const HISTORY_SIZE = 1000;
|
|
3
|
+
/** The history file, or null when history isn't kept. */
|
|
4
|
+
export declare function historyFile(): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* The entries in the file's last `HISTORY_SIZE` lines, newest first, as
|
|
7
|
+
* readline takes them. A missing or unreadable file is no history.
|
|
8
|
+
* The file is cut back to that many lines once it holds twice as many,
|
|
9
|
+
* since each session only appends to it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadHistory(file: string): string[];
|
|
12
|
+
/** Adds an entry to the end of the file. Throws when it can't. */
|
|
13
|
+
export declare function appendHistory(file: string, entry: string): void;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// The `--interactive` prompt's history, kept across sessions in
|
|
2
|
+
// ~/.sm-dev-history (or `SM_DEV_HISTORY`; set it empty for none).
|
|
3
|
+
//
|
|
4
|
+
// As in a shell with `histappend`, sessions share the file without
|
|
5
|
+
// overwriting each other: each loads it when it starts, and appends
|
|
6
|
+
// its own commands as they are typed. A session doesn't see another's
|
|
7
|
+
// commands until it is restarted.
|
|
8
|
+
//
|
|
9
|
+
// One entry per line, as a JSON string, since a `{{` block is one
|
|
10
|
+
// entry of several lines.
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
/** How many entries a session loads, and the file keeps. */
|
|
15
|
+
export const HISTORY_SIZE = 1000;
|
|
16
|
+
/** The history file, or null when history isn't kept. */
|
|
17
|
+
export function historyFile() {
|
|
18
|
+
const chosen = process.env.SM_DEV_HISTORY;
|
|
19
|
+
if (chosen !== undefined)
|
|
20
|
+
return chosen.trim() ? path.resolve(chosen.trim()) : null;
|
|
21
|
+
return path.join(os.homedir(), '.sm-dev-history');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The entries in the file's last `HISTORY_SIZE` lines, newest first, as
|
|
25
|
+
* readline takes them. A missing or unreadable file is no history.
|
|
26
|
+
* The file is cut back to that many lines once it holds twice as many,
|
|
27
|
+
* since each session only appends to it.
|
|
28
|
+
*/
|
|
29
|
+
export function loadHistory(file) {
|
|
30
|
+
let text;
|
|
31
|
+
try {
|
|
32
|
+
text = fs.readFileSync(file, 'utf8');
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const lines = text.split('\n').filter(Boolean);
|
|
38
|
+
const entries = [];
|
|
39
|
+
for (const line of lines.slice(-HISTORY_SIZE)) {
|
|
40
|
+
try {
|
|
41
|
+
const entry = JSON.parse(line);
|
|
42
|
+
if (typeof entry === 'string' && entry !== entries.at(-1))
|
|
43
|
+
entries.push(entry);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// A line cut short by a crash mid-write: skipped.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
if (lines.length >= 2 * HISTORY_SIZE) {
|
|
51
|
+
// Written aside and renamed, so a session reading the file never
|
|
52
|
+
// sees half of it. One appending meanwhile loses that entry.
|
|
53
|
+
const temp = `${file}.${process.pid}.tmp`;
|
|
54
|
+
try {
|
|
55
|
+
writePrivate(temp, lines.slice(-HISTORY_SIZE).join('\n') + '\n', 'w');
|
|
56
|
+
fs.renameSync(temp, file);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
fs.rmSync(temp, { force: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else if (text && !text.endsWith('\n')) {
|
|
63
|
+
// End a cut-short line, so the next entry doesn't join it.
|
|
64
|
+
writePrivate(file, '\n', 'a');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Tidying only. A file that can't be written is reported by the
|
|
69
|
+
// first appendHistory.
|
|
70
|
+
}
|
|
71
|
+
return entries.reverse();
|
|
72
|
+
}
|
|
73
|
+
/** Adds an entry to the end of the file. Throws when it can't. */
|
|
74
|
+
export function appendHistory(file, entry) {
|
|
75
|
+
writePrivate(file, JSON.stringify(entry) + '\n', 'a');
|
|
76
|
+
}
|
|
77
|
+
// Every write of the file goes through here, so it stays readable only
|
|
78
|
+
// by its owner: commands can hold passwords (`type`) and tokens. A
|
|
79
|
+
// file's mode is only set when it is made, so it is set again here.
|
|
80
|
+
function writePrivate(file, text, flag) {
|
|
81
|
+
const fd = fs.openSync(file, flag, 0o600);
|
|
82
|
+
try {
|
|
83
|
+
fs.fchmodSync(fd, 0o600);
|
|
84
|
+
fs.writeSync(fd, text);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
fs.closeSync(fd);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// How to bring this sm-dev up to date, for messages that need it.
|
|
2
|
+
//
|
|
3
|
+
// The build records the checkout it was built from in
|
|
4
|
+
// lib/build-info.json. That covers both ways sm-dev runs:
|
|
5
|
+
// - In the checkout itself (scripts/sm-dev), from its own lib/.
|
|
6
|
+
// - In a repo of userscripts, from the copy `pnpm install` took (with
|
|
7
|
+
// no src/ of its own). `pnpm install` copies the checkout's lib/ as
|
|
8
|
+
// it is, without building it first, so the fix needs a build there
|
|
9
|
+
// too.
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { quoted } from './output-style.js';
|
|
14
|
+
// lib/, beside this module's lib/harness/.
|
|
15
|
+
const LIB_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
16
|
+
/**
|
|
17
|
+
* How to rebuild what this sm-dev runs from, as a sentence: in the
|
|
18
|
+
* checkout itself, or in the checkout an installed copy came from and
|
|
19
|
+
* then here.
|
|
20
|
+
*/
|
|
21
|
+
export function rebuildAdvice() {
|
|
22
|
+
const source = buildSource();
|
|
23
|
+
if (!source)
|
|
24
|
+
return 'Run `pnpm run build` in SourceMonkey, and `pnpm install` again where it is installed.';
|
|
25
|
+
if (path.resolve(source, 'lib') === LIB_DIR)
|
|
26
|
+
return 'Run `pnpm run build`.';
|
|
27
|
+
return `Run ${quoted('pnpm run build')} in ${source}, then ${quoted('pnpm install')} here.`;
|
|
28
|
+
}
|
|
29
|
+
// The checkout lib/ was built from, or null: built before
|
|
30
|
+
// build-info.json existed, or not by build.mjs, leaves nothing to go by.
|
|
31
|
+
function buildSource() {
|
|
32
|
+
try {
|
|
33
|
+
const info = JSON.parse(readFileSync(path.join(LIB_DIR, 'build-info.json'), 'utf8'));
|
|
34
|
+
return typeof info.source === 'string' ? info.source : null;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type FileHandle } from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Where the logs go: `/tmp/sm-dev-logs-<user>` on most machines.
|
|
4
|
+
* `SM_DEV_LOGS_DIR` moves it, for tests.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runLogsDir(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Where a temp browser run's downloads go: in the logs folder, named
|
|
9
|
+
* after the run's log when it has one, and kept after the run ends as
|
|
10
|
+
* the log is (the browser's own profile is deleted).
|
|
11
|
+
*/
|
|
12
|
+
export declare function runDownloadsDir(log?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Local time as `20260408-203012-345`: SeeWhatISee's file-name
|
|
15
|
+
* timestamp. Names the log files, and starts each line in them.
|
|
16
|
+
*/
|
|
17
|
+
export declare function logTimestamp(ms?: number): string;
|
|
18
|
+
/** A log line's timestamp and the space after it, for taking back off. */
|
|
19
|
+
export declare const LOG_LINE_PREFIX: RegExp;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new log file, `sm-dev-<timestamp>.log`. A name already
|
|
22
|
+
* taken moves the timestamp on a millisecond and tries again; created
|
|
23
|
+
* exclusively, so two runs starting together can't share one.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createRunLog(): Promise<{
|
|
26
|
+
file: string;
|
|
27
|
+
handle: FileHandle;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Starts each line this process writes to stdout and stderr with the
|
|
31
|
+
* time it was written. For the detached run, whose output is its log
|
|
32
|
+
* file. Output that bypasses the streams (a crash in Node itself)
|
|
33
|
+
* still lands in the file, unstamped.
|
|
34
|
+
*/
|
|
35
|
+
export declare function timestampOutputLines(): void;
|
|
36
|
+
/**
|
|
37
|
+
* A log's full path, and its link's name when it has one, for printing:
|
|
38
|
+
* `/tmp/sm-dev-logs-you/sm-dev-20260926-063756-629.log (D1.log)`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function runLogLabel(file: string, id: string | undefined): string;
|
|
41
|
+
/**
|
|
42
|
+
* Points `<run id>.log`, beside the log, at it: the latest log of
|
|
43
|
+
* a run with that id, found by the id alone. Swapped in by a rename, so
|
|
44
|
+
* the link is never missing or half made. A failure only costs the
|
|
45
|
+
* link, so it is said and the run goes on.
|
|
46
|
+
*/
|
|
47
|
+
export declare function linkRunLog(file: string, id: string, out: (line: string) => void): Promise<void>;
|