-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextension.js
More file actions
160 lines (153 loc) · 5.96 KB
/
extension.js
File metadata and controls
160 lines (153 loc) · 5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
const vscode = require("vscode");
const {
getIndentUnit,
getCodePart,
getGuessedIndentUnit,
indentLines,
calculateIndentedLines,
preprocessClipboardText,
getBaseIndentLevel,
adjustInsertTextForMidLinePaste,
calculateDedentsForCut
} = require('./logic');
/**
* Removes surrounding whitespace (spaces or tabs) around the cursor position.
* @param {vscode.TextEditor} editor - The active text editor.
* @param {vscode.TextEditorEdit} editBuilder - The edit builder for modifying the document.
* @returns {vscode.Position} The new cursor position after whitespace removal.
*/
function removeSurroundingWhitespace(editor, editBuilder) {
const document = editor.document;
const selection = editor.selection;
const startPos = selection.start;
const endPos = selection.end;
const newStartLine = startPos.line;
let newStartCharacter = startPos.character;
const newEndLine = endPos.line;
let newEndCharacter = endPos.character;
const startLine = document.lineAt(startPos.line);
const startText = startLine.text;
const isStartWhitespace = /^[\s\t]*$/.test(startText.substring(0, startPos.character));
const endLine = document.lineAt(endPos.line);
const endText = endLine.text;
const isEndWhitespace = /^[\s\t]*$/.test(endText.substring(endPos.character));
if (isStartWhitespace) {
if (selection.isEmpty) {
if (isEndWhitespace) newStartCharacter = 0;
} else if (newStartLine !== newEndLine || (newStartLine === newEndLine && newEndCharacter === startText.length)) {
newStartCharacter = 0;
}
}
if (isEndWhitespace) newEndCharacter = endText.length;
const rangeToDelete = new vscode.Range(
newStartLine,
newStartCharacter,
newEndLine,
newEndCharacter
);
editBuilder.delete(rangeToDelete);
return new vscode.Position(newStartLine, newStartCharacter);
}
/**
* Inserts the final processed and indented text into the editor.
* Handles removing surrounding whitespace and adjusting insertion based on cursor position.
* @param {vscode.TextEditor} editor - The active text editor.
* @param {string} insertText - The text to insert.
* @param {string} separator - The line separator used.
*/
async function insertPastedText(editor, insertText, separator) {
await editor.edit((editBuilder) => {
const selection = editor.selection;
const startLine = selection.start.line;
const endLine = selection.end.line;
const endChar = selection.end.character;
const isSingleLineWithNewline = startLine + 1 === endLine && endChar === 0;
let adjustedInsertText = adjustInsertTextForMidLinePaste(editor, selection, insertText);
if (isSingleLineWithNewline) adjustedInsertText += separator;
let newPosition = removeSurroundingWhitespace(editor, editBuilder);
editBuilder.insert(newPosition, adjustedInsertText);
});
}
/**
* Performs a cut operation, adjusting indentation of subsequent lines if needed.
* @param {vscode.TextEditor} editor - The active text editor.
*/
async function cut(editor) {
if (!editor || editor.document.languageId !== "python") return;
const selection = editor.selection;
if (selection.isEmpty) return;
await editor.edit((editBuilder) => {
const selectedText = editor.document
.getText(new vscode.Range(selection.start, selection.end));
editBuilder.delete(selection);
vscode.env.clipboard.writeText(selectedText);
const startLine = selection.start.line;
const endLine = selection.end.line;
const endChar = selection.end.character;
const isSingleLine = startLine === endLine;
const isSingleLineWithNewline = startLine + 1 === endLine && endChar === 0;
if (
!((isSingleLine || isSingleLineWithNewline) && getCodePart(selectedText).endsWith(':'))
) {
return;
}
const totalLines = editor.document.lineCount;
const baseLine = editor.document.lineAt(startLine);
const indentUnit = getIndentUnit(editor);
const baseIndent = baseLine.text.match(/^\s*/)?.[0] || "";
const baseIndentLevel = Math.floor(baseIndent.length / indentUnit.length);
if (startLine + 1 >= totalLines) return;
const rangeRemaining = new vscode.Range(startLine + 1, 0, totalLines, 0);
const textRemaining = editor.document.getText(rangeRemaining);
const separator = textRemaining.includes("\r\n") ? "\r\n" : "\n";
const linesRemaining = textRemaining.split(separator);
const { lines: dedentedLines, count } = calculateDedentsForCut(linesRemaining, baseIndentLevel, indentUnit);
for (let i = 0; i < count; i++) {
const lineIndex = startLine + 1 + i;
const newText = dedentedLines[i];
const line = editor.document.lineAt(lineIndex);
editBuilder.replace(line.range, newText);
}
});
}
/**
* Performs a paste operation with proper indentation adjustment for Python code.
* @param {vscode.TextEditor} editor - The active text editor.
*/
async function paste(editor) {
if (!editor || editor.document.languageId !== "python") return;
const clipboardText = await vscode.env.clipboard.readText();
if (!clipboardText.trim()) return;
const { lines: processedLines, separator } = preprocessClipboardText(clipboardText);
const indentUnit = getIndentUnit(editor);
const baseIndentLevel = getBaseIndentLevel(editor, indentUnit);
const indentedLines = calculateIndentedLines(processedLines, baseIndentLevel, indentUnit);
const insertText = indentedLines.join(separator);
await insertPastedText(editor, insertText, separator);
}
/**
* Activates the extension.
* @param {vscode.ExtensionContext} context - The extension context.
*/
function activate(context) {
context.subscriptions.push(
vscode.commands.registerTextEditorCommand("pythonPastePro.cut", cut),
vscode.commands.registerTextEditorCommand("pythonPastePro.paste", paste)
);
}
/**
* Deactivates the extension.
*/
function deactivate() { }
module.exports = {
activate,
deactivate,
getIndentUnit,
getCodePart,
getGuessedIndentUnit,
indentLines,
calculateIndentedLines,
preprocessClipboardText,
getBaseIndentLevel,
adjustInsertTextForMidLinePaste
};