From 55a46397ac2479afde2759e7f2744d9e38087625 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Thu, 22 Jun 2017 09:52:13 -0700 Subject: [PATCH] Improve multi cursor in abbr actions #27621 --- extensions/emmet/src/abbreviationActions.ts | 87 +++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 6d5c86f2bb233..fd91ec55efb60 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -22,15 +22,55 @@ export function wrapWithAbbreviation() { vscode.window.showInputBox({ prompt: 'Enter Abbreviation' }).then(abbr => { if (!abbr || !abbr.trim()) { return; } + + let textToReplaceList: [string, vscode.Range][] = []; + let firstTextToReplace: string; + let allTextToReplaceSame: boolean = true; + editor.selections.forEach(selection => { let rangeToReplace: vscode.Range = selection; if (rangeToReplace.isEmpty) { rangeToReplace = new vscode.Range(rangeToReplace.start.line, 0, rangeToReplace.start.line, editor.document.lineAt(rangeToReplace.start.line).text.length); } let textToReplace = editor.document.getText(rangeToReplace); - let expandedText = expand(abbr, getExpandOptions(syntax, textToReplace)); - editor.insertSnippet(new vscode.SnippetString(expandedText), rangeToReplace); + + if (!firstTextToReplace) { + firstTextToReplace = textToReplace; + } else if (allTextToReplaceSame && firstTextToReplace !== textToReplace) { + allTextToReplaceSame = false; + } + + textToReplaceList.push([textToReplace, rangeToReplace]); + }); + + if (textToReplaceList.length === 0) { + return; + } + + // Text to replace at multiple cursors are not the same + // `editor.insertSnippet` will have to be called for each instance separately + // We will not be able to maintain multiple cursors after snippet insertion + if (!allTextToReplaceSame) { + textToReplaceList.forEach(([textToReplace, rangeToReplace]) => { + let expandedText = expand(abbr, getExpandOptions(syntax, textToReplace)); + if (expandedText) { + editor.insertSnippet(new vscode.SnippetString(expandedText), rangeToReplace); + } + }); + return; + } + + // Text to replace at all cursors are the same + // We can pass all ranges to `editor.insertSnippet` in a single call so that + // all cursors are maintained after snippet insertion + let expandedText = expand(abbr, getExpandOptions(syntax, textToReplaceList[0][0])); + let allRanges = textToReplaceList.map(value => { + return value[1]; }); + if (expandedText) { + editor.insertSnippet(new vscode.SnippetString(expandedText), allRanges); + } + }); } @@ -48,6 +88,10 @@ export function expandAbbreviation(args) { let parseContent = isStyleSheet(syntax) ? parseStylesheet : parse; let rootNode: Node = parseContent(new DocumentStreamReader(editor.document)); + let abbreviationList: [string, vscode.Range][] = []; + let firstAbbreviation: string; + let allAbbreviationsSame: boolean = true; + editor.selections.forEach(selection => { let abbreviationRange: vscode.Range = selection; let position = selection.isReversed ? selection.anchor : selection.active; @@ -61,11 +105,44 @@ export function expandAbbreviation(args) { return; } - let expandedText = expand(abbreviation, getExpandOptions(syntax)); - if (expandedText) { - editor.insertSnippet(new vscode.SnippetString(expandedText), abbreviationRange); + if (!firstAbbreviation) { + firstAbbreviation = abbreviation; + } else if (allAbbreviationsSame && firstAbbreviation !== abbreviation) { + allAbbreviationsSame = false; } + + abbreviationList.push([abbreviation, abbreviationRange]); + }); + + if (abbreviationList.length === 0) { + return; + } + + // Abbreviations at multiple cursors are not the same + // `editor.insertSnippet` will have to be called for each abbreviation separately + // We will not be able to maintain multiple cursors after snippet insertion + if (!allAbbreviationsSame) { + abbreviationList.forEach(([abbreviation, abbreviationRange]) => { + let expandedText = expand(abbreviation, getExpandOptions(syntax)); + if (expandedText) { + editor.insertSnippet(new vscode.SnippetString(expandedText), abbreviationRange); + } + }); + return; + } + + // Abbreviations at all cursors are the same + // We can pass all ranges to `editor.insertSnippet` in a single call so that + // all cursors are maintained after snippet insertion + let expandedText = expand(abbreviationList[0][0], getExpandOptions(syntax)); + let allRanges = abbreviationList.map(value => { + return value[1]; }); + if (expandedText) { + editor.insertSnippet(new vscode.SnippetString(expandedText), allRanges); + } + + }