diff --git a/src/vs/editor/browser/editor.all.ts b/src/vs/editor/browser/editor.all.ts index 19ead3cbcafe716695b783dfadb34b35cbc53bd8..cd56e43c2fab5d83a20ef845878fa4210a73732d 100644 --- a/src/vs/editor/browser/editor.all.ts +++ b/src/vs/editor/browser/editor.all.ts @@ -5,6 +5,7 @@ 'use strict'; +import 'vs/editor/common/controller/coreCommands'; import 'vs/editor/browser/widget/codeEditorWidget'; import 'vs/editor/browser/widget/diffEditorWidget'; diff --git a/src/vs/editor/common/commonCodeEditor.ts b/src/vs/editor/common/commonCodeEditor.ts index 2fef9136e64c924fde2b69cc2112dcb0b4508c84..3c8ecce71b18fd2044ac9997c356c88b92e1588a 100644 --- a/src/vs/editor/common/commonCodeEditor.ts +++ b/src/vs/editor/common/commonCodeEditor.ts @@ -13,7 +13,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IContextKey, IContextKeyServiceTarget, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { CommonEditorConfiguration } from 'vs/editor/common/config/commonEditorConfig'; import { Cursor } from 'vs/editor/common/controller/cursor'; -import { CursorColumns, IViewModelHelper, ICursors } from 'vs/editor/common/controller/cursorCommon'; +import { CursorColumns, IViewModelHelper, ICursors, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range, IRange } from 'vs/editor/common/core/range'; import { Selection, ISelection } from 'vs/editor/common/core/selection'; @@ -698,6 +698,10 @@ export abstract class CommonCodeEditor extends Disposable implements editorCommo return this.cursor; } + public _getCursorConfiguration(): CursorConfiguration { + return this.cursor.context.config; + } + public pushUndoStop(): boolean { if (!this.model) { return false; diff --git a/src/vs/editor/common/controller/coreCommands.ts b/src/vs/editor/common/controller/coreCommands.ts index 6ad405c37a1f58f1437ae253af9499701e7b79b8..ae8a6e85e1ace49fd32039f34ab0be68738279ca 100644 --- a/src/vs/editor/common/controller/coreCommands.ts +++ b/src/vs/editor/common/controller/coreCommands.ts @@ -1395,7 +1395,10 @@ export namespace CoreNavigationCommands { ); } }); -}; +} + +export namespace CoreEditingCommands { +} namespace Config { diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index aec7779027468832051bba23a06403e53d4d3e54..42b712abd335a06d6ff0eb171922f75f2bcfa9d8 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -504,7 +504,6 @@ export class Cursor extends Disposable implements ICursors { private _registerHandlers(): void { let H = editorCommon.Handler; - this._handlers[H.LineInsertBefore] = (args) => this._lineInsertBefore(args); this._handlers[H.LineInsertAfter] = (args) => this._lineInsertAfter(args); this._handlers[H.LineBreakInsert] = (args) => this._lineBreakInsert(args); @@ -559,10 +558,6 @@ export class Cursor extends Disposable implements ICursors { return r; } - private _lineInsertBefore(args: CursorOperationArgs): EditOperationResult { - return TypeOperations.lineInsertBefore(this.context.config, this.context.model, this._getAllCursorsModelState()); - } - private _lineInsertAfter(args: CursorOperationArgs): EditOperationResult { return TypeOperations.lineInsertAfter(this.context.config, this.context.model, this._getAllCursorsModelState()); } diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index b231d46d1e4b7086a7e49dbdd8124aed18e681a0..7d9346cf06d67cc7ebcbec75f688c3288394c7f0 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -582,11 +582,11 @@ export class TypeOperations { }); } - public static lineInsertBefore(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[]): EditOperationResult { + public static lineInsertBefore(config: CursorConfiguration, model: ITokenizedModel, cursors: Selection[]): ICommand[] { let commands: ICommand[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; - let lineNumber = cursor.position.lineNumber; + let lineNumber = cursor.positionLineNumber; if (lineNumber === 1) { commands[i] = new ReplaceCommandWithoutChangingPosition(new Range(1, 1, 1, 1), '\n'); @@ -597,10 +597,7 @@ export class TypeOperations { commands[i] = this._enter(config, model, false, new Range(lineNumber, column, lineNumber, column)); } } - return new EditOperationResult(commands, { - shouldPushStackElementBefore: true, - shouldPushStackElementAfter: false, - }); + return commands; } public static lineInsertAfter(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[]): EditOperationResult { diff --git a/src/vs/editor/common/core/selection.ts b/src/vs/editor/common/core/selection.ts index 21f2066d982ed606068aa2b81885b045b38becd4..10705ad4fe8d82ec5714f96df591141727e4e5db 100644 --- a/src/vs/editor/common/core/selection.ts +++ b/src/vs/editor/common/core/selection.ts @@ -5,7 +5,7 @@ 'use strict'; import { Range } from 'vs/editor/common/core/range'; -import { IPosition } from 'vs/editor/common/core/position'; +import { Position, IPosition } from 'vs/editor/common/core/position'; /** * A selection in the editor. @@ -129,6 +129,13 @@ export class Selection extends Range { return new Selection(endLineNumber, endColumn, this.startLineNumber, this.startColumn); } + /** + * Get the position at `positionLineNumber` and `positionColumn`. + */ + public getPosition(): Position { + return new Position(this.positionLineNumber, this.positionColumn); + } + /** * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`. */ diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 268c48f5d1188f1529e94019e6fc452f9e593d1b..bca8965eafba99755afcb713ffa776441f201880 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -23,7 +23,7 @@ import { } from 'vs/editor/common/model/textModelEvents'; import * as editorOptions from 'vs/editor/common/config/editorOptions'; import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; -import { ICursors } from 'vs/editor/common/controller/cursorCommon'; +import { ICursors, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon'; /** * Vertical Lane in the overview ruler of the editor. @@ -1918,6 +1918,11 @@ export interface ICommonCodeEditor extends IEditor { */ _getCursors(): ICursors; + /** + * @internal + */ + _getCursorConfiguration(): CursorConfiguration; + /** * Get all the decorations on a line (filtering out decorations from other editors). */ @@ -2078,7 +2083,6 @@ export var Handler = { Undo: 'undo', Redo: 'redo', - LineInsertBefore: 'lineInsertBefore', LineInsertAfter: 'lineInsertAfter', LineBreakInsert: 'lineBreakInsert', }; diff --git a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts index 59acf7fcd23795d8e3a6bafca56ddb1c13bfb8ff..0cb23b5039308c1fce98f21aa9f0f8047206da7e 100644 --- a/src/vs/editor/contrib/linesOperations/common/linesOperations.ts +++ b/src/vs/editor/contrib/linesOperations/common/linesOperations.ts @@ -18,6 +18,7 @@ import { editorAction, ServicesAccessor, IActionOptions, EditorAction, HandlerEd import { CopyLinesCommand } from './copyLinesCommand'; import { DeleteLinesCommand } from './deleteLinesCommand'; import { MoveLinesCommand } from './moveLinesCommand'; +import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; // copy lines @@ -329,20 +330,24 @@ class OutdentLinesAction extends HandlerEditorAction { } @editorAction -class InsertLineBeforeAction extends HandlerEditorAction { +export class InsertLineBeforeAction extends EditorAction { constructor() { super({ id: 'editor.action.insertLineBefore', label: nls.localize('lines.insertBefore', "Insert Line Above"), alias: 'Insert Line Above', precondition: EditorContextKeys.writable, - handlerId: Handler.LineInsertBefore, kbOpts: { kbExpr: EditorContextKeys.textFocus, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter } }); } + + public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void { + editor.pushUndoStop(); + editor.executeCommands(this.id, TypeOperations.lineInsertBefore(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections())); + } } @editorAction diff --git a/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts b/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts index 0239d6ee087a6510214c01a3ad2fa6e6668253ca..f32dd7ee82280c14a9b7d5604e7c049c754adb8a 100644 --- a/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts +++ b/src/vs/editor/contrib/linesOperations/test/common/linesOperations.test.ts @@ -6,9 +6,11 @@ import * as assert from 'assert'; import { Selection } from 'vs/editor/common/core/selection'; -import { Handler } from 'vs/editor/common/editorCommon'; +import { Position } from 'vs/editor/common/core/position'; +import { Handler, IModel } from 'vs/editor/common/editorCommon'; import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor'; -import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction, DeleteAllRightAction } from 'vs/editor/contrib/linesOperations/common/linesOperations'; +import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction, DeleteAllRightAction, InsertLineBeforeAction } from 'vs/editor/contrib/linesOperations/common/linesOperations'; +import { Cursor } from "vs/editor/common/controller/cursor"; suite('Editor Contrib - Line Operations', () => { suite('DeleteAllLeftAction', () => { @@ -488,4 +490,45 @@ suite('Editor Contrib - Line Operations', () => { }); }); }); + + test('InsertLineBeforeAction', function () { + function testInsertLineBefore(lineNumber: number, column: number, callback: (model: IModel, cursor: Cursor) => void): void { + const TEXT = [ + 'First line', + 'Second line', + 'Third line' + ]; + withMockCodeEditor(TEXT, {}, (editor, cursor) => { + editor.setPosition(new Position(lineNumber, column)); + let insertLineBeforeAction = new InsertLineBeforeAction(); + + insertLineBeforeAction.run(null, editor); + callback(editor.getModel(), cursor); + }); + } + + testInsertLineBefore(1, 3, (model, cursor) => { + assert.deepEqual(cursor.getSelection(), new Selection(1, 1, 1, 1)); + assert.equal(model.getLineContent(1), ''); + assert.equal(model.getLineContent(2), 'First line'); + assert.equal(model.getLineContent(3), 'Second line'); + assert.equal(model.getLineContent(4), 'Third line'); + }); + + testInsertLineBefore(2, 3, (model, cursor) => { + assert.deepEqual(cursor.getSelection(), new Selection(2, 1, 2, 1)); + assert.equal(model.getLineContent(1), 'First line'); + assert.equal(model.getLineContent(2), ''); + assert.equal(model.getLineContent(3), 'Second line'); + assert.equal(model.getLineContent(4), 'Third line'); + }); + + testInsertLineBefore(3, 3, (model, cursor) => { + assert.deepEqual(cursor.getSelection(), new Selection(3, 1, 3, 1)); + assert.equal(model.getLineContent(1), 'First line'); + assert.equal(model.getLineContent(2), 'Second line'); + assert.equal(model.getLineContent(3), ''); + assert.equal(model.getLineContent(4), 'Third line'); + }); + }); }); \ No newline at end of file diff --git a/src/vs/editor/test/common/controller/cursor.test.ts b/src/vs/editor/test/common/controller/cursor.test.ts index 134f327f9bf02de51fa2a07a61c4684a9efc73ae..8a505460120c2104d29a658d3197baa9d09acc79 100644 --- a/src/vs/editor/test/common/controller/cursor.test.ts +++ b/src/vs/editor/test/common/controller/cursor.test.ts @@ -1930,48 +1930,6 @@ suite('Editor Controller - Cursor Configuration', () => { mode.dispose(); }); - test('Insert line before', () => { - let testInsertLineBefore = (lineNumber: number, column: number, callback: (model: Model, cursor: Cursor) => void) => { - usingCursor({ - text: [ - 'First line', - 'Second line', - 'Third line' - ], - }, (model, cursor) => { - moveTo(cursor, lineNumber, column, false); - assertCursor(cursor, new Position(lineNumber, column)); - - cursorCommand(cursor, H.LineInsertBefore, null, 'keyboard'); - callback(model, cursor); - }); - }; - - testInsertLineBefore(1, 3, (model, cursor) => { - assertCursor(cursor, new Selection(1, 1, 1, 1)); - assert.equal(model.getLineContent(1), ''); - assert.equal(model.getLineContent(2), 'First line'); - assert.equal(model.getLineContent(3), 'Second line'); - assert.equal(model.getLineContent(4), 'Third line'); - }); - - testInsertLineBefore(2, 3, (model, cursor) => { - assertCursor(cursor, new Selection(2, 1, 2, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), ''); - assert.equal(model.getLineContent(3), 'Second line'); - assert.equal(model.getLineContent(4), 'Third line'); - }); - - testInsertLineBefore(3, 3, (model, cursor) => { - assertCursor(cursor, new Selection(3, 1, 3, 1)); - assert.equal(model.getLineContent(1), 'First line'); - assert.equal(model.getLineContent(2), 'Second line'); - assert.equal(model.getLineContent(3), ''); - assert.equal(model.getLineContent(4), 'Third line'); - }); - }); - test('Insert line after', () => { let testInsertLineAfter = (lineNumber: number, column: number, callback: (model: Model, cursor: Cursor) => void) => { usingCursor({ diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 334b54b64b1d3711a8c2dde09c4602f5835ae130..e12595a783f863403d206be0da7acce842b62467 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -724,6 +724,10 @@ declare module monaco { * Create a new selection with a different `positionLineNumber` and `positionColumn`. */ setEndPosition(endLineNumber: number, endColumn: number): Selection; + /** + * Get the position at `positionLineNumber` and `positionColumn`. + */ + getPosition(): Position; /** * Create a new selection with a different `selectionStartLineNumber` and `selectionStartColumn`. */