Merge pull request #48023 from brentwang23/master
Implement word part move and delete for issue #46203
This commit is contained in:
commit
1cc8ec4cd8
5 changed files with 487 additions and 4 deletions
|
@ -333,11 +333,11 @@ export function compareIgnoreCase(a: string, b: string): number {
|
|||
}
|
||||
}
|
||||
|
||||
function isLowerAsciiLetter(code: number): boolean {
|
||||
export function isLowerAsciiLetter(code: number): boolean {
|
||||
return code >= CharCode.a && code <= CharCode.z;
|
||||
}
|
||||
|
||||
function isUpperAsciiLetter(code: number): boolean {
|
||||
export function isUpperAsciiLetter(code: number): boolean {
|
||||
return code >= CharCode.A && code <= CharCode.Z;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { WordCharacterClassifier, WordCharacterClass, getMapForWordSeparators }
|
|||
import * as strings from 'vs/base/common/strings';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
|
||||
interface IFindWordResult {
|
||||
/**
|
||||
|
@ -235,7 +236,7 @@ export class WordOperations {
|
|||
return new Position(lineNumber, column);
|
||||
}
|
||||
|
||||
private static _deleteWordLeftWhitespace(model: ICursorSimpleModel, position: Position): Range {
|
||||
protected static _deleteWordLeftWhitespace(model: ICursorSimpleModel, position: Position): Range {
|
||||
const lineContent = model.getLineContent(position.lineNumber);
|
||||
const startIndex = position.column - 2;
|
||||
const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex);
|
||||
|
@ -310,7 +311,7 @@ export class WordOperations {
|
|||
return len;
|
||||
}
|
||||
|
||||
private static _deleteWordRightWhitespace(model: ICursorSimpleModel, position: Position): Range {
|
||||
protected static _deleteWordRightWhitespace(model: ICursorSimpleModel, position: Position): Range {
|
||||
const lineContent = model.getLineContent(position.lineNumber);
|
||||
const startIndex = position.column - 1;
|
||||
const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex);
|
||||
|
@ -463,3 +464,128 @@ export class WordOperations {
|
|||
return cursor.move(true, lineNumber, column, 0);
|
||||
}
|
||||
}
|
||||
|
||||
export function _lastWordPartEnd(str: string, startIndex: number = str.length - 1): number {
|
||||
for (let i = startIndex; i >= 0; i--) {
|
||||
let chCode = str.charCodeAt(i);
|
||||
if (chCode === CharCode.Space || chCode === CharCode.Tab || strings.isUpperAsciiLetter(chCode) || chCode === CharCode.Underline) {
|
||||
return i - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function _nextWordPartBegin(str: string, startIndex: number = str.length - 1): number {
|
||||
const checkLowerCase = str.charCodeAt(startIndex - 1) === CharCode.Space; // does a lc char count as a part start?
|
||||
for (let i = startIndex; i < str.length; ++i) {
|
||||
let chCode = str.charCodeAt(i);
|
||||
if (chCode === CharCode.Space || chCode === CharCode.Tab || strings.isUpperAsciiLetter(chCode) || (checkLowerCase && strings.isLowerAsciiLetter(chCode))) {
|
||||
return i + 1;
|
||||
}
|
||||
if (chCode === CharCode.Underline) {
|
||||
return i + 2;
|
||||
}
|
||||
}
|
||||
return str.length + 1;
|
||||
}
|
||||
|
||||
export class WordPartOperations extends WordOperations {
|
||||
public static deleteWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
|
||||
if (!selection.isEmpty()) {
|
||||
return selection;
|
||||
}
|
||||
|
||||
const position = new Position(selection.positionLineNumber, selection.positionColumn);
|
||||
const lineNumber = position.lineNumber;
|
||||
const column = position.column;
|
||||
|
||||
if (lineNumber === 1 && column === 1) {
|
||||
// Ignore deleting at beginning of file
|
||||
return null;
|
||||
}
|
||||
|
||||
if (whitespaceHeuristics) {
|
||||
let r = WordOperations._deleteWordLeftWhitespace(model, position);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
const wordRange = WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
|
||||
const lastWordPartEnd = _lastWordPartEnd(model.getLineContent(position.lineNumber), position.column - 2);
|
||||
const wordPartRange = new Range(lineNumber, column, lineNumber, lastWordPartEnd + 2);
|
||||
|
||||
if (wordPartRange.getStartPosition().isBeforeOrEqual(wordRange.getStartPosition())) {
|
||||
return wordRange;
|
||||
}
|
||||
return wordPartRange;
|
||||
}
|
||||
|
||||
public static deleteWordPartRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
|
||||
if (!selection.isEmpty()) {
|
||||
return selection;
|
||||
}
|
||||
|
||||
const position = new Position(selection.positionLineNumber, selection.positionColumn);
|
||||
const lineNumber = position.lineNumber;
|
||||
const column = position.column;
|
||||
|
||||
const lineCount = model.getLineCount();
|
||||
const maxColumn = model.getLineMaxColumn(lineNumber);
|
||||
if (lineNumber === lineCount && column === maxColumn) {
|
||||
// Ignore deleting at end of file
|
||||
return null;
|
||||
}
|
||||
|
||||
if (whitespaceHeuristics) {
|
||||
let r = WordOperations._deleteWordRightWhitespace(model, position);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
const wordRange = WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
|
||||
const nextWordPartBegin = _nextWordPartBegin(model.getLineContent(position.lineNumber), position.column);
|
||||
const wordPartRange = new Range(lineNumber, column, lineNumber, nextWordPartBegin);
|
||||
|
||||
if (wordRange.getEndPosition().isBeforeOrEqual(wordPartRange.getEndPosition())) {
|
||||
return wordRange;
|
||||
}
|
||||
return wordPartRange;
|
||||
}
|
||||
|
||||
public static moveWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
const lineNumber = position.lineNumber;
|
||||
const column = position.column;
|
||||
if (column === 1) {
|
||||
return (lineNumber > 1 ? new Position(lineNumber - 1, model.getLineMaxColumn(lineNumber - 1)) : position);
|
||||
}
|
||||
|
||||
const wordPos = WordOperations.moveWordLeft(wordSeparators, model, position, wordNavigationType);
|
||||
const lastWordPartEnd = _lastWordPartEnd(model.getLineContent(lineNumber), column - 2);
|
||||
const wordPartPos = new Position(lineNumber, lastWordPartEnd + 2);
|
||||
|
||||
if (wordPartPos.isBeforeOrEqual(wordPos)) {
|
||||
return wordPos;
|
||||
}
|
||||
return wordPartPos;
|
||||
}
|
||||
|
||||
public static moveWordPartRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
const lineNumber = position.lineNumber;
|
||||
const column = position.column;
|
||||
const maxColumn = model.getLineMaxColumn(lineNumber);
|
||||
if (column === maxColumn) {
|
||||
return (lineNumber < model.getLineCount() ? new Position(lineNumber + 1, 1) : position);
|
||||
}
|
||||
|
||||
const wordPos = WordOperations.moveWordRight(wordSeparators, model, position, wordNavigationType);
|
||||
const nextWordPartBegin = _nextWordPartBegin(model.getLineContent(lineNumber), column);
|
||||
const wordPartPos = new Position(lineNumber, nextWordPartBegin);
|
||||
|
||||
if (wordPos.isBeforeOrEqual(wordPartPos)) {
|
||||
return wordPos;
|
||||
}
|
||||
return wordPartPos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import {
|
||||
DeleteWordPartLeft, DeleteWordPartRight,
|
||||
CursorWordPartLeft, CursorWordPartRight
|
||||
} from 'vs/editor/contrib/wordPartOperations/wordPartOperations';
|
||||
import { EditorCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
suite('WordPartOperations', () => {
|
||||
const _deleteWordPartLeft = new DeleteWordPartLeft();
|
||||
const _deleteWordPartRight = new DeleteWordPartRight();
|
||||
const _cursorWordPartLeft = new CursorWordPartLeft();
|
||||
const _cursorWordPartRight = new CursorWordPartRight();
|
||||
|
||||
function runEditorCommand(editor: ICodeEditor, command: EditorCommand): void {
|
||||
command.runEditorCommand(null, editor, null);
|
||||
}
|
||||
function moveWordPartLeft(editor: ICodeEditor, inSelectionmode: boolean = false): void {
|
||||
runEditorCommand(editor, inSelectionmode ? _cursorWordPartLeft : _cursorWordPartLeft);
|
||||
}
|
||||
function moveWordPartRight(editor: ICodeEditor, inSelectionmode: boolean = false): void {
|
||||
runEditorCommand(editor, inSelectionmode ? _cursorWordPartLeft : _cursorWordPartRight);
|
||||
}
|
||||
function deleteWordPartLeft(editor: ICodeEditor): void {
|
||||
runEditorCommand(editor, _deleteWordPartLeft);
|
||||
}
|
||||
function deleteWordPartRight(editor: ICodeEditor): void {
|
||||
runEditorCommand(editor, _deleteWordPartRight);
|
||||
}
|
||||
|
||||
test('move word part left basic', () => {
|
||||
withTestCodeEditor([
|
||||
'start line',
|
||||
'thisIsACamelCaseVar this_is_a_snake_case_var',
|
||||
'end line'
|
||||
], {}, (editor, _) => {
|
||||
editor.setPosition(new Position(3, 8));
|
||||
const expectedStops = [
|
||||
[3, 5],
|
||||
[3, 4],
|
||||
[3, 1],
|
||||
[2, 46],
|
||||
[2, 42],
|
||||
[2, 37],
|
||||
[2, 31],
|
||||
[2, 29],
|
||||
[2, 26],
|
||||
[2, 22],
|
||||
[2, 21],
|
||||
[2, 20],
|
||||
[2, 17],
|
||||
[2, 13],
|
||||
[2, 8],
|
||||
[2, 7],
|
||||
[2, 5],
|
||||
[2, 1],
|
||||
[1, 11],
|
||||
[1, 7],
|
||||
[1, 6],
|
||||
[1, 1]
|
||||
];
|
||||
|
||||
let actualStops: number[][] = [];
|
||||
for (let i = 0; i < expectedStops.length; i++) {
|
||||
moveWordPartLeft(editor);
|
||||
const pos = editor.getPosition();
|
||||
actualStops.push([pos.lineNumber, pos.column]);
|
||||
}
|
||||
|
||||
assert.deepEqual(actualStops, expectedStops);
|
||||
});
|
||||
});
|
||||
|
||||
test('move word part right basic', () => {
|
||||
withTestCodeEditor([
|
||||
'start line',
|
||||
'thisIsACamelCaseVar this_is_a_snake_case_var',
|
||||
'end line'
|
||||
], {}, (editor, _) => {
|
||||
editor.setPosition(new Position(1, 1));
|
||||
const expectedStops = [
|
||||
[1, 6],
|
||||
[1, 7],
|
||||
[1, 11],
|
||||
[2, 1],
|
||||
[2, 5],
|
||||
[2, 7],
|
||||
[2, 8],
|
||||
[2, 13],
|
||||
[2, 17],
|
||||
[2, 20],
|
||||
[2, 21],
|
||||
[2, 22],
|
||||
[2, 27],
|
||||
[2, 30],
|
||||
[2, 32],
|
||||
[2, 38],
|
||||
[2, 43],
|
||||
[2, 46],
|
||||
[3, 1],
|
||||
[3, 4],
|
||||
[3, 5],
|
||||
[3, 9]
|
||||
];
|
||||
|
||||
let actualStops: number[][] = [];
|
||||
for (let i = 0; i < expectedStops.length; i++) {
|
||||
moveWordPartRight(editor);
|
||||
const pos = editor.getPosition();
|
||||
actualStops.push([pos.lineNumber, pos.column]);
|
||||
}
|
||||
|
||||
assert.deepEqual(actualStops, expectedStops);
|
||||
});
|
||||
});
|
||||
|
||||
test('delete word part left basic', () => {
|
||||
withTestCodeEditor([
|
||||
' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var'
|
||||
], {}, (editor, _) => {
|
||||
const model = editor.getModel();
|
||||
editor.setPosition(new Position(1, 84));
|
||||
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case', '001');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake', '002');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a', '003');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is', '004');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this', '005');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar ', '006');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar', '007');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamelCase', '008');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsACamel', '009');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIsA', '010');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ thisIs', '011');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ this', '012');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */ ', '013');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 */', '014');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3 ', '015');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-3', '015bis');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5-', '016');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +5', '017');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 +', '018');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3 ', '019');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= 3', '019bis');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+= ', '020');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a+=', '021');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text a', '022');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text ', '023');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some text', '024');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some ', '025');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just some', '026');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just ', '027');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* Just', '028');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /* ', '029');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' /*', '030');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), ' ', '031');
|
||||
deleteWordPartLeft(editor); assert.equal(model.getLineContent(1), '', '032');
|
||||
});
|
||||
});
|
||||
|
||||
test('delete word part right basic', () => {
|
||||
withTestCodeEditor([
|
||||
' /* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var'
|
||||
], {}, (editor, _) => {
|
||||
const model = editor.getModel();
|
||||
editor.setPosition(new Position(1, 1));
|
||||
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '/* Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '001');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '002');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'Just some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '003');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '004');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'some text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '005');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '006');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'text a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '007');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '008');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'a+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '009');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '+= 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '010');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' 3 +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '011');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' +5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '012');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '5-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '013');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '-3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '014');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '3 */ thisIsACamelCaseVar this_is_a_snake_case_var', '015');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' */ thisIsACamelCaseVar this_is_a_snake_case_var', '016');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' thisIsACamelCaseVar this_is_a_snake_case_var', '017');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'thisIsACamelCaseVar this_is_a_snake_case_var', '018');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'IsACamelCaseVar this_is_a_snake_case_var', '019');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'ACamelCaseVar this_is_a_snake_case_var', '020');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'CamelCaseVar this_is_a_snake_case_var', '021');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'CaseVar this_is_a_snake_case_var', '022');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'Var this_is_a_snake_case_var', '023');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), ' this_is_a_snake_case_var', '024');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'this_is_a_snake_case_var', '025');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'is_a_snake_case_var', '026');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'a_snake_case_var', '027');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'snake_case_var', '028');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'case_var', '029');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), 'var', '030');
|
||||
deleteWordPartRight(editor); assert.equal(model.getLineContent(1), '', '031');
|
||||
});
|
||||
});
|
||||
});
|
147
src/vs/editor/contrib/wordPartOperations/wordPartOperations.ts
Normal file
147
src/vs/editor/contrib/wordPartOperations/wordPartOperations.ts
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { registerEditorCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { WordNavigationType, WordPartOperations } from 'vs/editor/common/controller/cursorWordOperations';
|
||||
import { WordCharacterClassifier } from 'vs/editor/common/controller/wordCharacterClassifier';
|
||||
import { DeleteWordCommand, MoveWordCommand } from '../wordOperations/wordOperations';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
|
||||
export class DeleteWordPartLeft extends DeleteWordCommand {
|
||||
constructor() {
|
||||
super({
|
||||
whitespaceHeuristics: true,
|
||||
wordNavigationType: WordNavigationType.WordStart,
|
||||
id: 'deleteWordPartLeft',
|
||||
precondition: EditorContextKeys.writable,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Backspace,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Backspace }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
|
||||
let r = WordPartOperations.deleteWordPartLeft(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
return new Range(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteWordPartRight extends DeleteWordCommand {
|
||||
constructor() {
|
||||
super({
|
||||
whitespaceHeuristics: true,
|
||||
wordNavigationType: WordNavigationType.WordEnd,
|
||||
id: 'deleteWordPartRight',
|
||||
precondition: EditorContextKeys.writable,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Delete,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Delete }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
|
||||
let r = WordPartOperations.deleteWordPartRight(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
const lineCount = model.getLineCount();
|
||||
const maxColumn = model.getLineMaxColumn(lineCount);
|
||||
return new Range(lineCount, maxColumn, lineCount, maxColumn);
|
||||
}
|
||||
}
|
||||
|
||||
export class WordPartLeftCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return WordPartOperations.moveWordPartLeft(wordSeparators, model, position, wordNavigationType);
|
||||
}
|
||||
}
|
||||
export class CursorWordPartLeft extends WordPartLeftCommand {
|
||||
constructor() {
|
||||
super({
|
||||
inSelectionMode: false,
|
||||
wordNavigationType: WordNavigationType.WordStart,
|
||||
id: 'cursorWordPartStartLeft',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.LeftArrow }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export class CursorWordPartLeftSelect extends WordPartLeftCommand {
|
||||
constructor() {
|
||||
super({
|
||||
inSelectionMode: true,
|
||||
wordNavigationType: WordNavigationType.WordStart,
|
||||
id: 'cursorWordPartStartLeftSelect',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class WordPartRightCommand extends MoveWordCommand {
|
||||
protected _move(wordSeparators: WordCharacterClassifier, model: ITextModel, position: Position, wordNavigationType: WordNavigationType): Position {
|
||||
return WordPartOperations.moveWordPartRight(wordSeparators, model, position, wordNavigationType);
|
||||
}
|
||||
}
|
||||
export class CursorWordPartRight extends WordPartRightCommand {
|
||||
constructor() {
|
||||
super({
|
||||
inSelectionMode: false,
|
||||
wordNavigationType: WordNavigationType.WordEnd,
|
||||
id: 'cursorWordPartRight',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.RightArrow }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export class CursorWordPartRightSelect extends WordPartRightCommand {
|
||||
constructor() {
|
||||
super({
|
||||
inSelectionMode: true,
|
||||
wordNavigationType: WordNavigationType.WordEnd,
|
||||
id: 'cursorWordPartRightSelect',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registerEditorCommand(new DeleteWordPartLeft());
|
||||
registerEditorCommand(new DeleteWordPartRight());
|
||||
registerEditorCommand(new CursorWordPartLeft());
|
||||
registerEditorCommand(new CursorWordPartLeftSelect());
|
||||
registerEditorCommand(new CursorWordPartRight());
|
||||
registerEditorCommand(new CursorWordPartRightSelect());
|
|
@ -42,3 +42,4 @@ import 'vs/editor/contrib/suggest/suggestController';
|
|||
import 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode';
|
||||
import 'vs/editor/contrib/wordHighlighter/wordHighlighter';
|
||||
import 'vs/editor/contrib/wordOperations/wordOperations';
|
||||
import 'vs/editor/contrib/wordPartOperations/wordPartOperations';
|
||||
|
|
Loading…
Reference in a new issue