From 3182ea7f89a713ee9170563dffc8fa34fe005c6c Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Tue, 17 Nov 2020 21:22:44 +0330 Subject: [PATCH 1/4] snake case --- .../linesOperations/linesOperations.ts | 16 ++++ .../test/linesOperations.test.ts | 95 ++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 9c365d50709..9d1b105c357 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -1049,6 +1049,21 @@ export class TitleCaseAction extends AbstractCaseAction { } } +export class SnakeCaseAction extends AbstractCaseAction { + constructor() { + super({ + id: 'editor.action.transformToSnakecase', + label: nls.localize('editor.transformToSnakecase', "Transform to Snake Case"), + alias: 'Transform to Snake Case', + precondition: EditorContextKeys.writable + }); + } + + protected _modifyText(text: string, wordSeparators: string): string { + return text.replace(/(?<=\p{Ll})(\p{Lu})|(? { withTestCodeEditor( [ 'hello world', - 'öçşğü' + 'öçşğü', + 'parseHTMLString', + 'getElementById', + 'insertHTML', + 'PascalCase', + 'CSSSelectorsList', + 'iD', + 'tEST', + 'öçşÖÇŞğüĞÜ', + 'myObject.doSomethingV2();', + 'snake_case', + 'Capital_Snake_Case', + 'kebab-case', + 'Capital-Kebab-Case', + 'Title Case', + 'some text' ], {}, (editor) => { let model = editor.getModel()!; let uppercaseAction = new UpperCaseAction(); let lowercaseAction = new LowerCaseAction(); let titlecaseAction = new TitleCaseAction(); + let snakecaseAction = new SnakeCaseAction(); editor.setSelection(new Selection(1, 1, 1, 12)); executeAction(uppercaseAction, editor); @@ -580,6 +596,81 @@ suite('Editor Contrib - Line Operations', () => { executeAction(titlecaseAction, editor); assert.equal(model.getLineContent(2), 'Öçşğü'); assertSelection(editor, new Selection(2, 1, 2, 6)); + + editor.setSelection(new Selection(3, 1, 3, 16)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(3), 'parse_html_string'); + assertSelection(editor, new Selection(3, 1, 3, 16)); + + editor.setSelection(new Selection(4, 1, 4, 15)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(4), 'get_element_by_id'); + assertSelection(editor, new Selection(4, 1, 4, 15)); + + editor.setSelection(new Selection(5, 1, 5, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(5), 'insert_html'); + assertSelection(editor, new Selection(5, 1, 5, 11)); + + editor.setSelection(new Selection(6, 1, 6, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(6), 'pascal_case'); + assertSelection(editor, new Selection(6, 1, 6, 11)); + + editor.setSelection(new Selection(7, 1, 7, 17)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(7), 'css_selectors_list'); + assertSelection(editor, new Selection(7, 1, 7, 17)); + + editor.setSelection(new Selection(8, 1, 8, 3)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(8), 'i_d'); + assertSelection(editor, new Selection(8, 1, 8, 3)); + + editor.setSelection(new Selection(9, 1, 9, 5)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(9), 't_est'); + assertSelection(editor, new Selection(9, 1, 9, 5)); + + editor.setSelection(new Selection(10, 1, 10, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); + assertSelection(editor, new Selection(10, 1, 10, 11)); + + editor.setSelection(new Selection(11, 1, 11, 26)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); + assertSelection(editor, new Selection(11, 1, 11, 26)); + + editor.setSelection(new Selection(12, 1, 12, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(12), 'snake_case'); + assertSelection(editor, new Selection(12, 1, 12, 11)); + + editor.setSelection(new Selection(13, 1, 13, 19)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(13), 'capital_snake_case'); + assertSelection(editor, new Selection(13, 1, 13, 19)); + + editor.setSelection(new Selection(14, 1, 14, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(14), 'kebab_case'); + assertSelection(editor, new Selection(14, 1, 14, 11)); + + editor.setSelection(new Selection(15, 1, 15, 19)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(15), 'capital_kebab_case'); + assertSelection(editor, new Selection(15, 1, 15, 19)); + + editor.setSelection(new Selection(16, 1, 16, 11)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(16), 'title_case'); + assertSelection(editor, new Selection(16, 1, 16, 11)); + + editor.setSelection(new Selection(17, 1, 17, 10)); + executeAction(snakecaseAction, editor); + assert.equal(model.getLineContent(17), 'some_text'); + assertSelection(editor, new Selection(17, 1, 17, 10)); } ); From 43418e212de38a097344769d79b9b8ef4595b2a3 Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Thu, 19 Nov 2020 20:30:00 +0330 Subject: [PATCH 2/4] update selection, better multiline support --- .../editor/common/commands/replaceCommand.ts | 45 +++++++++++++++++ .../linesOperations/linesOperations.ts | 45 ++++++++++++++++- .../test/linesOperations.test.ts | 50 +++++++------------ 3 files changed, 107 insertions(+), 33 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index 3e628f2db76..dddf007f0c8 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -142,3 +142,48 @@ export class ReplaceCommandThatPreservesSelection implements ICommand { return helper.getTrackedSelection(this._selectionId!); } } + +export class ReplaceCommandThatModifiesSelection implements ICommand { + + private readonly _range: Range; + private readonly _text: string; + private readonly _initialSelection: Selection; + private readonly _initialText: string; + private readonly _forceMoveMarkers: boolean; + + constructor(editRange: Range, text: string, initialSelection: Selection, initialText: string, forceMoveMarkers: boolean = false) { + this._range = editRange; + this._text = text; + this._initialSelection = initialSelection; + this._initialText = initialText; + this._forceMoveMarkers = forceMoveMarkers; + } + + public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { + builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers); + } + + public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { + let start = 0; + let end = 0; + let modifiedLines = this._text.split('\n'); + let initialLines = this._initialText.split('\n'); + + if (this._initialSelection.selectionStartLineNumber < this._initialSelection.positionLineNumber || + (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && + this._initialSelection.selectionStartColumn < this._initialSelection.positionColumn)) { + start = this._initialSelection.selectionStartColumn; + end = this._initialSelection.positionColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + } else if (this._initialSelection.selectionStartLineNumber > this._initialSelection.positionLineNumber || + (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && + this._initialSelection.selectionStartColumn > this._initialSelection.positionColumn)) { + end = this._initialSelection.positionColumn; + start = this._initialSelection.selectionStartColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + } else { + start = this._initialSelection.selectionStartColumn; + end = this._initialSelection.positionColumn; + } + + return new Selection(this._initialSelection.selectionStartLineNumber, start, this._initialSelection.positionLineNumber, end); + } +} diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 9d1b105c357..6e3765bf9f8 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -8,7 +8,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, IActionOptions, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions'; -import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText } from 'vs/editor/common/commands/replaceCommand'; +import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText, ReplaceCommandThatModifiesSelection } from 'vs/editor/common/commands/replaceCommand'; import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -1059,8 +1059,49 @@ export class SnakeCaseAction extends AbstractCaseAction { }); } + public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { + let selections = editor.getSelections(); + if (selections === null) { + return; + } + + let model = editor.getModel(); + if (model === null) { + return; + } + + let wordSeparators = editor.getOption(EditorOption.wordSeparators); + + let commands: ICommand[] = []; + + for (let i = 0, len = selections.length; i < len; i++) { + let selection = selections[i]; + if (selection.isEmpty()) { + let cursor = selection.getStartPosition(); + const word = editor.getConfiguredWordAtPosition(cursor); + + if (!word) { + continue; + } + + let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + let text = model.getValueInRange(wordRange); + commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), + new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); + + } else { + let text = model.getValueInRange(selection); + commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); + } + } + + editor.pushUndoStop(); + editor.executeCommands(this.id, commands); + editor.pushUndoStop(); + } + protected _modifyText(text: string, wordSeparators: string): string { - return text.replace(/(?<=\p{Ll})(\p{Lu})|(? { 'myObject.doSomethingV2();', 'snake_case', 'Capital_Snake_Case', - 'kebab-case', - 'Capital-Kebab-Case', - 'Title Case', - 'some text' + `function helloWorld() { + return someGlobalObject.printHelloWorld("en", "utf-8"); + } + helloWorld();`.replace(/^\s+/gm, '') ], {}, (editor) => { let model = editor.getModel()!; let uppercaseAction = new UpperCaseAction(); @@ -600,47 +600,47 @@ suite('Editor Contrib - Line Operations', () => { editor.setSelection(new Selection(3, 1, 3, 16)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(3), 'parse_html_string'); - assertSelection(editor, new Selection(3, 1, 3, 16)); + assertSelection(editor, new Selection(3, 1, 3, 18)); editor.setSelection(new Selection(4, 1, 4, 15)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(4), 'get_element_by_id'); - assertSelection(editor, new Selection(4, 1, 4, 15)); + assertSelection(editor, new Selection(4, 1, 4, 18)); editor.setSelection(new Selection(5, 1, 5, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(5), 'insert_html'); - assertSelection(editor, new Selection(5, 1, 5, 11)); + assertSelection(editor, new Selection(5, 1, 5, 12)); editor.setSelection(new Selection(6, 1, 6, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(6), 'pascal_case'); - assertSelection(editor, new Selection(6, 1, 6, 11)); + assertSelection(editor, new Selection(6, 1, 6, 12)); editor.setSelection(new Selection(7, 1, 7, 17)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(7), 'css_selectors_list'); - assertSelection(editor, new Selection(7, 1, 7, 17)); + assertSelection(editor, new Selection(7, 1, 7, 19)); editor.setSelection(new Selection(8, 1, 8, 3)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(8), 'i_d'); - assertSelection(editor, new Selection(8, 1, 8, 3)); + assertSelection(editor, new Selection(8, 1, 8, 4)); editor.setSelection(new Selection(9, 1, 9, 5)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(9), 't_est'); - assertSelection(editor, new Selection(9, 1, 9, 5)); + assertSelection(editor, new Selection(9, 1, 9, 6)); editor.setSelection(new Selection(10, 1, 10, 11)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); - assertSelection(editor, new Selection(10, 1, 10, 11)); + assertSelection(editor, new Selection(10, 1, 10, 14)); editor.setSelection(new Selection(11, 1, 11, 26)); executeAction(snakecaseAction, editor); assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); - assertSelection(editor, new Selection(11, 1, 11, 26)); + assertSelection(editor, new Selection(11, 1, 11, 29)); editor.setSelection(new Selection(12, 1, 12, 11)); executeAction(snakecaseAction, editor); @@ -652,25 +652,13 @@ suite('Editor Contrib - Line Operations', () => { assert.equal(model.getLineContent(13), 'capital_snake_case'); assertSelection(editor, new Selection(13, 1, 13, 19)); - editor.setSelection(new Selection(14, 1, 14, 11)); + editor.setSelection(new Selection(14, 1, 17, 14)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(14), 'kebab_case'); - assertSelection(editor, new Selection(14, 1, 14, 11)); - - editor.setSelection(new Selection(15, 1, 15, 19)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(15), 'capital_kebab_case'); - assertSelection(editor, new Selection(15, 1, 15, 19)); - - editor.setSelection(new Selection(16, 1, 16, 11)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(16), 'title_case'); - assertSelection(editor, new Selection(16, 1, 16, 11)); - - editor.setSelection(new Selection(17, 1, 17, 10)); - executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(17), 'some_text'); - assertSelection(editor, new Selection(17, 1, 17, 10)); + assert.equal(model.getValueInRange(new Selection(14, 1, 17, 15)), `function hello_world() { + return some_global_object.print_hello_world("en", "utf-8"); + } + hello_world();`.replace(/^\s+/gm, '')); + assertSelection(editor, new Selection(14, 1, 17, 15)); } ); From fc393cae1bb07c6b49212618871ac4d3101a9534 Mon Sep 17 00:00:00 2001 From: a5hk <5412540+a5hk@users.noreply.github.com> Date: Sun, 22 Nov 2020 18:30:01 +0330 Subject: [PATCH 3/4] readability and test improvements --- .../editor/common/commands/replaceCommand.ts | 39 +++++++++++-------- .../linesOperations/linesOperations.ts | 20 +++++----- .../test/linesOperations.test.ts | 8 ++-- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index dddf007f0c8..0d4aa010d60 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -164,26 +164,31 @@ export class ReplaceCommandThatModifiesSelection implements ICommand { } public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { - let start = 0; - let end = 0; - let modifiedLines = this._text.split('\n'); - let initialLines = this._initialText.split('\n'); + let startColumn = 0; + let endColumn = 0; + const modifiedLines = this._text.split('\n'); + const initialLines = this._initialText.split('\n'); + const { + selectionStartLineNumber, + positionLineNumber, + selectionStartColumn, + positionColumn + } = this._initialSelection; - if (this._initialSelection.selectionStartLineNumber < this._initialSelection.positionLineNumber || - (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && - this._initialSelection.selectionStartColumn < this._initialSelection.positionColumn)) { - start = this._initialSelection.selectionStartColumn; - end = this._initialSelection.positionColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); - } else if (this._initialSelection.selectionStartLineNumber > this._initialSelection.positionLineNumber || - (this._initialSelection.selectionStartLineNumber === this._initialSelection.positionLineNumber && - this._initialSelection.selectionStartColumn > this._initialSelection.positionColumn)) { - end = this._initialSelection.positionColumn; - start = this._initialSelection.selectionStartColumn + (modifiedLines[modifiedLines.length - 1].length - initialLines[initialLines.length - 1].length); + const lastInitialLineLength = initialLines[initialLines.length - 1].length; + const lastModifiedLineLength = modifiedLines[modifiedLines.length - 1].length; + + if (selectionStartLineNumber < positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn < positionColumn)) { + startColumn = selectionStartColumn; + endColumn = positionColumn + (lastModifiedLineLength - lastInitialLineLength); + } else if (selectionStartLineNumber > positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn > positionColumn)) { + endColumn = positionColumn; + startColumn = selectionStartColumn + (lastModifiedLineLength - lastInitialLineLength); } else { - start = this._initialSelection.selectionStartColumn; - end = this._initialSelection.positionColumn; + startColumn = selectionStartColumn; + endColumn = positionColumn; } - return new Selection(this._initialSelection.selectionStartLineNumber, start, this._initialSelection.positionLineNumber, end); + return new Selection(selectionStartLineNumber, startColumn, positionLineNumber, endColumn); } } diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 6e3765bf9f8..48f57a6cff8 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -1060,37 +1060,35 @@ export class SnakeCaseAction extends AbstractCaseAction { } public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - let selections = editor.getSelections(); + const selections = editor.getSelections(); if (selections === null) { return; } - let model = editor.getModel(); + const model = editor.getModel(); if (model === null) { return; } - let wordSeparators = editor.getOption(EditorOption.wordSeparators); + const wordSeparators = editor.getOption(EditorOption.wordSeparators); + const commands: ICommand[] = []; - let commands: ICommand[] = []; - - for (let i = 0, len = selections.length; i < len; i++) { - let selection = selections[i]; + for (const selection of selections) { if (selection.isEmpty()) { - let cursor = selection.getStartPosition(); + const cursor = selection.getStartPosition(); const word = editor.getConfiguredWordAtPosition(cursor); if (!word) { continue; } - let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - let text = model.getValueInRange(wordRange); + const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + const text = model.getValueInRange(wordRange); commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); } else { - let text = model.getValueInRange(selection); + const text = model.getValueInRange(selection); commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); } } diff --git a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts index 7e977e20559..f7b6b002f42 100644 --- a/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/linesOperations.test.ts @@ -543,7 +543,7 @@ suite('Editor Contrib - Line Operations', () => { 'iD', 'tEST', 'öçşÖÇŞğüĞÜ', - 'myObject.doSomethingV2();', + 'audioConverter.convertM4AToMP3();', 'snake_case', 'Capital_Snake_Case', `function helloWorld() { @@ -637,10 +637,10 @@ suite('Editor Contrib - Line Operations', () => { assert.equal(model.getLineContent(10), 'öçş_öç_şğü_ğü'); assertSelection(editor, new Selection(10, 1, 10, 14)); - editor.setSelection(new Selection(11, 1, 11, 26)); + editor.setSelection(new Selection(11, 1, 11, 34)); executeAction(snakecaseAction, editor); - assert.equal(model.getLineContent(11), 'my_object.do_something_v2();'); - assertSelection(editor, new Selection(11, 1, 11, 29)); + assert.equal(model.getLineContent(11), 'audio_converter.convert_m4a_to_mp3();'); + assertSelection(editor, new Selection(11, 1, 11, 38)); editor.setSelection(new Selection(12, 1, 12, 11)); executeAction(snakecaseAction, editor); From db27c55205685574af50bbbf44d57491ed992b1d Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Fri, 18 Dec 2020 17:55:51 +0100 Subject: [PATCH 4/4] Adopt `ICodeEditor.executeEdits` --- .../editor/common/commands/replaceCommand.ts | 50 -------------- .../linesOperations/linesOperations.ts | 69 ++++--------------- 2 files changed, 13 insertions(+), 106 deletions(-) diff --git a/src/vs/editor/common/commands/replaceCommand.ts b/src/vs/editor/common/commands/replaceCommand.ts index 0d4aa010d60..3e628f2db76 100644 --- a/src/vs/editor/common/commands/replaceCommand.ts +++ b/src/vs/editor/common/commands/replaceCommand.ts @@ -142,53 +142,3 @@ export class ReplaceCommandThatPreservesSelection implements ICommand { return helper.getTrackedSelection(this._selectionId!); } } - -export class ReplaceCommandThatModifiesSelection implements ICommand { - - private readonly _range: Range; - private readonly _text: string; - private readonly _initialSelection: Selection; - private readonly _initialText: string; - private readonly _forceMoveMarkers: boolean; - - constructor(editRange: Range, text: string, initialSelection: Selection, initialText: string, forceMoveMarkers: boolean = false) { - this._range = editRange; - this._text = text; - this._initialSelection = initialSelection; - this._initialText = initialText; - this._forceMoveMarkers = forceMoveMarkers; - } - - public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { - builder.addTrackedEditOperation(this._range, this._text, this._forceMoveMarkers); - } - - public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection { - let startColumn = 0; - let endColumn = 0; - const modifiedLines = this._text.split('\n'); - const initialLines = this._initialText.split('\n'); - const { - selectionStartLineNumber, - positionLineNumber, - selectionStartColumn, - positionColumn - } = this._initialSelection; - - const lastInitialLineLength = initialLines[initialLines.length - 1].length; - const lastModifiedLineLength = modifiedLines[modifiedLines.length - 1].length; - - if (selectionStartLineNumber < positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn < positionColumn)) { - startColumn = selectionStartColumn; - endColumn = positionColumn + (lastModifiedLineLength - lastInitialLineLength); - } else if (selectionStartLineNumber > positionLineNumber || (selectionStartLineNumber === positionLineNumber && selectionStartColumn > positionColumn)) { - endColumn = positionColumn; - startColumn = selectionStartColumn + (lastModifiedLineLength - lastInitialLineLength); - } else { - startColumn = selectionStartColumn; - endColumn = positionColumn; - } - - return new Selection(selectionStartLineNumber, startColumn, positionLineNumber, endColumn); - } -} diff --git a/src/vs/editor/contrib/linesOperations/linesOperations.ts b/src/vs/editor/contrib/linesOperations/linesOperations.ts index 48f57a6cff8..8d3f3e6f8cc 100644 --- a/src/vs/editor/contrib/linesOperations/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/linesOperations.ts @@ -8,7 +8,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, IActionOptions, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions'; -import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText, ReplaceCommandThatModifiesSelection } from 'vs/editor/common/commands/replaceCommand'; +import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandThatSelectsText } from 'vs/editor/common/commands/replaceCommand'; import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { EditOperation } from 'vs/editor/common/core/editOperation'; @@ -939,43 +939,39 @@ export class TransposeAction extends EditorAction { export abstract class AbstractCaseAction extends EditorAction { public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - let selections = editor.getSelections(); + const selections = editor.getSelections(); if (selections === null) { return; } - let model = editor.getModel(); + const model = editor.getModel(); if (model === null) { return; } - let wordSeparators = editor.getOption(EditorOption.wordSeparators); + const wordSeparators = editor.getOption(EditorOption.wordSeparators); + const textEdits: IIdentifiedSingleEditOperation[] = []; - let commands: ICommand[] = []; - - for (let i = 0, len = selections.length; i < len; i++) { - let selection = selections[i]; + for (const selection of selections) { if (selection.isEmpty()) { - let cursor = selection.getStartPosition(); + const cursor = selection.getStartPosition(); const word = editor.getConfiguredWordAtPosition(cursor); if (!word) { continue; } - let wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - let text = model.getValueInRange(wordRange); - commands.push(new ReplaceCommandThatPreservesSelection(wordRange, this._modifyText(text, wordSeparators), - new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column))); - + const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); + const text = model.getValueInRange(wordRange); + textEdits.push(EditOperation.replace(wordRange, this._modifyText(text, wordSeparators))); } else { - let text = model.getValueInRange(selection); - commands.push(new ReplaceCommandThatPreservesSelection(selection, this._modifyText(text, wordSeparators), selection)); + const text = model.getValueInRange(selection); + textEdits.push(EditOperation.replace(selection, this._modifyText(text, wordSeparators))); } } editor.pushUndoStop(); - editor.executeCommands(this.id, commands); + editor.executeEdits(this.id, textEdits); editor.pushUndoStop(); } @@ -1059,45 +1055,6 @@ export class SnakeCaseAction extends AbstractCaseAction { }); } - public run(_accessor: ServicesAccessor, editor: ICodeEditor): void { - const selections = editor.getSelections(); - if (selections === null) { - return; - } - - const model = editor.getModel(); - if (model === null) { - return; - } - - const wordSeparators = editor.getOption(EditorOption.wordSeparators); - const commands: ICommand[] = []; - - for (const selection of selections) { - if (selection.isEmpty()) { - const cursor = selection.getStartPosition(); - const word = editor.getConfiguredWordAtPosition(cursor); - - if (!word) { - continue; - } - - const wordRange = new Range(cursor.lineNumber, word.startColumn, cursor.lineNumber, word.endColumn); - const text = model.getValueInRange(wordRange); - commands.push(new ReplaceCommandThatModifiesSelection(wordRange, this._modifyText(text, wordSeparators), - new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column), text)); - - } else { - const text = model.getValueInRange(selection); - commands.push(new ReplaceCommandThatModifiesSelection(selection, this._modifyText(text, wordSeparators), selection, text)); - } - } - - editor.pushUndoStop(); - editor.executeCommands(this.id, commands); - editor.pushUndoStop(); - } - protected _modifyText(text: string, wordSeparators: string): string { return text.replace(/(?<=\p{Ll})(\p{Lu})|(?