mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 11:03:07 +00:00
fix(tui): avoid duplicating quotes during autocomplete
This commit is contained in:
parent
1665636fbe
commit
f181385859
2 changed files with 49 additions and 4 deletions
|
|
@ -299,13 +299,18 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
||||||
const currentLine = lines[cursorLine] || "";
|
const currentLine = lines[cursorLine] || "";
|
||||||
const beforePrefix = currentLine.slice(0, cursorCol - prefix.length);
|
const beforePrefix = currentLine.slice(0, cursorCol - prefix.length);
|
||||||
const afterCursor = currentLine.slice(cursorCol);
|
const afterCursor = currentLine.slice(cursorCol);
|
||||||
|
const isQuotedPrefix = prefix.startsWith('"') || prefix.startsWith('@"');
|
||||||
|
const hasLeadingQuoteAfterCursor = afterCursor.startsWith('"');
|
||||||
|
const hasTrailingQuoteInItem = item.value.endsWith('"');
|
||||||
|
const adjustedAfterCursor =
|
||||||
|
isQuotedPrefix && hasTrailingQuoteInItem && hasLeadingQuoteAfterCursor ? afterCursor.slice(1) : afterCursor;
|
||||||
|
|
||||||
// Check if we're completing a slash command (prefix starts with "/" but NOT a file path)
|
// Check if we're completing a slash command (prefix starts with "/" but NOT a file path)
|
||||||
// Slash commands are at the start of the line and don't contain path separators after the first /
|
// Slash commands are at the start of the line and don't contain path separators after the first /
|
||||||
const isSlashCommand = prefix.startsWith("/") && beforePrefix.trim() === "" && !prefix.slice(1).includes("/");
|
const isSlashCommand = prefix.startsWith("/") && beforePrefix.trim() === "" && !prefix.slice(1).includes("/");
|
||||||
if (isSlashCommand) {
|
if (isSlashCommand) {
|
||||||
// This is a command name completion
|
// This is a command name completion
|
||||||
const newLine = `${beforePrefix}/${item.value} ${afterCursor}`;
|
const newLine = `${beforePrefix}/${item.value} ${adjustedAfterCursor}`;
|
||||||
const newLines = [...lines];
|
const newLines = [...lines];
|
||||||
newLines[cursorLine] = newLine;
|
newLines[cursorLine] = newLine;
|
||||||
|
|
||||||
|
|
@ -322,7 +327,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
||||||
// 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.label.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}${adjustedAfterCursor}`;
|
||||||
const newLines = [...lines];
|
const newLines = [...lines];
|
||||||
newLines[cursorLine] = newLine;
|
newLines[cursorLine] = newLine;
|
||||||
|
|
||||||
|
|
@ -340,7 +345,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
||||||
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
||||||
if (textBeforeCursor.includes("/") && textBeforeCursor.includes(" ")) {
|
if (textBeforeCursor.includes("/") && textBeforeCursor.includes(" ")) {
|
||||||
// This is likely a command argument completion
|
// This is likely a command argument completion
|
||||||
const newLine = beforePrefix + item.value + afterCursor;
|
const newLine = beforePrefix + item.value + adjustedAfterCursor;
|
||||||
const newLines = [...lines];
|
const newLines = [...lines];
|
||||||
newLines[cursorLine] = newLine;
|
newLines[cursorLine] = newLine;
|
||||||
|
|
||||||
|
|
@ -356,7 +361,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For file paths, complete the path
|
// For file paths, complete the path
|
||||||
const newLine = beforePrefix + item.value + afterCursor;
|
const newLine = beforePrefix + item.value + adjustedAfterCursor;
|
||||||
const newLines = [...lines];
|
const newLines = [...lines];
|
||||||
newLines[cursorLine] = newLine;
|
newLines[cursorLine] = newLine;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,26 @@ describe("CombinedAutocompleteProvider", () => {
|
||||||
assert.ok(values?.includes('@"my folder/test.txt"'));
|
assert.ok(values?.includes('@"my folder/test.txt"'));
|
||||||
assert.ok(values?.includes('@"my folder/other.txt"'));
|
assert.ok(values?.includes('@"my folder/other.txt"'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("applies quoted @ completion without duplicating closing quote", () => {
|
||||||
|
setupFolder(baseDir, {
|
||||||
|
files: {
|
||||||
|
"my folder/test.txt": "content",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath());
|
||||||
|
const line = '@"my folder/te"';
|
||||||
|
const cursorCol = line.length - 1;
|
||||||
|
const result = provider.getSuggestions([line], 0, cursorCol);
|
||||||
|
|
||||||
|
assert.notEqual(result, null, "Should return suggestions for quoted @ path");
|
||||||
|
const item = result?.items.find((entry) => entry.value === '@"my folder/test.txt"');
|
||||||
|
assert.ok(item, "Should find test.txt suggestion");
|
||||||
|
|
||||||
|
const applied = provider.applyCompletion([line], 0, cursorCol, item!, result!.prefix);
|
||||||
|
assert.strictEqual(applied.lines[0], '@"my folder/test.txt" ');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("quoted path completion", () => {
|
describe("quoted path completion", () => {
|
||||||
|
|
@ -311,5 +331,25 @@ describe("CombinedAutocompleteProvider", () => {
|
||||||
assert.ok(values?.includes('"my folder/test.txt"'));
|
assert.ok(values?.includes('"my folder/test.txt"'));
|
||||||
assert.ok(values?.includes('"my folder/other.txt"'));
|
assert.ok(values?.includes('"my folder/other.txt"'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("applies quoted completion without duplicating closing quote", () => {
|
||||||
|
setupFolder(baseDir, {
|
||||||
|
files: {
|
||||||
|
"my folder/test.txt": "content",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const provider = new CombinedAutocompleteProvider([], baseDir);
|
||||||
|
const line = '"my folder/te"';
|
||||||
|
const cursorCol = line.length - 1;
|
||||||
|
const result = provider.getForceFileSuggestions([line], 0, cursorCol);
|
||||||
|
|
||||||
|
assert.notEqual(result, null, "Should return suggestions for quoted path");
|
||||||
|
const item = result?.items.find((entry) => entry.value === '"my folder/test.txt"');
|
||||||
|
assert.ok(item, "Should find test.txt suggestion");
|
||||||
|
|
||||||
|
const applied = provider.applyCompletion([line], 0, cursorCol, item!, result!.prefix);
|
||||||
|
assert.strictEqual(applied.lines[0], '"my folder/test.txt"');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue