Fix path completion hanging and autocomplete arrow key behavior

- Fixed catastrophic regex backtracking in extractPathPrefix that caused
  terminal to hang when text contained many / characters (e.g., URLs).
  Replaced complex regex with simple lastIndexOf approach. (#18)
- Fixed arrow keys moving both autocomplete selection and editor cursor
  by adding missing return statement after handling arrow keys in
  autocomplete mode.

Closes #18
This commit is contained in:
Mario Zechner 2025-11-21 12:47:23 +01:00
parent e7a5ca144c
commit 1d8bc9d6eb
4 changed files with 97 additions and 88 deletions

View file

@ -283,21 +283,17 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
return atMatch[0]; // Return the full @path pattern
}
// Match paths - including those ending with /, ~/, or any word at end for forced extraction
// This regex captures:
// - Paths starting from beginning of line or after space/quote/equals
// - Absolute paths starting with /
// - Relative paths with ./ or ../
// - Home directory paths with ~/
// - The path itself (can include / in the middle)
// - For forced extraction, capture any word at the end
const matches = text.match(/(?:^|[\s"'=])((?:\/|~\/|\.{1,2}\/)?(?:[^\s"'=]*\/?)*[^\s"'=]*)$/);
if (!matches) {
// If forced extraction and no matches, return empty string to trigger from current dir
return forceExtract ? "" : null;
}
// Simple approach: find the last whitespace/delimiter and extract the word after it
// This avoids catastrophic backtracking from nested quantifiers
const lastDelimiterIndex = Math.max(
text.lastIndexOf(" "),
text.lastIndexOf("\t"),
text.lastIndexOf('"'),
text.lastIndexOf("'"),
text.lastIndexOf("="),
);
const pathPrefix = matches[1] || "";
const pathPrefix = lastDelimiterIndex === -1 ? text : text.slice(lastDelimiterIndex + 1);
// For forced extraction (Tab key), always return something
if (forceExtract) {

View file

@ -192,6 +192,7 @@ export class Editor implements Component {
// Only pass arrow keys to the list, not Enter/Tab (we handle those directly)
if (data === "\x1b[A" || data === "\x1b[B") {
this.autocompleteList.handleInput(data);
return;
}
// If Tab was pressed, always apply the selection
@ -832,6 +833,11 @@ export class Editor implements Component {
this.tryTriggerAutocomplete(true);
}
/*
https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/559322883
17 this job fails with https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19
536643416/job/55932288317 havea look at .gi
*/
private forceFileAutocomplete(): void {
if (!this.autocompleteProvider) return;