aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/commands/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/commands/index.ts')
-rw-r--r--editors/code/src/commands/index.ts89
1 files changed, 53 insertions, 36 deletions
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts
index 0937b495c..abb53a248 100644
--- a/editors/code/src/commands/index.ts
+++ b/editors/code/src/commands/index.ts
@@ -41,48 +41,65 @@ export function applySourceChange(ctx: Ctx): Cmd {
41 }; 41 };
42} 42}
43 43
44export function selectAndApplySourceChange(ctx: Ctx): Cmd { 44export function applyActionGroup(_ctx: Ctx): Cmd {
45 return async (changes: ra.SourceChange[]) => { 45 return async (actions: { label: string; edit: vscode.WorkspaceEdit }[]) => {
46 if (changes.length === 1) { 46 const selectedAction = await vscode.window.showQuickPick(actions);
47 await sourceChange.applySourceChange(ctx, changes[0]); 47 if (!selectedAction) return;
48 } else if (changes.length > 0) { 48 await applySnippetWorkspaceEdit(selectedAction.edit);
49 const selectedChange = await vscode.window.showQuickPick(changes);
50 if (!selectedChange) return;
51 await sourceChange.applySourceChange(ctx, selectedChange);
52 }
53 }; 49 };
54} 50}
55 51
56export function applySnippetWorkspaceEdit(_ctx: Ctx): Cmd { 52export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd {
57 return async (edit: vscode.WorkspaceEdit) => { 53 return async (edit: vscode.WorkspaceEdit) => {
58 assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); 54 await applySnippetWorkspaceEdit(edit);
59 const [uri, edits] = edit.entries()[0]; 55 };
56}
60 57
61 const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); 58export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
62 if (!editor) return; 59 assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`);
60 const [uri, edits] = edit.entries()[0];
63 61
64 let editWithSnippet: vscode.TextEdit | undefined = undefined; 62 const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
65 let lineDelta = 0; 63 if (!editor) return;
66 await editor.edit((builder) => { 64
67 for (const indel of edits) { 65 let selection: vscode.Selection | undefined = undefined;
68 const isSnippet = indel.newText.indexOf('$0') !== -1 || indel.newText.indexOf('${') !== -1; 66 let lineDelta = 0;
69 if (isSnippet) { 67 await editor.edit((builder) => {
70 editWithSnippet = indel; 68 for (const indel of edits) {
71 } else { 69 const parsed = parseSnippet(indel.newText);
72 if (!editWithSnippet) { 70 if (parsed) {
73 lineDelta = (indel.newText.match(/\n/g) || []).length - (indel.range.end.line - indel.range.start.line); 71 const [newText, [placeholderStart, placeholderLength]] = parsed;
74 } 72 const prefix = newText.substr(0, placeholderStart);
75 builder.replace(indel.range, indel.newText); 73 const lastNewline = prefix.lastIndexOf('\n');
76 } 74
75 const startLine = indel.range.start.line + lineDelta + countLines(prefix);
76 const startColumn = lastNewline === -1 ?
77 indel.range.start.character + placeholderStart
78 : prefix.length - lastNewline - 1;
79 const endColumn = startColumn + placeholderLength;
80 selection = new vscode.Selection(
81 new vscode.Position(startLine, startColumn),
82 new vscode.Position(startLine, endColumn),
83 );
84 builder.replace(indel.range, newText);
85 } else {
86 lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line);
87 builder.replace(indel.range, indel.newText);
77 } 88 }
78 });
79 if (editWithSnippet) {
80 const snip = editWithSnippet as vscode.TextEdit;
81 const range = snip.range.with(
82 snip.range.start.with(snip.range.start.line + lineDelta),
83 snip.range.end.with(snip.range.end.line + lineDelta),
84 );
85 await editor.insertSnippet(new vscode.SnippetString(snip.newText), range);
86 } 89 }
87 }; 90 });
91 if (selection) editor.selection = selection;
92}
93
94function parseSnippet(snip: string): [string, [number, number]] | undefined {
95 const m = snip.match(/\$(0|\{0:([^}]*)\})/);
96 if (!m) return undefined;
97 const placeholder = m[2] ?? "";
98 const range: [number, number] = [m.index!!, placeholder.length];
99 const insert = snip.replace(m[0], placeholder);
100 return [insert, range];
101}
102
103function countLines(text: string): number {
104 return (text.match(/\n/g) || []).length;
88} 105}