提交 9fc25c06 编写于 作者: A Alexandru Dima 提交者: GitHub

Merge pull request #15787 from rebornix/MissingCommands

Add missing Sublime/Atom commands
......@@ -10,6 +10,7 @@ import { SortLinesCommand } from 'vs/editor/contrib/linesOperations/common/sortL
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
import { EditorContextKeys, Handler, ICommand, ICommonCodeEditor, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
import { ReplaceCommand, ReplaceCommandThatPreservesSelection, ReplaceCommandWithOffsetCursorState } from 'vs/editor/common/commands/replaceCommand';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { editorAction, ServicesAccessor, IActionOptions, EditorAction, HandlerEditorAction } from 'vs/editor/common/editorCommonExtensions';
......@@ -401,3 +402,202 @@ export class DeleteAllLeftAction extends EditorAction {
editor.executeEdits(this.id, edits);
}
}
@editorAction
export class JoinLinesAction extends EditorAction {
constructor() {
super({
id: 'editor.action.joinLines',
label: nls.localize('lines.joinLines', "Join Lines"),
alias: 'Join Lines',
precondition: EditorContextKeys.Writable,
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: KeyMod.WinCtrl | KeyCode.KEY_J
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let selection = editor.getSelection();
let model = editor.getModel();
let startLineNumber = selection.startLineNumber;
let startColumn = 1;
let endLineNumber: number,
endColumn: number,
columnDeltaOffset: number;
let selectionEndPositionOffset = model.getLineContent(selection.endLineNumber).length - selection.endColumn;
if (selection.isEmpty() || selection.startLineNumber === selection.endLineNumber) {
let position = selection.getStartPosition();
if (position.lineNumber < model.getLineCount()) {
endLineNumber = startLineNumber + 1;
endColumn = model.getLineMaxColumn(endLineNumber);
} else {
endLineNumber = position.lineNumber;
endColumn = model.getLineMaxColumn(position.lineNumber);
}
} else {
endLineNumber = selection.endLineNumber;
endColumn = model.getLineMaxColumn(endLineNumber);
}
let trimmedLinesContent = model.getLineContent(startLineNumber);
for (let i = startLineNumber + 1; i <= endLineNumber; i++) {
let lineText = model.getLineContent(i);
let firstNonWhitespaceIdx = model.getLineFirstNonWhitespaceColumn(i);
if (firstNonWhitespaceIdx >= 1) {
let insertSpace = true;
if (trimmedLinesContent === '') {
insertSpace = false;
}
if (insertSpace && (trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === ' ' ||
trimmedLinesContent.charAt(trimmedLinesContent.length - 1) === '\t')) {
insertSpace = false;
trimmedLinesContent = trimmedLinesContent.replace(/[\s\uFEFF\xA0]+$/g, ' ');
}
let lineTextWithoutIndent = lineText.substr(firstNonWhitespaceIdx - 1);
trimmedLinesContent += (insertSpace ? ' ' : '') + lineTextWithoutIndent;
if (insertSpace) {
columnDeltaOffset = lineTextWithoutIndent.length + 1;
} else {
columnDeltaOffset = lineTextWithoutIndent.length;
}
} else {
columnDeltaOffset = 0;
}
}
let deleteSelection = new Range(
startLineNumber,
startColumn,
endLineNumber,
endColumn
);
if (!deleteSelection.isEmpty()) {
if (selection.isEmpty()) {
editor.executeCommand(this.id,
new ReplaceCommandWithOffsetCursorState(deleteSelection, trimmedLinesContent, 0, -columnDeltaOffset)
);
} else {
if (selection.startLineNumber === selection.endLineNumber) {
editor.executeCommand(this.id,
new ReplaceCommandThatPreservesSelection(deleteSelection, trimmedLinesContent, selection)
);
} else {
editor.executeCommand(this.id, new ReplaceCommand(deleteSelection, trimmedLinesContent));
editor.setSelection(new Selection(selection.startLineNumber, selection.startColumn,
selection.startLineNumber, trimmedLinesContent.length - selectionEndPositionOffset));
}
}
}
}
}
@editorAction
export class TransposeAction extends EditorAction {
constructor() {
super({
id: 'editor.action.transpose',
label: nls.localize('editor.transpose', "Transpose characters around the cursor"),
alias: 'Transpose characters around the cursor',
precondition: EditorContextKeys.Writable
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let selections = editor.getSelections();
let model = editor.getModel();
let commands: ICommand[] = [];
for (let i = 0, len = selections.length; i < len; i++) {
let selection = selections[i];
if (selection.isEmpty()) {
let cursor = selection.getStartPosition();
if (cursor.column > model.getLineContent(cursor.lineNumber).length) {
return;
}
let deleteSelection = new Range(cursor.lineNumber, Math.max(1, cursor.column - 1), cursor.lineNumber, cursor.column + 1);
let chars = model.getValueInRange(deleteSelection).split('').reverse().join('');
commands.push(new ReplaceCommandThatPreservesSelection(deleteSelection, chars,
new Selection(cursor.lineNumber, cursor.column + 1, cursor.lineNumber, cursor.column + 1)));
}
}
editor.executeCommands(this.id, commands);
}
}
export abstract class AbstractCaseAction extends EditorAction {
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let selections = editor.getSelections();
let model = editor.getModel();
let commands: ICommand[] = [];
for (let i = 0, len = selections.length; i < len; i++) {
let selection = selections[i];
if (selection.isEmpty()) {
let cursor = selection.getStartPosition();
let word = model.getWordAtPosition(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),
new Selection(cursor.lineNumber, cursor.column, cursor.lineNumber, cursor.column)));
} else {
let text = model.getValueInRange(selection);
commands.push(new ReplaceCommandThatPreservesSelection(selection, this._modifyText(text), selection));
}
}
editor.executeCommands(this.id, commands);
}
protected abstract _modifyText(text: string): string;
}
@editorAction
export class UpperCaseAction extends AbstractCaseAction {
constructor() {
super({
id: 'editor.action.transformToUppercase',
label: nls.localize('editor.transformToUppercase', "Transform to Uppercase"),
alias: 'Transform to Uppercase',
precondition: EditorContextKeys.Writable
});
}
protected _modifyText(text: string): string {
return text.toLocaleUpperCase();
}
}
@editorAction
export class LowerCaseAction extends AbstractCaseAction {
constructor() {
super({
id: 'editor.action.transformToLowercase',
label: nls.localize('editor.transformToLowercase', "Transform to Lowercase"),
alias: 'Transform to Lowercase',
precondition: EditorContextKeys.Writable
});
}
protected _modifyText(text: string): string {
return text.toLocaleLowerCase();
}
}
......@@ -7,7 +7,7 @@
import * as assert from 'assert';
import { Selection } from 'vs/editor/common/core/selection';
import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { DeleteAllLeftAction } from 'vs/editor/contrib/linesOperations/common/linesOperations';
import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction } from 'vs/editor/contrib/linesOperations/common/linesOperations';
suite('Editor Contrib - Line Operations', () => {
test('delete all left', function () {
......@@ -67,4 +67,161 @@ suite('Editor Contrib - Line Operations', () => {
assert.equal(model.getLineContent(5), 'horlworld', '005');
});
});
test('Join lines', function () {
withMockCodeEditor(
[
'hello',
'world',
'hello ',
'world',
'hello ',
' world',
'hello ',
' world',
'',
'',
'hello world'
], {}, (editor, cursor) => {
let model = editor.getModel();
let joinLinesAction = new JoinLinesAction();
editor.setSelection(new Selection(1, 2, 1, 2));
joinLinesAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hello world', '001');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 6, 1, 6).toString(), '002');
editor.setSelection(new Selection(2, 2, 2, 2));
joinLinesAction.run(null, editor);
assert.equal(model.getLineContent(2), 'hello world', '003');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 7, 2, 7).toString(), '004');
editor.setSelection(new Selection(3, 2, 3, 2));
joinLinesAction.run(null, editor);
assert.equal(model.getLineContent(3), 'hello world', '005');
assert.deepEqual(editor.getSelection().toString(), new Selection(3, 7, 3, 7).toString(), '006');
editor.setSelection(new Selection(4, 2, 5, 3));
joinLinesAction.run(null, editor);
assert.equal(model.getLineContent(4), 'hello world', '007');
assert.deepEqual(editor.getSelection().toString(), new Selection(4, 2, 4, 8).toString(), '008');
editor.setSelection(new Selection(5, 1, 7, 3));
joinLinesAction.run(null, editor);
assert.equal(model.getLineContent(5), 'hello world', '009');
assert.deepEqual(editor.getSelection().toString(), new Selection(5, 1, 5, 3).toString(), '010');
});
});
test('transpose', function () {
withMockCodeEditor(
[
'hello world',
'',
' '
], {}, (editor, cursor) => {
let model = editor.getModel();
let transposeAction = new TransposeAction();
editor.setSelection(new Selection(1, 1, 1, 1));
transposeAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hello world', '001');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 2, 1, 2).toString(), '002');
editor.setSelection(new Selection(1, 6, 1, 6));
transposeAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hell oworld', '003');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 7, 1, 7).toString(), '004');
editor.setSelection(new Selection(1, 12, 1, 12));
transposeAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hell oworld', '005');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 12, 1, 12).toString(), '006');
editor.setSelection(new Selection(2, 1, 2, 1));
transposeAction.run(null, editor);
assert.equal(model.getLineContent(2), '', '007');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 1, 2, 1).toString(), '008');
editor.setSelection(new Selection(3, 2, 3, 2));
transposeAction.run(null, editor);
assert.equal(model.getLineContent(3), ' ', '009');
assert.deepEqual(editor.getSelection().toString(), new Selection(3, 3, 3, 3).toString(), '010');
}
);
});
test('toggle case', function () {
withMockCodeEditor(
[
'hello world',
'öçşğü'
], {}, (editor, cursor) => {
let model = editor.getModel();
let uppercaseAction = new UpperCaseAction();
let lowercaseAction = new LowerCaseAction();
editor.setSelection(new Selection(1, 1, 1, 12));
uppercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), 'HELLO WORLD', '001');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 1, 1, 12).toString(), '002');
editor.setSelection(new Selection(1, 1, 1, 12));
lowercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hello world', '003');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 1, 1, 12).toString(), '004');
editor.setSelection(new Selection(1, 3, 1, 3));
uppercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), 'HELLO world', '005');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 3, 1, 3).toString(), '006');
editor.setSelection(new Selection(1, 4, 1, 4));
lowercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), 'hello world', '007');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 4, 1, 4).toString(), '008');
editor.setSelection(new Selection(2, 1, 2, 6));
uppercaseAction.run(null, editor);
assert.equal(model.getLineContent(2), 'ÖÇŞĞÜ', '009');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 1, 2, 6).toString(), '010');
editor.setSelection(new Selection(2, 1, 2, 6));
lowercaseAction.run(null, editor);
assert.equal(model.getLineContent(2), 'öçşğü', '011');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 1, 2, 6).toString(), '012');
}
);
withMockCodeEditor(
[
'',
' '
], {}, (editor, cursor) => {
let model = editor.getModel();
let uppercaseAction = new UpperCaseAction();
let lowercaseAction = new LowerCaseAction();
editor.setSelection(new Selection(1, 1, 1, 1));
uppercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), '', '001');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 1, 1, 1).toString(), '002');
editor.setSelection(new Selection(1, 1, 1, 1));
lowercaseAction.run(null, editor);
assert.equal(model.getLineContent(1), '', '003');
assert.deepEqual(editor.getSelection().toString(), new Selection(1, 1, 1, 1).toString(), '004');
editor.setSelection(new Selection(2, 2, 2, 2));
uppercaseAction.run(null, editor);
assert.equal(model.getLineContent(2), ' ', '005');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 2, 2, 2).toString(), '006');
editor.setSelection(new Selection(2, 2, 2, 2));
lowercaseAction.run(null, editor);
assert.equal(model.getLineContent(2), ' ', '007');
assert.deepEqual(editor.getSelection().toString(), new Selection(2, 2, 2, 2).toString(), '008');
}
);
});
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册