diff --git a/src/web/public/constants.js b/src/web/public/constants.js index 7fa14ee8..062cd139 100644 --- a/src/web/public/constants.js +++ b/src/web/public/constants.js @@ -2266,8 +2266,8 @@ const SPACED_FILE_PATH_LABEL_PATTERN = * or a bare `=` makes the candidate a sentence (`/tmp/out has the logs in run.log`), * so a name such as `Pros and Cons.md` splits as master does. A command line is * refused: an executable under `bin/`, `.bin/`, `scripts/` or `tools/` as the - * first word, a first word ending in `$` (a shell prompt, `/home/me/proj$ cat a.md`), - * or any `-x`/`--x` flag word. + * first word, any earlier word ending in `$` (a shell prompt, `/home/me/proj$ cat a.md`, + * `/mnt/c/My Docs$ ls a.md`), or any `-x`/`--x` flag word. * * A candidate that is one path but not a linkable one (an unknown root such as * `/etc`, a `.`/`..`/empty segment) comes back with `link: false` when its last @@ -2302,11 +2302,13 @@ function spacedFilePathOnLine(line) { if (/\/(?:\.?bin|scripts?|tools)\/[^/]+$/.test(words[0]) || words.some((word) => /^-{1,2}\w/.test(word))) { return null; } - // A shell prompt that prints its working directory in full (`/home/me/proj$ cat - // notes.md`; WSL's `/mnt/c/...` is outside `$HOME`) is a command line too. - if (words[0].endsWith('$')) return null; for (const word of words.slice(0, -1)) { if (word.endsWith('/') || word.endsWith(':') || /^(?:—|–|→|=>|->|<-|=)$/.test(word)) return null; + // A shell prompt that prints its working directory in full (`/home/me/proj$ cat + // notes.md`; WSL's `/mnt/c/...` is outside `$HOME`) is a command line too, and so is + // one whose directory has a space in it (`/mnt/c/My Docs$ ls notes.md`): the `$` + // can end any earlier word, not only the first. + if (word.endsWith('$')) return null; // A word with no letter or digit (a prompt glyph `❯` or `$`, a `✓`) is never // part of a file name, apart from a bare `-` (`OneDrive - Contoso`). if (word !== '-' && !/[\p{L}\p{N}]/u.test(word)) return null; diff --git a/test/spaced-file-path-links.test.ts b/test/spaced-file-path-links.test.ts index 73a6fe8f..4c9c41fc 100644 --- a/test/spaced-file-path-links.test.ts +++ b/test/spaced-file-path-links.test.ts @@ -337,13 +337,15 @@ describe('spaced file paths: shapes that keep master links', () => { }); // A shell prompt that prints its working directory in full (WSL's `/mnt/c/...` is - // outside `$HOME`): a word with no letter or digit, or a first word ending in `$`, - // is never part of a file name, so every earlier command in the scrollback keeps - // master's links. + // outside `$HOME`): a word with no letter or digit, or any earlier word ending in `$` + // (the first, or a later one when the directory has a space in it), is never part of + // a file name, so every earlier command in the scrollback keeps master's links. it.each([ ['/mnt/c/proj ❯ code notes.md', ['/mnt/c/proj', true], ['notes.md']], ['/home/me/proj $ cat notes.md', ['/home/me/proj', true], ['notes.md']], ['/home/me/proj$ cat notes.md', ['/home/me/proj', true], ['notes.md']], + ['/mnt/c/Users/me/OneDrive - Contoso/proj$ code notes.md', ['/mnt/c/Users/me/OneDrive', true], ['notes.md']], + ['/mnt/c/My Docs$ ls notes.md', ['/mnt/c/My', true], ['notes.md']], ['/home/me/proj ❯ git add src/a.ts', ['/home/me/proj', true], ['src/a.ts']], ['/mnt/c/Users/me/OneDrive - Contoso/proj ❯ code notes.md', ['/mnt/c/Users/me/OneDrive', true], ['notes.md']], ['/home/me/proj/out ✓ report.pdf', ['/home/me/proj/out', true], ['report.pdf']],