diff --git a/src/extension.ts b/src/extension.ts index 1106a6c..d2b801b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -75,7 +75,7 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo async (progress, progressCancellationToken) => { try { progress.report({ message: "Starting model..." }); - + let axiosCancelPost: () => void; const axiosCancelToken = new axios.CancelToken((c) => { axiosCancelPost = () => { @@ -85,7 +85,7 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo progressCancellationToken.onCancellationRequested(axiosCancelPost); vscode.workspace.onDidCloseTextDocument(axiosCancelPost); }); - + const response = await axios.post(apiEndpoint, { model: apiModel, prompt: fimPrompt, @@ -102,15 +102,15 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo 'Authorization': apiAuthentication } }); - + progress.report({ message: "Generating..." }); - + let completionText = response.data.response; completionText = completionText.replace(/||/g, '').trim(); - + // Split the completion text by new lines const lines = completionText.split('\n'); - + // Create a decoration for each line of the response const previewRanges = lines.map((line: string, idx: number) => { const linePos = new vscode.Position(position.line + idx, 0); @@ -126,20 +126,22 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo } }; }); - + // Apply the decorations for multiline preview textEditor.setDecorations(previewDecorationType, previewRanges); - + + let completionInserted = false; // Flag to track insertion + const disposable = vscode.workspace.onDidChangeTextDocument(async (event) => { if (event.document.uri.toString() === document.uri.toString()) { const change = event.contentChanges[0]; - + // Handle Backspace to decline the preview if (change && change.text === '' && change.rangeLength === 1) { textEditor.setDecorations(previewDecorationType, []); // Remove preview decorations disposable.dispose(); } - + // Handle Ctrl + Enter (or Cmd + Enter on macOS) to accept the preview const isCtrlOrCmdPressed = event.contentChanges.some( (change) => { @@ -148,28 +150,31 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo return isCtrlOrCmd; } ); - - if (isCtrlOrCmdPressed) { + + if (isCtrlOrCmdPressed && !completionInserted) { + // Ensure that we insert the completion text only once + completionInserted = true; + // Remove the preview decoration before applying the final completion textEditor.setDecorations(previewDecorationType, []); - + const edit = new vscode.WorkspaceEdit(); const insertPosition = new vscode.Position(position.line, 0); - - // Insert the completion only once + + // Avoid duplicating the completion text if (!document.getText().includes(completionText)) { edit.insert(document.uri, insertPosition, '\n' + completionText); await vscode.workspace.applyEdit(edit); } - + const newPosition = new vscode.Position(position.line + lines.length, lines[lines.length - 1].length); textEditor.selection = new vscode.Selection(newPosition, newPosition); - + disposable.dispose(); // Clean up the listener after accepting the completion } } }); - + } catch (err: any) { vscode.window.showErrorMessage( "Fabelous Autocoder encountered an error: " + err.message @@ -178,6 +183,8 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo } } ); + + }