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.ts70
1 files changed, 61 insertions, 9 deletions
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts
index bdb7fc3b0..abb53a248 100644
--- a/editors/code/src/commands/index.ts
+++ b/editors/code/src/commands/index.ts
@@ -4,6 +4,7 @@ import * as ra from '../rust-analyzer-api';
4 4
5import { Ctx, Cmd } from '../ctx'; 5import { Ctx, Cmd } from '../ctx';
6import * as sourceChange from '../source_change'; 6import * as sourceChange from '../source_change';
7import { assert } from '../util';
7 8
8export * from './analyzer_status'; 9export * from './analyzer_status';
9export * from './matching_brace'; 10export * from './matching_brace';
@@ -40,14 +41,65 @@ export function applySourceChange(ctx: Ctx): Cmd {
40 }; 41 };
41} 42}
42 43
43export function selectAndApplySourceChange(ctx: Ctx): Cmd { 44export function applyActionGroup(_ctx: Ctx): Cmd {
44 return async (changes: ra.SourceChange[]) => { 45 return async (actions: { label: string; edit: vscode.WorkspaceEdit }[]) => {
45 if (changes.length === 1) { 46 const selectedAction = await vscode.window.showQuickPick(actions);
46 await sourceChange.applySourceChange(ctx, changes[0]); 47 if (!selectedAction) return;
47 } else if (changes.length > 0) { 48 await applySnippetWorkspaceEdit(selectedAction.edit);
48 const selectedChange = await vscode.window.showQuickPick(changes); 49 };
49 if (!selectedChange) return; 50}
50 await sourceChange.applySourceChange(ctx, selectedChange); 51
51 } 52export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd {
53 return async (edit: vscode.WorkspaceEdit) => {
54 await applySnippetWorkspaceEdit(edit);
52 }; 55 };
53} 56}
57
58export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
59 assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`);
60 const [uri, edits] = edit.entries()[0];
61
62 const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
63 if (!editor) return;
64
65 let selection: vscode.Selection | undefined = undefined;
66 let lineDelta = 0;
67 await editor.edit((builder) => {
68 for (const indel of edits) {
69 const parsed = parseSnippet(indel.newText);
70 if (parsed) {
71 const [newText, [placeholderStart, placeholderLength]] = parsed;
72 const prefix = newText.substr(0, placeholderStart);
73 const lastNewline = prefix.lastIndexOf('\n');
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);
88 }
89 }
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;
105}