mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 02:49:33 +01:00
fix(terminal): keep sentences and script commands out of spaced paths
A side-by-side sweep of master and this branch over about 590 realistic lines found more shapes where a spaced candidate swallowed prose or a command: - An earlier word that is a lowercase connective or verb (and, or, to, in, the, is, has, contains, then, as and a few more) now makes the candidate a sentence, for own-line, list-marker and labelled forms alike: `/home/me/proj contains a.md`, `- /tmp/out has the logs in run.log`, `Path: /home/me/proj/out contains a.md`, `Files: src/components and utils/x.ts`, `Wrote: 3 files to docs/design notes/overview.md`. `at` and `of` stay out so screenshot names and `Copy of report.docx` still link whole; a name such as `Pros and Cons.md` splits as on master. - A bare `=` word is refused like the arrows. - An executable under `scripts/` or `tools/` is refused like one under `bin/` (`/home/me/proj/scripts/deploy prod.yml`). - An earlier word holding an extension anywhere (`a.ts#L12`) ends the path. The two residuals pinned earlier (`/home/me/proj contains a.md` and `Files: src/components and utils/x.ts`) now return master's links.
This commit is contained in:
1 parent
5e1daaf7c7
commit
df9f93d3ee
5 files changed
+84
-17
No files matched your search
@@ -2241,14 +2241,18 @@ const SPACED_FILE_PATH_LABEL_PATTERN =
|
||||
* path needs a path label to be taken spaced. One trailing sentence mark is left
|
||||
* out, and a leading `./` is not a segment. The candidate must read as ONE path:
|
||||
* it ends on a known extension, a rooted one has a directory before its first
|
||||
* space, no earlier word ends on an extension or `/`, and none holds a `:` and a
|
||||
* digit (`a.ts:42`, a line suffix ends the path). Later words cannot start a new
|
||||
* space, no earlier word holds an extension (`a.md,`, `a.ts#L12`) or ends in `/`,
|
||||
* and none holds a `:` and a digit (`a.ts:42`, a line suffix ends the path). Later words cannot start a new
|
||||
* `/`, `~/`, `./` or `../` path, no earlier word ends in `:` or is an arrow, and
|
||||
* a run of spaces (a column gap) is refused, so two paths on a line are never
|
||||
* merged. A relative candidate whose only `/` word is its last is prose after the
|
||||
* label (`Wrote: 120 lines to src/foo.ts`) and is left alone, which also splits
|
||||
* `Saved to: My Docs/plan.md` as master does. A command line is refused: an
|
||||
* executable under `bin/` or `.bin/` as the first word, or any `-x`/`--x` flag word.
|
||||
* `Saved to: My Docs/plan.md` as master does. An earlier word that is a lowercase
|
||||
* connective or verb (SPACED_PATH_PROSE_WORD: `and`, `in`, `has`, `contains`, ...)
|
||||
* 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, 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
|
||||
@@ -2278,13 +2282,20 @@ function spacedFilePathOnLine(line) {
|
||||
// or `/review the changes in src/a.ts` is a command, not a spaced path.
|
||||
if (path.startsWith('/') && !/^\/[^/]+\//.test(words[0])) return null;
|
||||
// A command whose executable sits under a known root (`/opt/homebrew/bin/node a.js`,
|
||||
// `…/node_modules/.bin/tsc -p tsconfig.json`) is not a path either.
|
||||
if (/\/\.?bin\/[^/]+$/.test(words[0]) || words.some((word) => /^-{1,2}\w/.test(word))) return null;
|
||||
// `/home/me/proj/node_modules/.bin/tsc -p tsconfig.json`, `/home/me/proj/scripts/deploy prod.yml`)
|
||||
// is not a path either.
|
||||
if (/\/(?:\.?bin|scripts?|tools)\/[^/]+$/.test(words[0]) || words.some((word) => /^-{1,2}\w/.test(word))) {
|
||||
return null;
|
||||
}
|
||||
for (const word of words.slice(0, -1)) {
|
||||
if (word.endsWith('/') || word.endsWith(':') || /^(?:—|–|→|=>|->|<-)$/.test(word)) return null;
|
||||
if (word.endsWith('/') || word.endsWith(':') || /^(?:—|–|→|=>|->|<-|=)$/.test(word)) return null;
|
||||
// `a.ts:42` (grep -n, compiler output): the path already ended at the line suffix.
|
||||
if (/:\d/.test(word)) return null;
|
||||
if (PATH_TOKEN_ENDS_WITH_EXTENSION.test(word.replace(/[.,;:!?)\]}]+$/, ''))) return null;
|
||||
// An extension anywhere in an earlier word (`a.md,`, `a.ts#L12`) ends a path there.
|
||||
if (PATH_TOKEN_HAS_EXTENSION.test(word)) return null;
|
||||
// A connective or verb joins a path to prose (`/tmp/out has the logs in run.log`,
|
||||
// `Files: src/components and utils/x.ts`), so the candidate is a sentence.
|
||||
if (SPACED_PATH_PROSE_WORD.test(word)) return null;
|
||||
}
|
||||
if (words.slice(1).some((word) => /^(?:\/|~\/|\.{1,2}\/)/.test(word))) return null;
|
||||
const rooted = SPACED_PATH_ROOT.test(path) || path.startsWith('~/');
|
||||
@@ -2487,6 +2498,14 @@ const FILE_LINK_ROOT_GROUP = /^\(\\\/\(\?:([^()]*)\)/.exec(FILE_PATH_LINK_PATTER
|
||||
const PATH_TOKEN_ENDS_WITH_EXTENSION = new RegExp(`\\.${FILE_LINK_EXTENSION_GROUP}$`);
|
||||
const PATH_TOKEN_HAS_EXTENSION = new RegExp(`\\.${FILE_LINK_EXTENSION_GROUP}\\b`);
|
||||
const PATH_TOKEN_STARTS_NEW_PATH = new RegExp(`^(?:~\\/|\\/(?:${FILE_LINK_ROOT_GROUP})\\/)`);
|
||||
/**
|
||||
* Lowercase connectives and verbs that put a spaced candidate in a sentence, for
|
||||
* {@link spacedFilePathOnLine}. `at` stays out (`Screenshot 2026-10-24 at 10.00.00.png`)
|
||||
* and so does `of` (`Copy of report.docx`); a name using a listed word
|
||||
* (`Pros and Cons.md`) splits as it did before spaced paths were linked.
|
||||
*/
|
||||
const SPACED_PATH_PROSE_WORD =
|
||||
/^(?:and|or|to|in|into|from|the|is|are|was|were|has|have|had|contains|holds|see|then|vs|via|as)$/;
|
||||
/** A rooted path's start (`/home/`, `/mnt/`, …), for {@link spacedFilePathOnLine}. */
|
||||
const SPACED_PATH_ROOT = new RegExp(`^\\/(?:${FILE_LINK_ROOT_GROUP})\\/`);
|
||||
/** A relative head that names its own location (`./a`, `../a`) is an entry of its own. */
|
||||
|
||||
Reference in new issue
Block a user