From ac7afb4b4ec7206784a4073c8a342716d735bff8 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Wed, 11 Sep 2024 11:28:55 +0200 Subject: [PATCH] step back --- src/extension.ts | 108 ++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 4b30205..319ee83 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -59,10 +59,13 @@ const previewDecorationType = vscode.window.createTextEditorDecorationType({ rangeBehavior: vscode.DecorationRangeBehavior.ClosedOpen, // Ensure proper handling of multiline decorations }); + + async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationToken?: vscode.CancellationToken) { const document = textEditor.document; const position = textEditor.selection.active; + // Get the context and create the FIM prompt const context = getContextLines(document, position); const fimPrompt = createFIMPrompt(context, document.languageId); @@ -85,7 +88,8 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo progressCancellationToken.onCancellationRequested(axiosCancelPost); vscode.workspace.onDidCloseTextDocument(axiosCancelPost); }); - + + // Make the API request const response = await axios.post(apiEndpoint, { model: apiModel, prompt: fimPrompt, @@ -107,80 +111,73 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo let completionText = response.data.response; completionText = completionText.replace(/||/g, '').trim(); - - // Split the completion text by new lines + // Split the completion text by new lines const lines = completionText.split('\n'); + + // Remove context lines and insert the preview + const startLine = Math.max(0, position.line - 1); // Start 1 line before the cursor + const endLine = position.line + 1; // End 1 line after the cursor + const rangeToReplace = new vscode.Range( + new vscode.Position(startLine, 0), + new vscode.Position(endLine, 0) + ); - // Create a decoration for each line of the response - const previewRanges = lines.map((line: string, idx: number) => { - // Determine the start position for each line - const startPos = new vscode.Position(position.line + idx, 0); - - // Create a range that decorates the line, spanning from start to start (empty range) - const range = new vscode.Range(startPos, startPos); - + // Apply grayed-out italic styling to the preview + const previewRanges = lines.map((line: string, index: number) => { + const linePos = new vscode.Position(startLine + index, 0); return { - range, + range: new vscode.Range(linePos, linePos), renderOptions: { - after: { - contentText: line, // Display the current line - color: '#888888', - fontStyle: 'italic', + before: { + contentText: line, + color: '#888888', // Grayed-out text + fontStyle: 'italic', // Italic text } } }; }); - // Apply the decorations for multiline preview + const previewDecorationType = vscode.window.createTextEditorDecorationType({ + color: '#888888', // Grayed-out color + fontStyle: 'italic', // Italic style + }); + + // Apply the preview as decoration textEditor.setDecorations(previewDecorationType, previewRanges); - - let completionInserted = false; // Flag to track insertion - + // Flag to ensure we only accept or dismiss once + let previewInserted = true; + + // Event handler to accept or dismiss the preview 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 + + // Handle Backspace to dismiss 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) => { - const isMac = process.platform === 'darwin'; - const isCtrlOrCmd = isMac ? change.text.includes('\u0010') : change.text.includes('\n'); - return isCtrlOrCmd; - } - ); - - if (isCtrlOrCmdPressed && !completionInserted) { - // Ensure that we insert the completion text only once - completionInserted = true; - - // Remove the preview decoration before applying the final completion + // Remove the decoration preview textEditor.setDecorations(previewDecorationType, []); - + disposable.dispose(); // Clean up event listener + previewInserted = false; + } + + // Handle Enter to accept the preview + if (change && change.text === '\n' && previewInserted) { + // Remove the decoration preview and insert actual completion text + textEditor.setDecorations(previewDecorationType, []); // Remove decorations + const edit = new vscode.WorkspaceEdit(); - const insertPosition = new vscode.Position(position.line, 0); - - // 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 + const acceptedText = completionText; + edit.replace(document.uri, rangeToReplace, acceptedText); // Insert actual completion + await vscode.workspace.applyEdit(edit); + + disposable.dispose(); // Clean up event listener + previewInserted = false; } } }); - + } catch (err: any) { vscode.window.showErrorMessage( "Fabelous Autocoder encountered an error: " + err.message @@ -189,12 +186,9 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo } } ); - - } - async function provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, cancellationToken: vscode.CancellationToken) { const item = new vscode.CompletionItem("Fabelous autocompletion"); item.insertText = new vscode.SnippetString('${1:}');