UNPKG

monaco-editor-core

Version:

A browser based code editor

1,137 lines • 75.3 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as nls from '../../nls.js'; import { isFirefox } from '../../base/browser/browser.js'; import * as types from '../../base/common/types.js'; import { status } from '../../base/browser/ui/aria/aria.js'; import { Command, EditorCommand, registerEditorCommand, UndoCommand, RedoCommand, SelectAllCommand } from './editorExtensions.js'; import { ICodeEditorService } from './services/codeEditorService.js'; import { ColumnSelection } from '../common/cursor/cursorColumnSelection.js'; import { CursorState } from '../common/cursorCommon.js'; import { DeleteOperations } from '../common/cursor/cursorDeleteOperations.js'; import { CursorMove as CursorMove_, CursorMoveCommands } from '../common/cursor/cursorMoveCommands.js'; import { TypeOperations } from '../common/cursor/cursorTypeOperations.js'; import { Position } from '../common/core/position.js'; import { Range } from '../common/core/range.js'; import { EditorContextKeys } from '../common/editorContextKeys.js'; import { ContextKeyExpr } from '../../platform/contextkey/common/contextkey.js'; import { KeybindingsRegistry } from '../../platform/keybinding/common/keybindingsRegistry.js'; import { getActiveElement } from '../../base/browser/dom.js'; import { EnterOperation } from '../common/cursor/cursorTypeEditOperations.js'; const CORE_WEIGHT = 0 /* KeybindingWeight.EditorCore */; export class CoreEditorCommand extends EditorCommand { runEditorCommand(accessor, editor, args) { const viewModel = editor._getViewModel(); if (!viewModel) { // the editor has no view => has no cursors return; } this.runCoreEditorCommand(viewModel, args || {}); } } export var EditorScroll_; (function (EditorScroll_) { const isEditorScrollArgs = function (arg) { if (!types.isObject(arg)) { return false; } const scrollArg = arg; if (!types.isString(scrollArg.to)) { return false; } if (!types.isUndefined(scrollArg.by) && !types.isString(scrollArg.by)) { return false; } if (!types.isUndefined(scrollArg.value) && !types.isNumber(scrollArg.value)) { return false; } if (!types.isUndefined(scrollArg.revealCursor) && !types.isBoolean(scrollArg.revealCursor)) { return false; } return true; }; EditorScroll_.metadata = { description: 'Scroll editor in the given direction', args: [ { name: 'Editor scroll argument object', description: `Property-value pairs that can be passed through this argument: * 'to': A mandatory direction value. \`\`\` 'up', 'down' \`\`\` * 'by': Unit to move. Default is computed based on 'to' value. \`\`\` 'line', 'wrappedLine', 'page', 'halfPage', 'editor' \`\`\` * 'value': Number of units to move. Default is '1'. * 'revealCursor': If 'true' reveals the cursor if it is outside view port. `, constraint: isEditorScrollArgs, schema: { 'type': 'object', 'required': ['to'], 'properties': { 'to': { 'type': 'string', 'enum': ['up', 'down'] }, 'by': { 'type': 'string', 'enum': ['line', 'wrappedLine', 'page', 'halfPage', 'editor'] }, 'value': { 'type': 'number', 'default': 1 }, 'revealCursor': { 'type': 'boolean', } } } } ] }; /** * Directions in the view for editor scroll command. */ EditorScroll_.RawDirection = { Up: 'up', Right: 'right', Down: 'down', Left: 'left' }; /** * Units for editor scroll 'by' argument */ EditorScroll_.RawUnit = { Line: 'line', WrappedLine: 'wrappedLine', Page: 'page', HalfPage: 'halfPage', Editor: 'editor', Column: 'column' }; function parse(args) { let direction; switch (args.to) { case EditorScroll_.RawDirection.Up: direction = 1 /* Direction.Up */; break; case EditorScroll_.RawDirection.Right: direction = 2 /* Direction.Right */; break; case EditorScroll_.RawDirection.Down: direction = 3 /* Direction.Down */; break; case EditorScroll_.RawDirection.Left: direction = 4 /* Direction.Left */; break; default: // Illegal arguments return null; } let unit; switch (args.by) { case EditorScroll_.RawUnit.Line: unit = 1 /* Unit.Line */; break; case EditorScroll_.RawUnit.WrappedLine: unit = 2 /* Unit.WrappedLine */; break; case EditorScroll_.RawUnit.Page: unit = 3 /* Unit.Page */; break; case EditorScroll_.RawUnit.HalfPage: unit = 4 /* Unit.HalfPage */; break; case EditorScroll_.RawUnit.Editor: unit = 5 /* Unit.Editor */; break; case EditorScroll_.RawUnit.Column: unit = 6 /* Unit.Column */; break; default: unit = 2 /* Unit.WrappedLine */; } const value = Math.floor(args.value || 1); const revealCursor = !!args.revealCursor; return { direction: direction, unit: unit, value: value, revealCursor: revealCursor, select: (!!args.select) }; } EditorScroll_.parse = parse; })(EditorScroll_ || (EditorScroll_ = {})); export var RevealLine_; (function (RevealLine_) { const isRevealLineArgs = function (arg) { if (!types.isObject(arg)) { return false; } const reveaLineArg = arg; if (!types.isNumber(reveaLineArg.lineNumber) && !types.isString(reveaLineArg.lineNumber)) { return false; } if (!types.isUndefined(reveaLineArg.at) && !types.isString(reveaLineArg.at)) { return false; } return true; }; RevealLine_.metadata = { description: 'Reveal the given line at the given logical position', args: [ { name: 'Reveal line argument object', description: `Property-value pairs that can be passed through this argument: * 'lineNumber': A mandatory line number value. * 'at': Logical position at which line has to be revealed. \`\`\` 'top', 'center', 'bottom' \`\`\` `, constraint: isRevealLineArgs, schema: { 'type': 'object', 'required': ['lineNumber'], 'properties': { 'lineNumber': { 'type': ['number', 'string'], }, 'at': { 'type': 'string', 'enum': ['top', 'center', 'bottom'] } } } } ] }; /** * Values for reveal line 'at' argument */ RevealLine_.RawAtArgument = { Top: 'top', Center: 'center', Bottom: 'bottom' }; })(RevealLine_ || (RevealLine_ = {})); class EditorOrNativeTextInputCommand { constructor(target) { // 1. handle case when focus is in editor. target.addImplementation(10000, 'code-editor', (accessor, args) => { // Only if editor text focus (i.e. not if editor has widget focus). const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor(); if (focusedEditor && focusedEditor.hasTextFocus()) { return this._runEditorCommand(accessor, focusedEditor, args); } return false; }); // 2. handle case when focus is in some other `input` / `textarea`. target.addImplementation(1000, 'generic-dom-input-textarea', (accessor, args) => { // Only if focused on an element that allows for entering text const activeElement = getActiveElement(); if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) { this.runDOMCommand(activeElement); return true; } return false; }); // 3. (default) handle case when focus is somewhere else. target.addImplementation(0, 'generic-dom', (accessor, args) => { // Redirecting to active editor const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor(); if (activeEditor) { activeEditor.focus(); return this._runEditorCommand(accessor, activeEditor, args); } return false; }); } _runEditorCommand(accessor, editor, args) { const result = this.runEditorCommand(accessor, editor, args); if (result) { return result; } return true; } } export var CoreNavigationCommands; (function (CoreNavigationCommands) { class BaseMoveToCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { if (!args.position) { return; } viewModel.model.pushStackElement(); const cursorStateChanged = viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, [ CursorMoveCommands.moveTo(viewModel, viewModel.getPrimaryCursorState(), this._inSelectionMode, args.position, args.viewPosition) ]); if (cursorStateChanged && args.revealType !== 2 /* NavigationCommandRevealType.None */) { viewModel.revealAllCursors(args.source, true, true); } } } CoreNavigationCommands.MoveTo = registerEditorCommand(new BaseMoveToCommand({ id: '_moveTo', inSelectionMode: false, precondition: undefined })); CoreNavigationCommands.MoveToSelect = registerEditorCommand(new BaseMoveToCommand({ id: '_moveToSelect', inSelectionMode: true, precondition: undefined })); class ColumnSelectCommand extends CoreEditorCommand { runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); const result = this._getColumnSelectResult(viewModel, viewModel.getPrimaryCursorState(), viewModel.getCursorColumnSelectData(), args); if (result === null) { // invalid arguments return; } viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, result.viewStates.map((viewState) => CursorState.fromViewState(viewState))); viewModel.setCursorColumnSelectData({ isReal: true, fromViewLineNumber: result.fromLineNumber, fromViewVisualColumn: result.fromVisualColumn, toViewLineNumber: result.toLineNumber, toViewVisualColumn: result.toVisualColumn }); if (result.reversed) { viewModel.revealTopMostCursor(args.source); } else { viewModel.revealBottomMostCursor(args.source); } } } CoreNavigationCommands.ColumnSelect = registerEditorCommand(new class extends ColumnSelectCommand { constructor() { super({ id: 'columnSelect', precondition: undefined }); } _getColumnSelectResult(viewModel, primary, prevColumnSelectData, args) { if (typeof args.position === 'undefined' || typeof args.viewPosition === 'undefined' || typeof args.mouseColumn === 'undefined') { return null; } // validate `args` const validatedPosition = viewModel.model.validatePosition(args.position); const validatedViewPosition = viewModel.coordinatesConverter.validateViewPosition(new Position(args.viewPosition.lineNumber, args.viewPosition.column), validatedPosition); const fromViewLineNumber = args.doColumnSelect ? prevColumnSelectData.fromViewLineNumber : validatedViewPosition.lineNumber; const fromViewVisualColumn = args.doColumnSelect ? prevColumnSelectData.fromViewVisualColumn : args.mouseColumn - 1; return ColumnSelection.columnSelect(viewModel.cursorConfig, viewModel, fromViewLineNumber, fromViewVisualColumn, validatedViewPosition.lineNumber, args.mouseColumn - 1); } }); CoreNavigationCommands.CursorColumnSelectLeft = registerEditorCommand(new class extends ColumnSelectCommand { constructor() { super({ id: 'cursorColumnSelectLeft', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 15 /* KeyCode.LeftArrow */, linux: { primary: 0 } } }); } _getColumnSelectResult(viewModel, primary, prevColumnSelectData, args) { return ColumnSelection.columnSelectLeft(viewModel.cursorConfig, viewModel, prevColumnSelectData); } }); CoreNavigationCommands.CursorColumnSelectRight = registerEditorCommand(new class extends ColumnSelectCommand { constructor() { super({ id: 'cursorColumnSelectRight', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 17 /* KeyCode.RightArrow */, linux: { primary: 0 } } }); } _getColumnSelectResult(viewModel, primary, prevColumnSelectData, args) { return ColumnSelection.columnSelectRight(viewModel.cursorConfig, viewModel, prevColumnSelectData); } }); class ColumnSelectUpCommand extends ColumnSelectCommand { constructor(opts) { super(opts); this._isPaged = opts.isPaged; } _getColumnSelectResult(viewModel, primary, prevColumnSelectData, args) { return ColumnSelection.columnSelectUp(viewModel.cursorConfig, viewModel, prevColumnSelectData, this._isPaged); } } CoreNavigationCommands.CursorColumnSelectUp = registerEditorCommand(new ColumnSelectUpCommand({ isPaged: false, id: 'cursorColumnSelectUp', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 16 /* KeyCode.UpArrow */, linux: { primary: 0 } } })); CoreNavigationCommands.CursorColumnSelectPageUp = registerEditorCommand(new ColumnSelectUpCommand({ isPaged: true, id: 'cursorColumnSelectPageUp', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 11 /* KeyCode.PageUp */, linux: { primary: 0 } } })); class ColumnSelectDownCommand extends ColumnSelectCommand { constructor(opts) { super(opts); this._isPaged = opts.isPaged; } _getColumnSelectResult(viewModel, primary, prevColumnSelectData, args) { return ColumnSelection.columnSelectDown(viewModel.cursorConfig, viewModel, prevColumnSelectData, this._isPaged); } } CoreNavigationCommands.CursorColumnSelectDown = registerEditorCommand(new ColumnSelectDownCommand({ isPaged: false, id: 'cursorColumnSelectDown', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 18 /* KeyCode.DownArrow */, linux: { primary: 0 } } })); CoreNavigationCommands.CursorColumnSelectPageDown = registerEditorCommand(new ColumnSelectDownCommand({ isPaged: true, id: 'cursorColumnSelectPageDown', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 512 /* KeyMod.Alt */ | 12 /* KeyCode.PageDown */, linux: { primary: 0 } } })); class CursorMoveImpl extends CoreEditorCommand { constructor() { super({ id: 'cursorMove', precondition: undefined, metadata: CursorMove_.metadata }); } runCoreEditorCommand(viewModel, args) { const parsed = CursorMove_.parse(args); if (!parsed) { // illegal arguments return; } this._runCursorMove(viewModel, args.source, parsed); } _runCursorMove(viewModel, source, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(source, 3 /* CursorChangeReason.Explicit */, CursorMoveImpl._move(viewModel, viewModel.getCursorStates(), args)); viewModel.revealAllCursors(source, true); } static _move(viewModel, cursors, args) { const inSelectionMode = args.select; const value = args.value; switch (args.direction) { case 0 /* CursorMove_.Direction.Left */: case 1 /* CursorMove_.Direction.Right */: case 2 /* CursorMove_.Direction.Up */: case 3 /* CursorMove_.Direction.Down */: case 4 /* CursorMove_.Direction.PrevBlankLine */: case 5 /* CursorMove_.Direction.NextBlankLine */: case 6 /* CursorMove_.Direction.WrappedLineStart */: case 7 /* CursorMove_.Direction.WrappedLineFirstNonWhitespaceCharacter */: case 8 /* CursorMove_.Direction.WrappedLineColumnCenter */: case 9 /* CursorMove_.Direction.WrappedLineEnd */: case 10 /* CursorMove_.Direction.WrappedLineLastNonWhitespaceCharacter */: return CursorMoveCommands.simpleMove(viewModel, cursors, args.direction, inSelectionMode, value, args.unit); case 11 /* CursorMove_.Direction.ViewPortTop */: case 13 /* CursorMove_.Direction.ViewPortBottom */: case 12 /* CursorMove_.Direction.ViewPortCenter */: case 14 /* CursorMove_.Direction.ViewPortIfOutside */: return CursorMoveCommands.viewportMove(viewModel, cursors, args.direction, inSelectionMode, value); default: return null; } } } CoreNavigationCommands.CursorMoveImpl = CursorMoveImpl; CoreNavigationCommands.CursorMove = registerEditorCommand(new CursorMoveImpl()); class CursorMoveBasedCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._staticArgs = opts.args; } runCoreEditorCommand(viewModel, dynamicArgs) { let args = this._staticArgs; if (this._staticArgs.value === -1 /* Constants.PAGE_SIZE_MARKER */) { // -1 is a marker for page size args = { direction: this._staticArgs.direction, unit: this._staticArgs.unit, select: this._staticArgs.select, value: dynamicArgs.pageSize || viewModel.cursorConfig.pageSize }; } viewModel.model.pushStackElement(); viewModel.setCursorStates(dynamicArgs.source, 3 /* CursorChangeReason.Explicit */, CursorMoveCommands.simpleMove(viewModel, viewModel.getCursorStates(), args.direction, args.select, args.value, args.unit)); viewModel.revealAllCursors(dynamicArgs.source, true); } } CoreNavigationCommands.CursorLeft = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 0 /* CursorMove_.Direction.Left */, unit: 0 /* CursorMove_.Unit.None */, select: false, value: 1 }, id: 'cursorLeft', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 15 /* KeyCode.LeftArrow */, mac: { primary: 15 /* KeyCode.LeftArrow */, secondary: [256 /* KeyMod.WinCtrl */ | 32 /* KeyCode.KeyB */] } } })); CoreNavigationCommands.CursorLeftSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 0 /* CursorMove_.Direction.Left */, unit: 0 /* CursorMove_.Unit.None */, select: true, value: 1 }, id: 'cursorLeftSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 15 /* KeyCode.LeftArrow */ } })); CoreNavigationCommands.CursorRight = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 1 /* CursorMove_.Direction.Right */, unit: 0 /* CursorMove_.Unit.None */, select: false, value: 1 }, id: 'cursorRight', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 17 /* KeyCode.RightArrow */, mac: { primary: 17 /* KeyCode.RightArrow */, secondary: [256 /* KeyMod.WinCtrl */ | 36 /* KeyCode.KeyF */] } } })); CoreNavigationCommands.CursorRightSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 1 /* CursorMove_.Direction.Right */, unit: 0 /* CursorMove_.Unit.None */, select: true, value: 1 }, id: 'cursorRightSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 17 /* KeyCode.RightArrow */ } })); CoreNavigationCommands.CursorUp = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 2 /* CursorMove_.Direction.Up */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: false, value: 1 }, id: 'cursorUp', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 16 /* KeyCode.UpArrow */, mac: { primary: 16 /* KeyCode.UpArrow */, secondary: [256 /* KeyMod.WinCtrl */ | 46 /* KeyCode.KeyP */] } } })); CoreNavigationCommands.CursorUpSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 2 /* CursorMove_.Direction.Up */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: true, value: 1 }, id: 'cursorUpSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 16 /* KeyCode.UpArrow */, secondary: [2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 16 /* KeyCode.UpArrow */], mac: { primary: 1024 /* KeyMod.Shift */ | 16 /* KeyCode.UpArrow */ }, linux: { primary: 1024 /* KeyMod.Shift */ | 16 /* KeyCode.UpArrow */ } } })); CoreNavigationCommands.CursorPageUp = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 2 /* CursorMove_.Direction.Up */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: false, value: -1 /* Constants.PAGE_SIZE_MARKER */ }, id: 'cursorPageUp', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 11 /* KeyCode.PageUp */ } })); CoreNavigationCommands.CursorPageUpSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 2 /* CursorMove_.Direction.Up */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: true, value: -1 /* Constants.PAGE_SIZE_MARKER */ }, id: 'cursorPageUpSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 11 /* KeyCode.PageUp */ } })); CoreNavigationCommands.CursorDown = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 3 /* CursorMove_.Direction.Down */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: false, value: 1 }, id: 'cursorDown', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 18 /* KeyCode.DownArrow */, mac: { primary: 18 /* KeyCode.DownArrow */, secondary: [256 /* KeyMod.WinCtrl */ | 44 /* KeyCode.KeyN */] } } })); CoreNavigationCommands.CursorDownSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 3 /* CursorMove_.Direction.Down */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: true, value: 1 }, id: 'cursorDownSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 18 /* KeyCode.DownArrow */, secondary: [2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 18 /* KeyCode.DownArrow */], mac: { primary: 1024 /* KeyMod.Shift */ | 18 /* KeyCode.DownArrow */ }, linux: { primary: 1024 /* KeyMod.Shift */ | 18 /* KeyCode.DownArrow */ } } })); CoreNavigationCommands.CursorPageDown = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 3 /* CursorMove_.Direction.Down */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: false, value: -1 /* Constants.PAGE_SIZE_MARKER */ }, id: 'cursorPageDown', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 12 /* KeyCode.PageDown */ } })); CoreNavigationCommands.CursorPageDownSelect = registerEditorCommand(new CursorMoveBasedCommand({ args: { direction: 3 /* CursorMove_.Direction.Down */, unit: 2 /* CursorMove_.Unit.WrappedLine */, select: true, value: -1 /* Constants.PAGE_SIZE_MARKER */ }, id: 'cursorPageDownSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 12 /* KeyCode.PageDown */ } })); CoreNavigationCommands.CreateCursor = registerEditorCommand(new class extends CoreEditorCommand { constructor() { super({ id: 'createCursor', precondition: undefined }); } runCoreEditorCommand(viewModel, args) { if (!args.position) { return; } let newState; if (args.wholeLine) { newState = CursorMoveCommands.line(viewModel, viewModel.getPrimaryCursorState(), false, args.position, args.viewPosition); } else { newState = CursorMoveCommands.moveTo(viewModel, viewModel.getPrimaryCursorState(), false, args.position, args.viewPosition); } const states = viewModel.getCursorStates(); // Check if we should remove a cursor (sort of like a toggle) if (states.length > 1) { const newModelPosition = (newState.modelState ? newState.modelState.position : null); const newViewPosition = (newState.viewState ? newState.viewState.position : null); for (let i = 0, len = states.length; i < len; i++) { const state = states[i]; if (newModelPosition && !state.modelState.selection.containsPosition(newModelPosition)) { continue; } if (newViewPosition && !state.viewState.selection.containsPosition(newViewPosition)) { continue; } // => Remove the cursor states.splice(i, 1); viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, states); return; } } // => Add the new cursor states.push(newState); viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, states); } }); CoreNavigationCommands.LastCursorMoveToSelect = registerEditorCommand(new class extends CoreEditorCommand { constructor() { super({ id: '_lastCursorMoveToSelect', precondition: undefined }); } runCoreEditorCommand(viewModel, args) { if (!args.position) { return; } const lastAddedCursorIndex = viewModel.getLastAddedCursorIndex(); const states = viewModel.getCursorStates(); const newStates = states.slice(0); newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(viewModel, states[lastAddedCursorIndex], true, args.position, args.viewPosition); viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, newStates); } }); class HomeCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, CursorMoveCommands.moveToBeginningOfLine(viewModel, viewModel.getCursorStates(), this._inSelectionMode)); viewModel.revealAllCursors(args.source, true); } } CoreNavigationCommands.CursorHome = registerEditorCommand(new HomeCommand({ inSelectionMode: false, id: 'cursorHome', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 14 /* KeyCode.Home */, mac: { primary: 14 /* KeyCode.Home */, secondary: [2048 /* KeyMod.CtrlCmd */ | 15 /* KeyCode.LeftArrow */] } } })); CoreNavigationCommands.CursorHomeSelect = registerEditorCommand(new HomeCommand({ inSelectionMode: true, id: 'cursorHomeSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 14 /* KeyCode.Home */, mac: { primary: 1024 /* KeyMod.Shift */ | 14 /* KeyCode.Home */, secondary: [2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 15 /* KeyCode.LeftArrow */] } } })); class LineStartCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, this._exec(viewModel.getCursorStates())); viewModel.revealAllCursors(args.source, true); } _exec(cursors) { const result = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; result[i] = CursorState.fromModelState(cursor.modelState.move(this._inSelectionMode, lineNumber, 1, 0)); } return result; } } CoreNavigationCommands.CursorLineStart = registerEditorCommand(new LineStartCommand({ inSelectionMode: false, id: 'cursorLineStart', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: 256 /* KeyMod.WinCtrl */ | 31 /* KeyCode.KeyA */ } } })); CoreNavigationCommands.CursorLineStartSelect = registerEditorCommand(new LineStartCommand({ inSelectionMode: true, id: 'cursorLineStartSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: 256 /* KeyMod.WinCtrl */ | 1024 /* KeyMod.Shift */ | 31 /* KeyCode.KeyA */ } } })); class EndCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, CursorMoveCommands.moveToEndOfLine(viewModel, viewModel.getCursorStates(), this._inSelectionMode, args.sticky || false)); viewModel.revealAllCursors(args.source, true); } } CoreNavigationCommands.CursorEnd = registerEditorCommand(new EndCommand({ inSelectionMode: false, id: 'cursorEnd', precondition: undefined, kbOpts: { args: { sticky: false }, weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 13 /* KeyCode.End */, mac: { primary: 13 /* KeyCode.End */, secondary: [2048 /* KeyMod.CtrlCmd */ | 17 /* KeyCode.RightArrow */] } }, metadata: { description: `Go to End`, args: [{ name: 'args', schema: { type: 'object', properties: { 'sticky': { description: nls.localize('stickydesc', "Stick to the end even when going to longer lines"), type: 'boolean', default: false } } } }] } })); CoreNavigationCommands.CursorEndSelect = registerEditorCommand(new EndCommand({ inSelectionMode: true, id: 'cursorEndSelect', precondition: undefined, kbOpts: { args: { sticky: false }, weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 1024 /* KeyMod.Shift */ | 13 /* KeyCode.End */, mac: { primary: 1024 /* KeyMod.Shift */ | 13 /* KeyCode.End */, secondary: [2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 17 /* KeyCode.RightArrow */] } }, metadata: { description: `Select to End`, args: [{ name: 'args', schema: { type: 'object', properties: { 'sticky': { description: nls.localize('stickydesc', "Stick to the end even when going to longer lines"), type: 'boolean', default: false } } } }] } })); class LineEndCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, this._exec(viewModel, viewModel.getCursorStates())); viewModel.revealAllCursors(args.source, true); } _exec(viewModel, cursors) { const result = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; const maxColumn = viewModel.model.getLineMaxColumn(lineNumber); result[i] = CursorState.fromModelState(cursor.modelState.move(this._inSelectionMode, lineNumber, maxColumn, 0)); } return result; } } CoreNavigationCommands.CursorLineEnd = registerEditorCommand(new LineEndCommand({ inSelectionMode: false, id: 'cursorLineEnd', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: 256 /* KeyMod.WinCtrl */ | 35 /* KeyCode.KeyE */ } } })); CoreNavigationCommands.CursorLineEndSelect = registerEditorCommand(new LineEndCommand({ inSelectionMode: true, id: 'cursorLineEndSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 0, mac: { primary: 256 /* KeyMod.WinCtrl */ | 1024 /* KeyMod.Shift */ | 35 /* KeyCode.KeyE */ } } })); class TopCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, CursorMoveCommands.moveToBeginningOfBuffer(viewModel, viewModel.getCursorStates(), this._inSelectionMode)); viewModel.revealAllCursors(args.source, true); } } CoreNavigationCommands.CursorTop = registerEditorCommand(new TopCommand({ inSelectionMode: false, id: 'cursorTop', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 14 /* KeyCode.Home */, mac: { primary: 2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */ } } })); CoreNavigationCommands.CursorTopSelect = registerEditorCommand(new TopCommand({ inSelectionMode: true, id: 'cursorTopSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 14 /* KeyCode.Home */, mac: { primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 16 /* KeyCode.UpArrow */ } } })); class BottomCommand extends CoreEditorCommand { constructor(opts) { super(opts); this._inSelectionMode = opts.inSelectionMode; } runCoreEditorCommand(viewModel, args) { viewModel.model.pushStackElement(); viewModel.setCursorStates(args.source, 3 /* CursorChangeReason.Explicit */, CursorMoveCommands.moveToEndOfBuffer(viewModel, viewModel.getCursorStates(), this._inSelectionMode)); viewModel.revealAllCursors(args.source, true); } } CoreNavigationCommands.CursorBottom = registerEditorCommand(new BottomCommand({ inSelectionMode: false, id: 'cursorBottom', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 13 /* KeyCode.End */, mac: { primary: 2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */ } } })); CoreNavigationCommands.CursorBottomSelect = registerEditorCommand(new BottomCommand({ inSelectionMode: true, id: 'cursorBottomSelect', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 13 /* KeyCode.End */, mac: { primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 18 /* KeyCode.DownArrow */ } } })); class EditorScrollImpl extends CoreEditorCommand { constructor() { super({ id: 'editorScroll', precondition: undefined, metadata: EditorScroll_.metadata }); } determineScrollMethod(args) { const horizontalUnits = [6 /* EditorScroll_.Unit.Column */]; const verticalUnits = [ 1 /* EditorScroll_.Unit.Line */, 2 /* EditorScroll_.Unit.WrappedLine */, 3 /* EditorScroll_.Unit.Page */, 4 /* EditorScroll_.Unit.HalfPage */, 5 /* EditorScroll_.Unit.Editor */, 6 /* EditorScroll_.Unit.Column */ ]; const horizontalDirections = [4 /* EditorScroll_.Direction.Left */, 2 /* EditorScroll_.Direction.Right */]; const verticalDirections = [1 /* EditorScroll_.Direction.Up */, 3 /* EditorScroll_.Direction.Down */]; if (horizontalUnits.includes(args.unit) && horizontalDirections.includes(args.direction)) { return this._runHorizontalEditorScroll.bind(this); } if (verticalUnits.includes(args.unit) && verticalDirections.includes(args.direction)) { return this._runVerticalEditorScroll.bind(this); } return null; } runCoreEditorCommand(viewModel, args) { const parsed = EditorScroll_.parse(args); if (!parsed) { // illegal arguments return; } const runEditorScroll = this.determineScrollMethod(parsed); if (!runEditorScroll) { // Incompatible unit and direction return; } runEditorScroll(viewModel, args.source, parsed); } _runVerticalEditorScroll(viewModel, source, args) { const desiredScrollTop = this._computeDesiredScrollTop(viewModel, args); if (args.revealCursor) { // must ensure cursor is in new visible range const desiredVisibleViewRange = viewModel.getCompletelyVisibleViewRangeAtScrollTop(desiredScrollTop); viewModel.setCursorStates(source, 3 /* CursorChangeReason.Explicit */, [ CursorMoveCommands.findPositionInViewportIfOutside(viewModel, viewModel.getPrimaryCursorState(), desiredVisibleViewRange, args.select) ]); } viewModel.viewLayout.setScrollPosition({ scrollTop: desiredScrollTop }, 0 /* ScrollType.Smooth */); } _computeDesiredScrollTop(viewModel, args) { if (args.unit === 1 /* EditorScroll_.Unit.Line */) { // scrolling by model lines const futureViewport = viewModel.viewLayout.getFutureViewport(); const visibleViewRange = viewModel.getCompletelyVisibleViewRangeAtScrollTop(futureViewport.top); const visibleModelRange = viewModel.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange); let desiredTopModelLineNumber; if (args.direction === 1 /* EditorScroll_.Direction.Up */) { // must go x model lines up desiredTopModelLineNumber = Math.max(1, visibleModelRange.startLineNumber - args.value); } else { // must go x model lines down desiredTopModelLineNumber = Math.min(viewModel.model.getLineCount(), visibleModelRange.startLineNumber + args.value); } const viewPosition = viewModel.coordinatesConverter.convertModelPositionToViewPosition(new Position(desiredTopModelLineNumber, 1)); return viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); } if (args.unit === 5 /* EditorScroll_.Unit.Editor */) { let desiredTopModelLineNumber = 0; if (args.direction === 3 /* EditorScroll_.Direction.Down */) { desiredTopModelLineNumber = viewModel.model.getLineCount() - viewModel.cursorConfig.pageSize; } return viewModel.viewLayout.getVerticalOffsetForLineNumber(desiredTopModelLineNumber); } let noOfLines; if (args.unit === 3 /* EditorScroll_.Unit.Page */) { noOfLines = viewModel.cursorConfig.pageSize * args.value; } else if (args.unit === 4 /* EditorScroll_.Unit.HalfPage */) { noOfLines = Math.round(viewModel.cursorConfig.pageSize / 2) * args.value; } else { noOfLines = args.value; } const deltaLines = (args.direction === 1 /* EditorScroll_.Direction.Up */ ? -1 : 1) * noOfLines; return viewModel.viewLayout.getCurrentScrollTop() + deltaLines * viewModel.cursorConfig.lineHeight; } _runHorizontalEditorScroll(viewModel, source, args) { const desiredScrollLeft = this._computeDesiredScrollLeft(viewModel, args); viewModel.viewLayout.setScrollPosition({ scrollLeft: desiredScrollLeft }, 0 /* ScrollType.Smooth */); } _computeDesiredScrollLeft(viewModel, args) { const deltaColumns = (args.direction === 4 /* EditorScroll_.Direction.Left */ ? -1 : 1) * args.value; return viewModel.viewLayout.getCurrentScrollLeft() + deltaColumns * viewModel.cursorConfig.typicalHalfwidthCharacterWidth; } } CoreNavigationCommands.EditorScrollImpl = EditorScrollImpl; CoreNavigationCommands.EditorScroll = registerEditorCommand(new EditorScrollImpl()); CoreNavigationCommands.ScrollLineUp = registerEditorCommand(new class extends CoreEditorCommand { constructor() { super({ id: 'scrollLineUp', precondition: undefined, kbOpts: { weight: CORE_WEIGHT, kbExpr: EditorContextKeys.textInputFocus, primary: 2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */, mac: { primary: 256 /* KeyMod.WinCtrl */ | 11 /* KeyCode.PageUp */ } } }); } runCoreEditorCommand(viewModel, args) { CoreNavigationCommands.EditorScroll.runCoreEditorCommand(viewModel, { to: EditorScroll_.RawDirection.Up, by: EditorScroll_.RawUnit.WrappedLine, value: 1, revealCursor: false, select: false, source: args.source }); } }); CoreNavigationCommands.ScrollPageUp = registerEditorCommand(new class extends CoreEditorCommand { constructor() { super({ id: 'scrollPageUp', precondition: undefined, kbOp