develop #6
128
src/extension.ts
128
src/extension.ts
|
@ -61,6 +61,7 @@ const previewDecorationType = vscode.window.createTextEditorDecorationType({
|
||||||
textDecoration: 'none; display: none;', // Hide the original text
|
textDecoration: 'none; display: none;', // Hide the original text
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationToken?: vscode.CancellationToken) {
|
async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationToken?: vscode.CancellationToken) {
|
||||||
const document = textEditor.document;
|
const document = textEditor.document;
|
||||||
const position = textEditor.selection.active;
|
const position = textEditor.selection.active;
|
||||||
|
@ -116,40 +117,42 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
let previewInserted = false;
|
let previewInserted = false;
|
||||||
let originalContent: string;
|
let originalContent: string;
|
||||||
let previewStartLine: number;
|
let previewStartLine: number;
|
||||||
|
let previewEndLine: number;
|
||||||
|
|
||||||
const storeAndInsertPreview = async () => {
|
const storeAndInsertPreview = async () => {
|
||||||
previewStartLine = startLine;
|
const currentLine = position.line;
|
||||||
const endLine = document.lineCount - 1;
|
previewStartLine = currentLine;
|
||||||
const endCharacter = document.lineAt(endLine).text.length;
|
const previewLines = completionText.split('\n');
|
||||||
const fullRange = new vscode.Range(startLine, 0, endLine, endCharacter);
|
previewEndLine = previewStartLine + previewLines.length;
|
||||||
|
|
||||||
|
// Ensure the previewEndLine doesn't exceed the document's line count
|
||||||
|
const documentEndLine = document.lineCount - 1;
|
||||||
|
previewEndLine = Math.min(previewEndLine, documentEndLine + 1);
|
||||||
|
|
||||||
|
// Store original content
|
||||||
|
const fullRange = new vscode.Range(previewStartLine, 0, previewEndLine, document.lineAt(previewEndLine - 1).text.length);
|
||||||
originalContent = document.getText(fullRange);
|
originalContent = document.getText(fullRange);
|
||||||
|
|
||||||
const previewContent = completionText + '\n'.repeat(1);
|
// Prepare the new content
|
||||||
|
const newContent = previewLines.join('\n');
|
||||||
|
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
edit.replace(document.uri, fullRange, previewContent); // Overwrite the content
|
edit.replace(document.uri, fullRange, newContent);
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
|
|
||||||
// Split the preview content into lines
|
// Highlight only the new lines
|
||||||
const previewLines = previewContent.split('\n');
|
const previewRanges: vscode.DecorationOptions[] = previewLines.map((line: string, index: number) => ({
|
||||||
|
range: new vscode.Range(previewStartLine + index, 0, previewStartLine + index, line.length),
|
||||||
|
renderOptions: {
|
||||||
// Set decorations on the newly inserted lines
|
after: {
|
||||||
const previewRanges: vscode.DecorationOptions[] = [];
|
contentText: line,
|
||||||
for (let i = 0; i < previewLines.length; i++) {
|
|
||||||
const range = new vscode.Range(previewStartLine + i, 0, previewStartLine + i, previewLines[i].length);
|
|
||||||
previewRanges.push({
|
|
||||||
range,
|
|
||||||
renderOptions: {
|
|
||||||
after: {
|
|
||||||
contentText: previewLines[i],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}));
|
||||||
textEditor.setDecorations(previewDecorationType, previewRanges);
|
textEditor.setDecorations(previewDecorationType, previewRanges);
|
||||||
previewInserted = true;
|
previewInserted = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const disposable = vscode.window.onDidChangeTextEditorSelection(async (event) => {
|
const disposable = vscode.window.onDidChangeTextEditorSelection(async (event) => {
|
||||||
const textEditor = vscode.window.activeTextEditor;
|
const textEditor = vscode.window.activeTextEditor;
|
||||||
if (!textEditor || !previewInserted || isHandlingChange) {
|
if (!textEditor || !previewInserted || isHandlingChange) {
|
||||||
|
@ -162,7 +165,6 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
const activeSelection = textEditor.selection;
|
const activeSelection = textEditor.selection;
|
||||||
const changeStartLine = activeSelection.active.line;
|
const changeStartLine = activeSelection.active.line;
|
||||||
|
|
||||||
// Detect Tab key press by checking the active selection
|
|
||||||
if (event.kind === vscode.TextEditorSelectionChangeKind.Keyboard && changeStartLine >= previewStartLine) {
|
if (event.kind === vscode.TextEditorSelectionChangeKind.Keyboard && changeStartLine >= previewStartLine) {
|
||||||
const changeText = textEditor.document.getText(activeSelection);
|
const changeText = textEditor.document.getText(activeSelection);
|
||||||
|
|
||||||
|
@ -176,7 +178,6 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handles Enter key separately
|
|
||||||
vscode.workspace.onDidChangeTextDocument(async (event) => {
|
vscode.workspace.onDidChangeTextDocument(async (event) => {
|
||||||
const textEditor = vscode.window.activeTextEditor;
|
const textEditor = vscode.window.activeTextEditor;
|
||||||
if (!textEditor || event.document.uri.toString() !== textEditor.document.uri.toString() || !previewInserted || isHandlingChange) {
|
if (!textEditor || event.document.uri.toString() !== textEditor.document.uri.toString() || !previewInserted || isHandlingChange) {
|
||||||
|
@ -190,15 +191,12 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
const changeStartLine = change.range.start.line;
|
const changeStartLine = change.range.start.line;
|
||||||
|
|
||||||
if (change.text.includes('\n') && changeStartLine >= previewStartLine) {
|
if (change.text.includes('\n') && changeStartLine >= previewStartLine) {
|
||||||
// Accept the preview and move to the next line
|
|
||||||
await acceptPreview(textEditor, textEditor.document, startLine, textEditor.selection.active, completionText);
|
await acceptPreview(textEditor, textEditor.document, startLine, textEditor.selection.active, completionText);
|
||||||
await vscode.commands.executeCommand('default:type', { text: '\n' });
|
await vscode.commands.executeCommand('default:type', { text: '\n' });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Backspace
|
|
||||||
if (change.text === '' && change.rangeLength === 1 && changeStartLine >= previewStartLine) {
|
if (change.text === '' && change.rangeLength === 1 && changeStartLine >= previewStartLine) {
|
||||||
// Discard the preview if Backspace is pressed
|
|
||||||
await restoreOriginalContent();
|
await restoreOriginalContent();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -208,72 +206,46 @@ async function autocompleteCommand(textEditor: vscode.TextEditor, cancellationTo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
vscode.window.onDidChangeTextEditorSelection(async (event) => {
|
|
||||||
const textEditor = vscode.window.activeTextEditor;
|
|
||||||
if (!textEditor || !previewInserted || isHandlingChange) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isHandlingChange = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Handle arrow keys or any other navigation keys
|
|
||||||
const currentSelection = event.selections[0];
|
|
||||||
const { document } = textEditor;
|
|
||||||
|
|
||||||
// Detect unwanted acceptance from simple navigation
|
|
||||||
if (currentSelection.start.line < previewStartLine) {
|
|
||||||
await restoreOriginalContent();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
isHandlingChange = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Restore original content if Backspace is pressed (decline the preview)
|
|
||||||
const restoreOriginalContent = async () => {
|
const restoreOriginalContent = async () => {
|
||||||
if (!previewInserted) return;
|
if (!previewInserted) return;
|
||||||
|
|
||||||
const endLine = document.lineCount - 1;
|
const fullRange = new vscode.Range(previewStartLine, 0, previewEndLine, 0);
|
||||||
const fullRange = new vscode.Range(previewStartLine, 0, endLine, document.lineAt(endLine).text.length);
|
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
|
|
||||||
edit.replace(document.uri, fullRange, originalContent);
|
edit.replace(document.uri, fullRange, originalContent);
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
|
|
||||||
textEditor.setDecorations(previewDecorationType, []);
|
textEditor.setDecorations(previewDecorationType, []);
|
||||||
previewInserted = false;
|
previewInserted = false;
|
||||||
disposable.dispose(); // Cancel listener when preview is discarded
|
disposable.dispose(); // Cancel listener when preview is discarded
|
||||||
};
|
};
|
||||||
|
|
||||||
// Accept the preview when Tab is pressed
|
|
||||||
const acceptPreview = async (textEditor: vscode.TextEditor, document: vscode.TextDocument, startLine: number, position: vscode.Position, completionText: string) => {
|
const acceptPreview = async (textEditor: vscode.TextEditor, document: vscode.TextDocument, startLine: number, position: vscode.Position, completionText: string) => {
|
||||||
textEditor.setDecorations(previewDecorationType, []);
|
textEditor.setDecorations(previewDecorationType, []);
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
|
|
||||||
// Adjust the insertion logic to avoid duplicate newlines
|
const previewLines = completionText.split('\n');
|
||||||
const insertText = completionText;
|
const endLine = startLine + previewLines.length;
|
||||||
|
|
||||||
// Replace the range from the start of the context to the current position
|
// Ensure that endLine does not exceed document bounds
|
||||||
const replaceRange = new vscode.Range(startLine, 0, position.line, position.character);
|
const documentEndLine = document.lineCount - 1;
|
||||||
edit.replace(document.uri, replaceRange, insertText);
|
const finalEndLine = Math.min(endLine, documentEndLine + 1);
|
||||||
|
|
||||||
|
// Prepare the new content
|
||||||
|
const newContent = previewLines.join('\n');
|
||||||
|
|
||||||
|
// Replace the range with the new content
|
||||||
|
const replaceRange = new vscode.Range(startLine, 0, finalEndLine, document.lineAt(finalEndLine - 1).text.length);
|
||||||
|
edit.replace(document.uri, replaceRange, newContent.trim());
|
||||||
|
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
await document.save();
|
await document.save();
|
||||||
|
|
||||||
disposable.dispose(); // Cancel listener when preview is accepted
|
disposable.dispose(); // Cancel listener when preview is accepted
|
||||||
previewInserted = false;
|
previewInserted = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call this function to initiate the preview
|
|
||||||
await storeAndInsertPreview();
|
await storeAndInsertPreview();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
"Fabelous Autocoder encountered an error: " + err.message
|
"Fabelous Autocoder encountered an error: " + err.message
|
||||||
|
|
Loading…
Reference in New Issue