fix(tui): close quoted directory paths during autocomplete

This commit is contained in:
Mario Zechner 2026-01-30 00:20:14 +01:00
parent dc8539a001
commit 1665636fbe
2 changed files with 22 additions and 11 deletions

View file

@ -80,7 +80,7 @@ function buildCompletionValue(
} }
const openQuote = `${prefix}"`; const openQuote = `${prefix}"`;
const closeQuote = options.isDirectory ? "" : '"'; const closeQuote = '"';
return `${openQuote}${path}${closeQuote}`; return `${openQuote}${path}${closeQuote}`;
} }
@ -320,16 +320,19 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
if (prefix.startsWith("@")) { if (prefix.startsWith("@")) {
// This is a file attachment completion // This is a file attachment completion
// Don't add space after directories so user can continue autocompleting // Don't add space after directories so user can continue autocompleting
const isDirectory = item.value.endsWith("/"); const isDirectory = item.label.endsWith("/");
const suffix = isDirectory ? "" : " "; const suffix = isDirectory ? "" : " ";
const newLine = `${beforePrefix + item.value}${suffix}${afterCursor}`; const newLine = `${beforePrefix + item.value}${suffix}${afterCursor}`;
const newLines = [...lines]; const newLines = [...lines];
newLines[cursorLine] = newLine; newLines[cursorLine] = newLine;
const hasTrailingQuote = item.value.endsWith('"');
const cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;
return { return {
lines: newLines, lines: newLines,
cursorLine, cursorLine,
cursorCol: beforePrefix.length + item.value.length + suffix.length, cursorCol: beforePrefix.length + cursorOffset + suffix.length,
}; };
} }
@ -341,10 +344,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
const newLines = [...lines]; const newLines = [...lines];
newLines[cursorLine] = newLine; newLines[cursorLine] = newLine;
const isDirectory = item.label.endsWith("/");
const hasTrailingQuote = item.value.endsWith('"');
const cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;
return { return {
lines: newLines, lines: newLines,
cursorLine, cursorLine,
cursorCol: beforePrefix.length + item.value.length, cursorCol: beforePrefix.length + cursorOffset,
}; };
} }
@ -353,10 +360,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
const newLines = [...lines]; const newLines = [...lines];
newLines[cursorLine] = newLine; newLines[cursorLine] = newLine;
const isDirectory = item.label.endsWith("/");
const hasTrailingQuote = item.value.endsWith('"');
const cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;
return { return {
lines: newLines, lines: newLines,
cursorLine, cursorLine,
cursorCol: beforePrefix.length + item.value.length, cursorCol: beforePrefix.length + cursorOffset,
}; };
} }

View file

@ -244,7 +244,7 @@ describe("CombinedAutocompleteProvider", () => {
const result = provider.getSuggestions([line], 0, line.length); const result = provider.getSuggestions([line], 0, line.length);
const values = result?.items.map((item) => item.value); const values = result?.items.map((item) => item.value);
assert.ok(values?.includes('@"my folder/')); assert.ok(values?.includes('@"my folder/"'));
}); });
test("continues autocomplete inside quoted @ paths", () => { test("continues autocomplete inside quoted @ paths", () => {
@ -256,8 +256,8 @@ describe("CombinedAutocompleteProvider", () => {
}); });
const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath()); const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath());
const line = '@"my folder/'; const line = '@"my folder/"';
const result = provider.getSuggestions([line], 0, line.length); const result = provider.getSuggestions([line], 0, line.length - 1);
assert.notEqual(result, null, "Should return suggestions for quoted folder path"); assert.notEqual(result, null, "Should return suggestions for quoted folder path");
const values = result?.items.map((item) => item.value); const values = result?.items.map((item) => item.value);
@ -291,7 +291,7 @@ describe("CombinedAutocompleteProvider", () => {
assert.notEqual(result, null, "Should return suggestions for path completion"); assert.notEqual(result, null, "Should return suggestions for path completion");
const values = result?.items.map((item) => item.value); const values = result?.items.map((item) => item.value);
assert.ok(values?.includes('"my folder/')); assert.ok(values?.includes('"my folder/"'));
}); });
test("continues completion inside quoted paths", () => { test("continues completion inside quoted paths", () => {
@ -303,8 +303,8 @@ describe("CombinedAutocompleteProvider", () => {
}); });
const provider = new CombinedAutocompleteProvider([], baseDir); const provider = new CombinedAutocompleteProvider([], baseDir);
const line = '"my folder/'; const line = '"my folder/"';
const result = provider.getForceFileSuggestions([line], 0, line.length); const result = provider.getForceFileSuggestions([line], 0, line.length - 1);
assert.notEqual(result, null, "Should return suggestions for quoted folder path"); assert.notEqual(result, null, "Should return suggestions for quoted folder path");
const values = result?.items.map((item) => item.value); const values = result?.items.map((item) => item.value);