Open davidpcahill opened 8 months ago
Some example pseudo-code. Likely won't need all these states but adding for examples:
# Since the actual Visual Studio Code API is not available here, we will just
# draft the refactored code. This code will not be run in this environment,
# but it can be used as a starting point for the user's local development.
# Here's a refactored version of the paste command handling part of the extension:
def refactor_paste_handling():
"""
This function represents the refactored logic for handling paste operations.
It's a pseudo-code and should be adapted to the actual TypeScript implementation.
"""
# Pseudo-code for the refactored paste handling
# State object to keep track of the extension's state
state = {
'autoSelected': False,
'lastPastePosition': None, # This will store the position of the last paste
'manualDeselection': False,
'manualSelection': False,
'recentPasteOperation': False,
'pasteTimestamp': 0,
}
# Refactored paste command
def on_paste():
# Check for manual deselection or manual selection before pasting
if state['manualDeselection'] or state['manualSelection']:
state['autoSelected'] = False
# Read content from the clipboard (to be replaced with actual API call)
clipboard_content = "clipboard content" # Placeholder for actual clipboard content
if clipboard_content:
# Logic to handle the pasting of content
# ... (omitted for brevity)
# After pasting, set the autoSelected flag and update the lastPastePosition
state['autoSelected'] = True
state['lastPastePosition'] = 'endPositionOfPastedContent' # Placeholder for actual position
state['pasteTimestamp'] = 'currentTimestamp' # Placeholder for actual timestamp
state['recentPasteOperation'] = True
# Reveal the pasted content in the editor
# ... (omitted for brevity)
# Reset the manual deselection and selection flags
state['manualDeselection'] = False
state['manualSelection'] = False
# Other parts of the extension will be refactored similarly, focusing on using the state object
# to keep track of the necessary information and to make decisions based on the current state.
return state, on_paste
# The returned state object and the on_paste function would be integrated into the actual extension code.
// State object to keep track of the extension's state
interface ExtensionState {
autoSelected: boolean;
lastPastePosition: vscode.Position | null;
manualDeselection: boolean;
manualSelection: boolean;
recentPasteOperation: boolean;
pasteTimestamp: number;
}
const state: ExtensionState = {
autoSelected: false,
lastPastePosition: null,
manualDeselection: false,
manualSelection: false,
recentPasteOperation: false,
pasteTimestamp: 0,
};
// Refactored paste command
function onPaste() {
// Check for manual deselection or manual selection before pasting
if (state.manualDeselection || state.manualSelection) {
state.autoSelected = false;
}
// Read content from the clipboard (this would be an actual API call in TypeScript)
const clipboardContent: string = vscode.env.clipboard.readText();
if (clipboardContent) {
// Logic to handle the pasting of content
// ...
// After pasting, set the autoSelected flag and update the lastPastePosition
state.autoSelected = true;
// Here you would set lastPastePosition to the actual end position of the pasted content
state.pasteTimestamp = Date.now();
state.recentPasteOperation = true;
// Reveal the pasted content in the editor
// ...
// Additional logic to handle appending pastes if needed
// ...
}
// Reset the manual deselection and selection flags
state.manualDeselection = false;
state.manualSelection = false;
}
// The rest of the extension would use the state object to track and make decisions
Additional refactoring example:
// This function is triggered whenever the text editor's selection changes
function onSelectionChange(event: vscode.TextEditorSelectionChangeEvent) {
// If a recent paste operation occurred and not enough time has passed, we won't reset the flags
if (state.recentPasteOperation && Date.now() - state.pasteTimestamp < 1000) {
return;
}
// Determine the kind of selection change (manual or auto) and update the state accordingly
if (event.kind === vscode.TextEditorSelectionChangeKind.Mouse) {
state.manualSelection = true;
state.autoSelected = false;
} else if (event.kind === vscode.TextEditorSelectionChangeKind.Keyboard) {
state.manualSelection = true;
state.autoSelected = false;
} else {
// If the selection change is neither by mouse nor keyboard, we reset the autoSelected flag
state.autoSelected = false;
}
// Reset recent paste operation flag as enough time has passed
state.recentPasteOperation = false;
}
// Register the event listener for selection changes
vscode.window.onDidChangeTextEditorSelection(onSelectionChange);
// Rest of the extension code...
// This command is triggered whenever a key is pressed
vscode.commands.registerCommand('type', async (args) => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
// Retrieve settings
const enableTypeDetection = vscode.workspace
.getConfiguration('autoSelectPastedText')
.get('enableTypeDetection');
const enableManualSelection = vscode.workspace
.getConfiguration('autoSelectPastedText')
.get('enableManualSelection');
const currentSelection = editor.selection;
// If a manual selection has been made, we don't want to mess with it unless we're allowing manual selection management
if (state.manualSelection && !enableManualSelection) {
// Reset manual selection state
state.manualSelection = false;
} else if (state.autoSelected && enableTypeDetection) {
// If the selection was auto-selected and type detection is enabled, we reset the selection to a cursor position
const currentPosition = currentSelection.active;
editor.selection = new vscode.Selection(currentPosition, currentPosition);
// Reset the auto selection state
state.autoSelected = false;
}
// Execute the default type command after adjusting the selection
await vscode.commands.executeCommand('default:type', args);
// Reset the manual selection flags after typing
state.manualSelection = false;
state.recentPasteOperation = false;
});
// This command is triggered on paste action
vscode.commands.registerCommand('editor.action.clipboardPasteAction', async () => {
const enableAutoSelection = vscode.workspace
.getConfiguration('autoSelectPastedText')
.get('enableAutoSelection');
// Log the status before pasting
log(`Before pasting - autoSelected: ${state.autoSelected}, manualSelection: ${state.manualSelection}`);
const clipboardContent = await vscode.env.clipboard.readText();
if (!clipboardContent) {
outputChannel.appendLine('Clipboard is empty.');
return;
}
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
let targetSelection: vscode.Selection;
if (state.autoSelected || state.manualSelection) {
// Append after the current selection or the cursor position
targetSelection = new vscode.Selection(editor.selection.end, editor.selection.end);
} else {
// Replace the current selection
targetSelection = editor.selection;
}
// Perform the paste operation
await editor.edit((editBuilder) => {
editBuilder.replace(targetSelection, clipboardContent);
});
// Calculate the end position for the selection post-paste
const linesPasted = clipboardContent.split('\n');
const lastLineLength = linesPasted[linesPasted.length - 1].length;
const endLine = targetSelection.start.line + linesPasted.length - 1;
const endCharacter = linesPasted.length === 1
? targetSelection.start.character + lastLineLength
: lastLineLength;
const endPosition = new vscode.Position(endLine, endCharacter);
if (enableAutoSelection) {
// Adjust the selection to cover the pasted content
editor.selection = new vscode.Selection(targetSelection.start, endPosition);
state.autoSelected = true;
state.recentPasteOperation = true;
state.pasteTimestamp = Date.now();
}
// Reveal the pasted content in the editor
editor.revealRange(new vscode.Range(targetSelection.start, endPosition), vscode.TextEditorRevealType.Default);
// Reset the manual selection flags after pasting
state.manualSelection = false;
// Log the status after pasting
log(`After pasting - autoSelected: ${state.autoSelected}, manualSelection: ${state.manualSelection}`);
});
// Event listener for selection changes in the editor
vscode.window.onDidChangeTextEditorSelection((event) => {
// Check if the selection change is within a short time window after a paste operation
if (state.recentPasteOperation && Date.now() - state.pasteTimestamp < 1000) {
log('Selection change likely due to recent paste, not resetting autoSelected flag.');
// We don't reset state.recentPasteOperation here as it might be an auto-selection
} else {
// Enough time has passed since the last paste operation, or there was no recent paste
state.autoSelected = false;
state.recentPasteOperation = false;
}
// Detect if the selection was changed manually via mouse or keyboard
if (event.kind === vscode.TextEditorSelectionChangeKind.Mouse) {
state.manualSelection = true;
state.autoSelected = false;
} else if (event.kind === vscode.TextEditorSelectionChangeKind.Keyboard) {
state.manualSelection = true;
state.autoSelected = false;
} else {
// If the selection change is not due to mouse or keyboard, it's not a manual selection
state.manualSelection = false;
}
// Log the selection change for debugging purposes
if (event.textEditor.document.uri.scheme === 'file') {
const selection = event.selections[0];
log(`Selection changed: Start(${selection.start.line}, ${selection.start.character}), End(${selection.end.line}, ${selection.end.character})`);
}
// Log the status after selection changes
log(`After selection change - autoSelected: ${state.autoSelected}, manualSelection: ${state.manualSelection}`);
});
// Register the type command to handle the deselection behavior
vscode.commands.registerCommand('type', async (args) => {
const editor = vscode.window.activeTextEditor;
if (editor) {
const currentSelection = editor.selection;
// If there's a non-empty selection and it's an auto-selection, we reset it to a cursor position
if (!currentSelection.isEmpty && state.autoSelected) {
const currentPosition = currentSelection.active;
editor.selection = new vscode.Selection(currentPosition, currentPosition);
state.autoSelected = false; // Reset the autoSelected flag after the type operation
}
// Execute the default type command after adjusting the selection
await vscode.commands.executeCommand('default:type', args);
}
// Log the status after typing
log(`After typing - autoSelected: ${state.autoSelected}, manualSelection: ${state.manualSelection}`);
});
// Register the paste command
let pasteCommandDisposable = vscode.commands.registerCommand(
'editor.action.clipboardPasteAction',
async () => {
const enableAutoSelection = vscode.workspace
.getConfiguration('autoSelectPastedText')
.get('enableAutoSelection');
// Read content from clipboard
const clipboardContent = await vscode.env.clipboard.readText();
if (clipboardContent) {
const editor = vscode.window.activeTextEditor;
if (editor) {
let targetSelection: vscode.Selection;
// Determine the target for the paste: either append after the current selection or replace it
if (state.autoSelected) {
const currentPosition = editor.selection.end;
targetSelection = new vscode.Selection(currentPosition, currentPosition);
} else {
targetSelection = editor.selection;
}
// Split content by lines to calculate the selection end position later
const linesPasted = clipboardContent.split('\n');
const lastLineLength = linesPasted[linesPasted.length - 1].length;
editor.edit((editBuilder) => {
// Replace the determined target selection with the clipboard content
editBuilder.replace(targetSelection, clipboardContent);
}).then((success) => {
if (success) {
// Determine the end position for the selection post-paste
const endLine = targetSelection.start.line + linesPasted.length - 1;
const endCharacter = linesPasted.length === 1 ? targetSelection.start.character + lastLineLength : lastLineLength;
const endPosition = new vscode.Position(endLine, endCharacter);
if (enableAutoSelection) {
// Adjust the selection to cover the pasted content
editor.selection = new vscode.Selection(targetSelection.start, endPosition);
state.autoSelected = true;
state.pasteTimestamp = Date.now();
state.recentPasteOperation = true;
}
// Reveal the pasted content in the editor
editor.revealRange(new vscode.Range(targetSelection.start, endPosition), vscode.TextEditorRevealType.Default);
}
});
}
}
// Reset the manual selection flags
state.manualSelection = false;
// Log the status after pasting
log(`After pasting - autoSelected: ${state.autoSelected}, manualSelection: ${state.manualSelection}`);
}
);
// Add the paste command disposable to the extension context's subscriptions
context.subscriptions.push(pasteCommandDisposable);
As always, if anyone wants to put in a merge request, I would be very happy for any help. <3
I'm still having problems with many states. We keep tacking on tracking variables but should have used a state machine to begin with. This will need to be a major rewrite and I will need development resources to help meet the base requirements: