提交 6ef00179 编写于 作者: A Alex Dima

More more core commands out

上级 2f76f540
......@@ -202,28 +202,28 @@ export class ViewController {
private wordSelect(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.WordSelect, {
this.triggerCursorHandler(source, CoreCommands.WordSelect.id, {
position: this.convertViewToModelPosition(viewPosition)
});
}
private wordSelectDrag(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.WordSelectDrag, {
this.triggerCursorHandler(source, CoreCommands.WordSelectDrag.id, {
position: this.convertViewToModelPosition(viewPosition)
});
}
private lastCursorWordSelect(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.LastCursorWordSelect, {
this.triggerCursorHandler(source, CoreCommands.LastCursorWordSelect.id, {
position: this.convertViewToModelPosition(viewPosition)
});
}
private lineSelect(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.LineSelect, {
this.triggerCursorHandler(source, CoreCommands.LineSelect.id, {
position: this.convertViewToModelPosition(viewPosition),
viewPosition: viewPosition
});
......@@ -231,7 +231,7 @@ export class ViewController {
private lineSelectDrag(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.LineSelectDrag, {
this.triggerCursorHandler(source, CoreCommands.LineSelectDrag.id, {
position: this.convertViewToModelPosition(viewPosition),
viewPosition: viewPosition
});
......@@ -239,7 +239,7 @@ export class ViewController {
private lastCursorLineSelect(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.LastCursorLineSelect, {
this.triggerCursorHandler(source, CoreCommands.LastCursorLineSelect.id, {
position: this.convertViewToModelPosition(viewPosition),
viewPosition: viewPosition
});
......@@ -247,7 +247,7 @@ export class ViewController {
private lastCursorLineSelectDrag(source: string, viewPosition: Position): void {
viewPosition = this._validateViewColumn(viewPosition);
this.triggerCursorHandler(source, editorCommon.Handler.LastCursorLineSelectDrag, {
this.triggerCursorHandler(source, CoreCommands.LastCursorLineSelectDrag.id, {
position: this.convertViewToModelPosition(viewPosition),
viewPosition: viewPosition
});
......
......@@ -19,146 +19,6 @@ import H = editorCommon.Handler;
const CORE_WEIGHT = KeybindingsRegistry.WEIGHT.editorCore();
export namespace EditorScroll {
const isEditorScrollArgs = function (arg): boolean {
if (!types.isObject(arg)) {
return false;
}
let scrollArg: RawArguments = 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;
};
export const description = <ICommandHandlerDescription>{
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'
\`\`\`
* 'value': Number of units to move. Default is '1'.
* 'revealCursor': If 'true' reveals the cursor if it is outside view port.
`,
constraint: isEditorScrollArgs
}
]
};
/**
* Directions in the view for editor scroll command.
*/
export const RawDirection = {
Up: 'up',
Down: 'down',
};
/**
* Units for editor scroll 'by' argument
*/
export const RawUnit = {
Line: 'line',
WrappedLine: 'wrappedLine',
Page: 'page',
HalfPage: 'halfPage'
};
/**
* Arguments for editor scroll command
*/
export interface RawArguments {
to: string;
by?: string;
value?: number;
revealCursor?: boolean;
};
export function parse(args: RawArguments): ParsedArguments {
let direction: Direction;
switch (args.to) {
case RawDirection.Up:
direction = Direction.Up;
break;
case RawDirection.Down:
direction = Direction.Down;
break;
default:
// Illegal arguments
return null;
}
let unit: Unit;
switch (args.by) {
case RawUnit.Line:
unit = Unit.Line;
break;
case RawUnit.WrappedLine:
unit = Unit.WrappedLine;
break;
case RawUnit.Page:
unit = Unit.Page;
break;
case RawUnit.HalfPage:
unit = Unit.HalfPage;
break;
default:
unit = Unit.WrappedLine;
}
const value = Math.floor(args.value || 1);
const revealCursor = !!args.revealCursor;
return {
direction: direction,
unit: unit,
value: value,
revealCursor: revealCursor
};
}
export interface ParsedArguments {
direction: Direction;
unit: Unit;
value: number;
revealCursor: boolean;
}
export const enum Direction {
Up = 1,
Down = 2
}
export const enum Unit {
Line = 1,
WrappedLine = 2,
Page = 3,
HalfPage = 4
}
}
export namespace RevealLine {
......@@ -254,10 +114,12 @@ export abstract class Command {
}
}
const weight = (typeof kbOpts.weight === 'number' ? kbOpts.weight : defaultWeight);
return {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: kbOpts.weight || defaultWeight,
weight: weight,
when: kbWhen,
primary: kbOpts.primary,
secondary: kbOpts.secondary,
......@@ -362,15 +224,6 @@ class CoreCommand extends Command {
}
}
class UnboundCoreCommand extends CoreCommand {
constructor(handlerId: string, precondition: ContextKeyExpr = null) {
super({
id: handlerId,
precondition: precondition
});
}
}
function registerCommand(command: Command) {
KeybindingsRegistry.registerCommandAndKeybindingRule(command.toCommandAndKeybindingRule(CORE_WEIGHT));
}
......@@ -397,185 +250,10 @@ registerCoreDispatchCommand(H.CompositionEnd);
registerCoreDispatchCommand(H.Paste);
registerCoreDispatchCommand(H.Cut);
// https://support.apple.com/en-gb/HT201236
// [ADDED] Control-H Delete the character to the left of the insertion point. Or use Delete.
// [ADDED] Control-D Delete the character to the right of the insertion point. Or use Fn-Delete.
// [ADDED] Control-K Delete the text between the insertion point and the end of the line or paragraph.
// [ADDED] Command–Up Arrow Move the insertion point to the beginning of the document.
// [ADDED] Command–Down Arrow Move the insertion point to the end of the document.
// [ADDED] Command–Left Arrow Move the insertion point to the beginning of the current line.
// [ADDED] Command–Right Arrow Move the insertion point to the end of the current line.
// [ADDED] Option–Left Arrow Move the insertion point to the beginning of the previous word.
// [ADDED] Option–Right Arrow Move the insertion point to the end of the next word.
// [ADDED] Command–Shift–Up Arrow Select the text between the insertion point and the beginning of the document.
// [ADDED] Command–Shift–Down Arrow Select the text between the insertion point and the end of the document.
// [ADDED] Command–Shift–Left Arrow Select the text between the insertion point and the beginning of the current line.
// [ADDED] Command–Shift–Right Arrow Select the text between the insertion point and the end of the current line.
// [USED BY DUPLICATE LINES] Shift–Option–Up Arrow Extend text selection to the beginning of the current paragraph, then to the beginning of the following paragraph if pressed again.
// [USED BY DUPLICATE LINES] Shift–Option–Down Arrow Extend text selection to the end of the current paragraph, then to the end of the following paragraph if pressed again.
// [ADDED] Shift–Option–Left Arrow Extend text selection to the beginning of the current word, then to the beginning of the following word if pressed again.
// [ADDED] Shift–Option–Right Arrow Extend text selection to the end of the current word, then to the end of the following word if pressed again.
// [ADDED] Control-A Move to the beginning of the line or paragraph.
// [ADDED] Control-E Move to the end of a line or paragraph.
// [ADDED] Control-F Move one character forward.
// [ADDED] Control-B Move one character backward.
//Control-L Center the cursor or selection in the visible area.
// [ADDED] Control-P Move up one line.
// [ADDED] Control-N Move down one line.
// [ADDED] Control-O Insert a new line after the insertion point.
//Control-T Swap the character behind the insertion point with the character in front of the insertion point.
// Unconfirmed????
// Config.addKeyBinding(editorCommon.Handler.CursorPageDown, KeyMod.WinCtrl | KeyCode.KEY_V);
// OS X built in commands
// Control+y => yank
// [ADDED] Command+backspace => Delete to Hard BOL
// [ADDED] Command+delete => Delete to Hard EOL
// [ADDED] Control+k => Delete to Hard EOL
// Control+l => show_at_center
// Control+Command+d => noop
// Control+Command+shift+d => noop
// Register cursor commands
registerCommand(new CoreCommand({
id: H.ExpandLineSelection,
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.KEY_I
}
}));
registerCoreAPICommand(H.EditorScroll, EditorScroll.description);
registerCommand(new CoreCommand({
id: H.ScrollLineUp,
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
mac: { primary: KeyMod.WinCtrl | KeyCode.PageUp }
}
}));
registerCommand(new CoreCommand({
id: H.ScrollLineDown,
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
mac: { primary: KeyMod.WinCtrl | KeyCode.PageDown }
}
}));
registerCommand(new CoreCommand({
id: H.ScrollPageUp,
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.PageUp,
win: { primary: KeyMod.Alt | KeyCode.PageUp },
linux: { primary: KeyMod.Alt | KeyCode.PageUp }
}
}));
registerCommand(new CoreCommand({
id: H.ScrollPageDown,
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.PageDown,
win: { primary: KeyMod.Alt | KeyCode.PageDown },
linux: { primary: KeyMod.Alt | KeyCode.PageDown }
}
}));
registerCoreAPICommand(H.RevealLine, RevealLine.description);
registerCommand(new CoreCommand({
id: H.Tab,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: ContextKeyExpr.and(
EditorContextKeys.textFocus,
EditorContextKeys.tabDoesNotMoveFocus
),
primary: KeyCode.Tab
}
}));
registerCommand(new CoreCommand({
id: H.Outdent,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: ContextKeyExpr.and(
EditorContextKeys.textFocus,
EditorContextKeys.tabDoesNotMoveFocus
),
primary: KeyMod.Shift | KeyCode.Tab
}
}));
registerCommand(new CoreCommand({
id: H.DeleteLeft,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Backspace,
secondary: [KeyMod.Shift | KeyCode.Backspace],
mac: { primary: KeyCode.Backspace, secondary: [KeyMod.Shift | KeyCode.Backspace, KeyMod.WinCtrl | KeyCode.KEY_H, KeyMod.WinCtrl | KeyCode.Backspace] }
}
}));
registerCommand(new CoreCommand({
id: H.DeleteRight,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Delete,
mac: { primary: KeyCode.Delete, secondary: [KeyMod.WinCtrl | KeyCode.KEY_D, KeyMod.WinCtrl | KeyCode.Delete] }
}
}));
registerCommand(new CoreCommand({
id: H.CancelSelection,
precondition: EditorContextKeys.hasNonEmptySelection,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
}));
registerCommand(new CoreCommand({
id: H.RemoveSecondaryCursors,
precondition: EditorContextKeys.hasMultipleSelections,
kbOpts: {
weight: CORE_WEIGHT + 1,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
}));
registerCommand(new CoreCommand({
id: H.LineBreakInsert,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: null,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_O }
}
}));
abstract class BaseTextInputAwareCommand extends Command {
public runCommand(accessor: ServicesAccessor, args: any): void {
......
......@@ -10,13 +10,18 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason } from "vs/editor/common/controller/cursorEvents";
import { CursorMoveCommands, CursorMove as CursorMove_ } from "vs/editor/common/controller/cursorMoveCommands";
import { EditorCommand, ICommandOptions } from "vs/editor/common/config/config";
import { EditorCommand, ICommandOptions, Command } from "vs/editor/common/config/config";
import { ServicesAccessor } from "vs/platform/instantiation/common/instantiation";
import { registerEditorCommand } from "vs/editor/common/editorCommonExtensions";
import { IColumnSelectResult, ColumnSelection } from "vs/editor/common/controller/cursorColumnSelection";
import { EditorContextKeys } from "vs/editor/common/editorContextKeys";
import { KeyMod, KeyCode } from "vs/base/common/keyCodes";
import { KeybindingsRegistry } from "vs/platform/keybinding/common/keybindingsRegistry";
import H = editorCommon.Handler;
import { ICodeEditorService } from "vs/editor/common/services/codeEditorService";
import { ContextKeyExpr } from "vs/platform/contextkey/common/contextkey";
import * as types from 'vs/base/common/types';
import { ICommandHandlerDescription } from "vs/platform/commands/common/commands";
const CORE_WEIGHT = KeybindingsRegistry.WEIGHT.editorCore();
......@@ -28,6 +33,147 @@ export abstract class CoreEditorCommand extends EditorCommand {
public abstract runCoreEditorCommand(cursors: ICursors, args: any): void;
}
export namespace EditorScroll_ {
const isEditorScrollArgs = function (arg): boolean {
if (!types.isObject(arg)) {
return false;
}
let scrollArg: RawArguments = 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;
};
export const description = <ICommandHandlerDescription>{
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'
\`\`\`
* 'value': Number of units to move. Default is '1'.
* 'revealCursor': If 'true' reveals the cursor if it is outside view port.
`,
constraint: isEditorScrollArgs
}
]
};
/**
* Directions in the view for editor scroll command.
*/
export const RawDirection = {
Up: 'up',
Down: 'down',
};
/**
* Units for editor scroll 'by' argument
*/
export const RawUnit = {
Line: 'line',
WrappedLine: 'wrappedLine',
Page: 'page',
HalfPage: 'halfPage'
};
/**
* Arguments for editor scroll command
*/
export interface RawArguments {
to: string;
by?: string;
value?: number;
revealCursor?: boolean;
};
export function parse(args: RawArguments): ParsedArguments {
let direction: Direction;
switch (args.to) {
case RawDirection.Up:
direction = Direction.Up;
break;
case RawDirection.Down:
direction = Direction.Down;
break;
default:
// Illegal arguments
return null;
}
let unit: Unit;
switch (args.by) {
case RawUnit.Line:
unit = Unit.Line;
break;
case RawUnit.WrappedLine:
unit = Unit.WrappedLine;
break;
case RawUnit.Page:
unit = Unit.Page;
break;
case RawUnit.HalfPage:
unit = Unit.HalfPage;
break;
default:
unit = Unit.WrappedLine;
}
const value = Math.floor(args.value || 1);
const revealCursor = !!args.revealCursor;
return {
direction: direction,
unit: unit,
value: value,
revealCursor: revealCursor
};
}
export interface ParsedArguments {
direction: Direction;
unit: Unit;
value: number;
revealCursor: boolean;
}
export const enum Direction {
Up = 1,
Down = 2
}
export const enum Unit {
Line = 1,
WrappedLine = 2,
Page = 3,
HalfPage = 4
}
}
export namespace CoreCommands {
class BaseMoveToCommand extends CoreEditorCommand {
......@@ -53,13 +199,13 @@ export namespace CoreCommands {
}
export const MoveTo: CoreEditorCommand = registerEditorCommand(new BaseMoveToCommand({
id: 'moveTo',
id: '_moveTo',
inSelectionMode: false,
precondition: null
}));
export const MoveToSelect: CoreEditorCommand = registerEditorCommand(new BaseMoveToCommand({
id: 'moveToSelect',
id: '_moveToSelect',
inSelectionMode: true,
precondition: null
}));
......@@ -175,7 +321,7 @@ export namespace CoreCommands {
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.UpArrow,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.PageUp,
linux: { primary: 0 }
}
}));
......@@ -519,7 +665,7 @@ export namespace CoreCommands {
export const LastCursorMoveToSelect: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'lastCursorMoveToSelect',
id: '_lastCursorMoveToSelect',
precondition: null
});
}
......@@ -732,4 +878,487 @@ export namespace CoreCommands {
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.DownArrow }
}
}));
export class EditorScrollImpl extends CoreEditorCommand {
constructor() {
super({
id: 'editorScroll',
precondition: null,
description: EditorScroll_.description
});
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const parsed = EditorScroll_.parse(args);
if (!parsed) {
// illegal arguments
return;
}
this._runEditorScroll(cursors, args.source, parsed);
}
_runEditorScroll(cursors: ICursors, source: string, args: EditorScroll_.ParsedArguments): void {
const desiredScrollTop = this._computeDesiredScrollTop(cursors.context, args);
if (args.revealCursor) {
// must ensure cursor is in new visible range
const desiredVisibleViewRange = cursors.context.getCompletelyVisibleViewRangeAtScrollTop(desiredScrollTop);
cursors.setStates(
source,
CursorChangeReason.Explicit,
[
CursorMoveCommands.findPositionInViewportIfOutside(cursors.context, cursors.getPrimaryCursor(), desiredVisibleViewRange, false)
]
);
}
cursors.scrollTo(desiredScrollTop);
}
private _computeDesiredScrollTop(context: CursorContext, args: EditorScroll_.ParsedArguments): number {
if (args.unit === EditorScroll_.Unit.Line) {
// scrolling by model lines
const visibleModelRange = context.getCompletelyVisibleModelRange();
let desiredTopModelLineNumber: number;
if (args.direction === 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(context.model.getLineCount(), visibleModelRange.startLineNumber + args.value);
}
const desiredTopViewPosition = context.convertModelPositionToViewPosition(new Position(desiredTopModelLineNumber, 1));
return context.getVerticalOffsetForViewLine(desiredTopViewPosition.lineNumber);
}
let noOfLines: number;
if (args.unit === EditorScroll_.Unit.Page) {
noOfLines = context.config.pageSize * args.value;
} else if (args.unit === EditorScroll_.Unit.HalfPage) {
noOfLines = Math.round(context.config.pageSize / 2) * args.value;
} else {
noOfLines = args.value;
}
const deltaLines = (args.direction === EditorScroll_.Direction.Up ? -1 : 1) * noOfLines;
return context.getScrollTop() + deltaLines * context.config.lineHeight;
}
}
export const EditorScroll: EditorScrollImpl = registerEditorCommand(new EditorScrollImpl());
export const ScrollLineUp: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'scrollLineUp',
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
mac: { primary: KeyMod.WinCtrl | KeyCode.PageUp }
}
});
}
runCoreEditorCommand(cursors: ICursors, args: any): void {
EditorScroll._runEditorScroll(cursors, args.source, {
direction: EditorScroll_.Direction.Up,
unit: EditorScroll_.Unit.WrappedLine,
value: 1,
revealCursor: false
});
}
});
export const ScrollPageUp: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'scrollPageUp',
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.PageUp,
win: { primary: KeyMod.Alt | KeyCode.PageUp },
linux: { primary: KeyMod.Alt | KeyCode.PageUp }
}
});
}
runCoreEditorCommand(cursors: ICursors, args: any): void {
EditorScroll._runEditorScroll(cursors, args.source, {
direction: EditorScroll_.Direction.Up,
unit: EditorScroll_.Unit.Page,
value: 1,
revealCursor: false
});
}
});
export const ScrollLineDown: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'scrollLineDown',
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
mac: { primary: KeyMod.WinCtrl | KeyCode.PageDown }
}
});
}
runCoreEditorCommand(cursors: ICursors, args: any): void {
EditorScroll._runEditorScroll(cursors, args.source, {
direction: EditorScroll_.Direction.Down,
unit: EditorScroll_.Unit.WrappedLine,
value: 1,
revealCursor: false
});
}
});
export const ScrollPageDown: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'scrollPageDown',
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.PageDown,
win: { primary: KeyMod.Alt | KeyCode.PageDown },
linux: { primary: KeyMod.Alt | KeyCode.PageDown }
}
});
}
runCoreEditorCommand(cursors: ICursors, args: any): void {
EditorScroll._runEditorScroll(cursors, args.source, {
direction: EditorScroll_.Direction.Down,
unit: EditorScroll_.Unit.Page,
value: 1,
revealCursor: false
});
}
});
class WordCommand extends CoreEditorCommand {
private readonly _inSelectionMode: boolean;
constructor(opts: ICommandOptions & { inSelectionMode: boolean; }) {
super(opts);
this._inSelectionMode = opts.inSelectionMode;
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
[
CursorMoveCommands.word(cursors.context, cursors.getPrimaryCursor(), this._inSelectionMode, args.position)
]
);
cursors.reveal(true, RevealTarget.Primary);
}
}
export const WordSelect: CoreEditorCommand = registerEditorCommand(new WordCommand({
inSelectionMode: false,
id: '_wordSelect',
precondition: null
}));
export const WordSelectDrag: CoreEditorCommand = registerEditorCommand(new WordCommand({
inSelectionMode: true,
id: '_wordSelectDrag',
precondition: null
}));
export const LastCursorWordSelect: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'lastCursorWordSelect',
precondition: null
});
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly || context.model.hasEditableRange()) {
return;
}
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.word(context, newStates[lastAddedCursorIndex], true, args.position);
context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
newStates
);
}
});
class LineCommand extends CoreEditorCommand {
private readonly _inSelectionMode: boolean;
constructor(opts: ICommandOptions & { inSelectionMode: boolean; }) {
super(opts);
this._inSelectionMode = opts.inSelectionMode;
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
[
CursorMoveCommands.line(cursors.context, cursors.getPrimaryCursor(), this._inSelectionMode, args.position, args.viewPosition)
]
);
cursors.reveal(false, RevealTarget.Primary);
}
}
export const LineSelect: CoreEditorCommand = registerEditorCommand(new LineCommand({
inSelectionMode: false,
id: '_lineSelect',
precondition: null
}));
export const LineSelectDrag: CoreEditorCommand = registerEditorCommand(new LineCommand({
inSelectionMode: true,
id: '_lineSelectDrag',
precondition: null
}));
class LastCursorLineCommand extends CoreEditorCommand {
private readonly _inSelectionMode: boolean;
constructor(opts: ICommandOptions & { inSelectionMode: boolean; }) {
super(opts);
this._inSelectionMode = opts.inSelectionMode;
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly || context.model.hasEditableRange()) {
return;
}
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, newStates[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition);
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
newStates
);
}
}
export const LastCursorLineSelect: CoreEditorCommand = registerEditorCommand(new LastCursorLineCommand({
inSelectionMode: false,
id: 'lastCursorLineSelect',
precondition: null
}));
export const LastCursorLineSelectDrag: CoreEditorCommand = registerEditorCommand(new LastCursorLineCommand({
inSelectionMode: true,
id: 'lastCursorLineSelectDrag',
precondition: null
}));
export const ExpandLineSelection: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'expandLineSelection',
precondition: null,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyCode.KEY_I
}
});
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
CursorState.ensureInEditableRange(
cursors.context,
CursorMoveCommands.expandLineSelection(cursors.context, cursors.getAll())
)
);
cursors.reveal(true, RevealTarget.Primary);
}
});
export const CancelSelection: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'cancelSelection',
precondition: EditorContextKeys.hasNonEmptySelection,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
});
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
[
CursorMoveCommands.cancelSelection(cursors.context, cursors.getPrimaryCursor())
]
);
cursors.reveal(true, RevealTarget.Primary);
}
});
export const RemoveSecondaryCursors: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
constructor() {
super({
id: 'removeSecondaryCursors',
precondition: EditorContextKeys.hasMultipleSelections,
kbOpts: {
weight: CORE_WEIGHT + 1,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
});
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
cursors.context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
[
cursors.getPrimaryCursor()
]
);
cursors.reveal(true, RevealTarget.Primary);
}
});
};
namespace Config {
function findFocusedEditor(commandId: string, accessor: ServicesAccessor, complain: boolean): editorCommon.ICommonCodeEditor {
let editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (!editor) {
if (complain) {
console.warn('Cannot execute ' + commandId + ' because no code editor is focused.');
}
return null;
}
return editor;
}
function withCodeEditorFromCommandHandler(commandId: string, accessor: ServicesAccessor, callback: (editor: editorCommon.ICommonCodeEditor) => void): void {
let editor = findFocusedEditor(commandId, accessor, true);
if (editor) {
callback(editor);
}
}
function triggerEditorHandler(handlerId: string, accessor: ServicesAccessor, args: any): void {
withCodeEditorFromCommandHandler(handlerId, accessor, (editor) => {
editor.trigger('keyboard', handlerId, args);
});
}
class CoreCommand extends Command {
public runCommand(accessor: ServicesAccessor, args: any): void {
triggerEditorHandler(this.id, accessor, args);
}
}
function registerCommand(command: Command) {
KeybindingsRegistry.registerCommandAndKeybindingRule(command.toCommandAndKeybindingRule(CORE_WEIGHT));
}
registerCommand(new CoreCommand({
id: H.Tab,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: ContextKeyExpr.and(
EditorContextKeys.textFocus,
EditorContextKeys.tabDoesNotMoveFocus
),
primary: KeyCode.Tab
}
}));
registerCommand(new CoreCommand({
id: H.Outdent,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: ContextKeyExpr.and(
EditorContextKeys.textFocus,
EditorContextKeys.tabDoesNotMoveFocus
),
primary: KeyMod.Shift | KeyCode.Tab
}
}));
registerCommand(new CoreCommand({
id: H.DeleteLeft,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Backspace,
secondary: [KeyMod.Shift | KeyCode.Backspace],
mac: { primary: KeyCode.Backspace, secondary: [KeyMod.Shift | KeyCode.Backspace, KeyMod.WinCtrl | KeyCode.KEY_H, KeyMod.WinCtrl | KeyCode.Backspace] }
}
}));
registerCommand(new CoreCommand({
id: H.DeleteRight,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.Delete,
mac: { primary: KeyCode.Delete, secondary: [KeyMod.WinCtrl | KeyCode.KEY_D, KeyMod.WinCtrl | KeyCode.Delete] }
}
}));
registerCommand(new CoreCommand({
id: H.LineBreakInsert,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textFocus,
primary: null,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_O }
}
}));
}
......@@ -21,7 +21,7 @@ import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations
import { TextModelEventType, ModelRawContentChangedEvent, RawContentChangedType } from 'vs/editor/common/model/textModelEvents';
import { CursorEventType, CursorChangeReason, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent, ICursorRevealRangeEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
import { CursorMoveCommands } from "vs/editor/common/controller/cursorMoveCommands";
import { RevealLine, EditorScroll } from "vs/editor/common/config/config";
import { RevealLine } from "vs/editor/common/config/config";
import { CommonEditorRegistry } from "vs/editor/common/editorCommonExtensions";
import { CoreEditorCommand } from 'vs/editor/common/controller/coreCommands';
......@@ -234,6 +234,12 @@ export class Cursor extends Disposable implements ICursors {
this.revealRange(target, VerticalRevealType.Simple, horizontal);
}
public scrollTo(desiredScrollTop: number): void {
this._eventEmitter.emit(CursorEventType.CursorScrollRequest, new CursorScrollRequest(
desiredScrollTop
));
}
public saveState(): editorCommon.ICursorState[] {
var selections = this.cursors.getSelections(),
......@@ -866,26 +872,12 @@ export class Cursor extends Disposable implements ICursors {
private _registerHandlers(): void {
let H = editorCommon.Handler;
this._handlers[H.AddCursorUp] = (ctx) => this._addCursorUp(ctx);
this._handlers[H.AddCursorDown] = (ctx) => this._addCursorDown(ctx);
this._handlers[H.SelectAll] = (ctx) => this._selectAll(ctx);
this._handlers[H.LineSelect] = (ctx) => this._line(false, ctx);
this._handlers[H.LineSelectDrag] = (ctx) => this._line(true, ctx);
this._handlers[H.LastCursorLineSelect] = (ctx) => this._lastCursorLine(false, ctx);
this._handlers[H.LastCursorLineSelectDrag] = (ctx) => this._lastCursorLine(true, ctx);
this._handlers[H.LineInsertBefore] = (ctx) => this._lineInsertBefore(ctx);
this._handlers[H.LineInsertAfter] = (ctx) => this._lineInsertAfter(ctx);
this._handlers[H.LineBreakInsert] = (ctx) => this._lineBreakInsert(ctx);
this._handlers[H.WordSelect] = (ctx) => this._word(false, ctx);
this._handlers[H.WordSelectDrag] = (ctx) => this._word(true, ctx);
this._handlers[H.LastCursorWordSelect] = (ctx) => this._lastCursorWord(ctx);
this._handlers[H.CancelSelection] = (ctx) => this._cancelSelection(ctx);
this._handlers[H.RemoveSecondaryCursors] = (ctx) => this._removeSecondaryCursors(ctx);
this._handlers[H.Type] = (ctx) => this._type(ctx);
this._handlers[H.ReplacePreviousChar] = (ctx) => this._replacePreviousChar(ctx);
this._handlers[H.CompositionStart] = (ctx) => this._compositionStart(ctx);
......@@ -895,20 +887,11 @@ export class Cursor extends Disposable implements ICursors {
this._handlers[H.Outdent] = (ctx) => this._outdent(ctx);
this._handlers[H.Paste] = (ctx) => this._paste(ctx);
this._handlers[H.EditorScroll] = (ctx) => this._editorScroll(ctx);
this._handlers[H.ScrollLineUp] = (ctx) => this._scrollUp(false, ctx);
this._handlers[H.ScrollLineDown] = (ctx) => this._scrollDown(false, ctx);
this._handlers[H.ScrollPageUp] = (ctx) => this._scrollUp(true, ctx);
this._handlers[H.ScrollPageDown] = (ctx) => this._scrollDown(true, ctx);
this._handlers[H.DeleteLeft] = (ctx) => this._deleteLeft(ctx);
this._handlers[H.DeleteRight] = (ctx) => this._deleteRight(ctx);
this._handlers[H.Cut] = (ctx) => this._cut(ctx);
this._handlers[H.ExpandLineSelection] = (ctx) => this._expandLineSelection(ctx);
this._handlers[H.Undo] = (ctx) => this._undo(ctx);
this._handlers[H.Redo] = (ctx) => this._redo(ctx);
......@@ -930,30 +913,6 @@ export class Cursor extends Disposable implements ICursors {
};
}
private _addCursorUp(ctx: IMultipleCursorOperationContext): void {
if (this.configuration.editor.readOnly) {
return;
}
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldRevealTarget = RevealTarget.TopMost;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
this.cursors.setStates(CursorMoveCommands.addCursorUp(this.context, this.getAll()), true);
}
private _addCursorDown(ctx: IMultipleCursorOperationContext): void {
if (this.configuration.editor.readOnly) {
return;
}
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldRevealTarget = RevealTarget.BottomMost;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
this.cursors.setStates(CursorMoveCommands.addCursorDown(this.context, this.getAll()), true);
}
private _selectAll(ctx: IMultipleCursorOperationContext): void {
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
......@@ -962,74 +921,6 @@ export class Cursor extends Disposable implements ICursors {
this.cursors.setStates([result], false);
}
private _line(inSelectionMode: boolean, ctx: IMultipleCursorOperationContext): void {
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldRevealHorizontal = false;
const r = CursorMoveCommands.line(this.context, this.getPrimaryCursor(), inSelectionMode, ctx.eventData.position, ctx.eventData.viewPosition);
this.cursors.setStates([r], false);
}
private _lastCursorLine(inSelectionMode: boolean, ctx: IMultipleCursorOperationContext): void {
if (this.configuration.editor.readOnly || this.model.hasEditableRange()) {
return;
}
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldReveal = false;
const lastAddedCursor = this.cursors.getLastAddedCursor();
const result = CursorMoveCommands.line(this.context, lastAddedCursor.asCursorState(), inSelectionMode, ctx.eventData.position, ctx.eventData.viewPosition);
lastAddedCursor.setState(this.context, result.modelState, result.viewState, false);
}
private _expandLineSelection(ctx: IMultipleCursorOperationContext): void {
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
this.cursors.setStates(CursorMoveCommands.expandLineSelection(this.context, this.getAll()), true);
}
private _word(inSelectionMode: boolean, ctx: IMultipleCursorOperationContext): void {
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
const primaryCursor = this.getPrimaryCursor();
const r = CursorMoveCommands.word(this.context, primaryCursor, inSelectionMode, ctx.eventData.position);
this.cursors.setStates([r], false);
}
private _lastCursorWord(ctx: IMultipleCursorOperationContext): void {
if (this.configuration.editor.readOnly || this.model.hasEditableRange()) {
return;
}
ctx.cursorPositionChangeReason = CursorChangeReason.Explicit;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
ctx.shouldReveal = false;
const lastAddedCursor = this.cursors.getLastAddedCursor();
const r = CursorMoveCommands.word(this.context, lastAddedCursor.asCursorState(), true, ctx.eventData.position);
lastAddedCursor.setState(this.context, r.modelState, r.viewState, false);
}
private _removeSecondaryCursors(ctx: IMultipleCursorOperationContext): void {
this.cursors.killSecondaryCursors();
}
private _cancelSelection(ctx: IMultipleCursorOperationContext): void {
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
const r = CursorMoveCommands.cancelSelection(this.context, this.getPrimaryCursor());
this.cursors.setStates([r], false);
}
// -------------------- START editing operations
private _applyEdits(ctx: IMultipleCursorOperationContext, edits: EditOperationResult): void {
......@@ -1220,82 +1111,6 @@ export class Cursor extends Disposable implements ICursors {
this.emitCursorRevealRange(range, null, revealAt, false);
}
private _scrollUp(isPaged: boolean, ctx: IMultipleCursorOperationContext): void {
this._doEditorScroll({
direction: EditorScroll.Direction.Up,
unit: (isPaged ? EditorScroll.Unit.Page : EditorScroll.Unit.WrappedLine),
value: 1,
revealCursor: false
}, ctx);
}
private _scrollDown(isPaged: boolean, ctx: IMultipleCursorOperationContext): void {
this._doEditorScroll({
direction: EditorScroll.Direction.Down,
unit: (isPaged ? EditorScroll.Unit.Page : EditorScroll.Unit.WrappedLine),
value: 1,
revealCursor: false
}, ctx);
}
private _editorScroll(ctx: IMultipleCursorOperationContext): void {
const args = EditorScroll.parse(ctx.eventData);
if (!args) {
// illegal arguments
return;
}
this._doEditorScroll(args, ctx);
}
private _doEditorScroll(args: EditorScroll.ParsedArguments, ctx: IMultipleCursorOperationContext): void {
const desiredScrollTop = this._computeDesiredScrollTop(args);
if (args.revealCursor) {
// must ensure cursor is in new visible range
const desiredVisibleViewRange = this.context.getCompletelyVisibleViewRangeAtScrollTop(desiredScrollTop);
const r = CursorMoveCommands.findPositionInViewportIfOutside(this.context, this.getPrimaryCursor(), desiredVisibleViewRange, false);
this.cursors.setStates([r], false);
}
this._eventEmitter.emit(CursorEventType.CursorScrollRequest, new CursorScrollRequest(
desiredScrollTop
));
ctx.shouldReveal = false;
}
private _computeDesiredScrollTop(args: EditorScroll.ParsedArguments): number {
if (args.unit === EditorScroll.Unit.Line) {
// scrolling by model lines
const visibleModelRange = this.context.getCompletelyVisibleModelRange();
let desiredTopModelLineNumber: number;
if (args.direction === 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(this.context.model.getLineCount(), visibleModelRange.startLineNumber + args.value);
}
const desiredTopViewPosition = this.context.convertModelPositionToViewPosition(new Position(desiredTopModelLineNumber, 1));
return this.context.getVerticalOffsetForViewLine(desiredTopViewPosition.lineNumber);
}
let noOfLines: number;
if (args.unit === EditorScroll.Unit.Page) {
noOfLines = this.context.config.pageSize * args.value;
} else if (args.unit === EditorScroll.Unit.HalfPage) {
noOfLines = Math.round(this.context.config.pageSize / 2) * args.value;
} else {
noOfLines = args.value;
}
const deltaLines = (args.direction === EditorScroll.Direction.Up ? -1 : 1) * noOfLines;
return this.context.getScrollTop() + deltaLines * this.context.config.lineHeight;
}
private _undo(ctx: IMultipleCursorOperationContext): void {
ctx.cursorPositionChangeReason = CursorChangeReason.Undo;
this._interpretCommandResult(this.model.undo());
......
......@@ -41,6 +41,7 @@ export interface ICursors {
setStates(source: string, reason: CursorChangeReason, states: CursorState[]): void;
reveal(horizontal: boolean, target: RevealTarget): void;
scrollTo(desiredScrollTop: number): void;
}
export interface CharacterMap {
......
......@@ -2032,11 +2032,6 @@ export var Handler = {
ExecuteCommand: 'executeCommand',
ExecuteCommands: 'executeCommands',
ExpandLineSelection: 'expandLineSelection',
AddCursorDown: 'addCursorDown',
AddCursorUp: 'addCursorUp',
Type: 'type',
ReplacePreviousChar: 'replacePreviousChar',
CompositionStart: 'compositionStart',
......@@ -2050,36 +2045,17 @@ export var Handler = {
DeleteLeft: 'deleteLeft',
DeleteRight: 'deleteRight',
RemoveSecondaryCursors: 'removeSecondaryCursors',
CancelSelection: 'cancelSelection',
Cut: 'cut',
Undo: 'undo',
Redo: 'redo',
WordSelect: 'wordSelect',
WordSelectDrag: 'wordSelectDrag',
LastCursorWordSelect: 'lastCursorWordSelect',
LineSelect: 'lineSelect',
LineSelectDrag: 'lineSelectDrag',
LastCursorLineSelect: 'lastCursorLineSelect',
LastCursorLineSelectDrag: 'lastCursorLineSelectDrag',
LineInsertBefore: 'lineInsertBefore',
LineInsertAfter: 'lineInsertAfter',
LineBreakInsert: 'lineBreakInsert',
SelectAll: 'selectAll',
EditorScroll: 'editorScroll',
ScrollLineUp: 'scrollLineUp',
ScrollLineDown: 'scrollLineDown',
ScrollPageUp: 'scrollPageUp',
ScrollPageDown: 'scrollPageDown',
RevealLine: 'revealLine'
};
......
......@@ -6,20 +6,22 @@
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Handler, ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { editorAction, ServicesAccessor, EditorAction, HandlerEditorAction } from 'vs/editor/common/editorCommonExtensions';
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
import { Selection } from 'vs/editor/common/core/selection';
import { CursorChangeReason } from "vs/editor/common/controller/cursorEvents";
import { CursorMoveCommands } from "vs/editor/common/controller/cursorMoveCommands";
import { CursorState, RevealTarget } from 'vs/editor/common/controller/cursorCommon';
@editorAction
class InsertCursorAbove extends HandlerEditorAction {
export class InsertCursorAbove extends EditorAction {
constructor() {
super({
id: 'editor.action.insertCursorAbove',
label: nls.localize('mutlicursor.insertAbove', "Add Cursor Above"),
alias: 'Add Cursor Above',
precondition: null,
handlerId: Handler.AddCursorUp,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.UpArrow,
......@@ -30,17 +32,36 @@ class InsertCursorAbove extends HandlerEditorAction {
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor, args: any): void {
const cursors = editor._getCursors();
const context = cursors.context;
if (context.config.readOnly) {
return;
}
context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
CursorState.ensureInEditableRange(
context,
CursorMoveCommands.addCursorUp(context, cursors.getAll())
)
);
cursors.reveal(true, RevealTarget.TopMost);
}
}
@editorAction
class InsertCursorBelow extends HandlerEditorAction {
export class InsertCursorBelow extends EditorAction {
constructor() {
super({
id: 'editor.action.insertCursorBelow',
label: nls.localize('mutlicursor.insertBelow', "Add Cursor Below"),
alias: 'Add Cursor Below',
precondition: null,
handlerId: Handler.AddCursorDown,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.DownArrow,
......@@ -51,6 +72,26 @@ class InsertCursorBelow extends HandlerEditorAction {
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor, args: any): void {
const cursors = editor._getCursors();
const context = cursors.context;
if (context.config.readOnly) {
return;
}
context.model.pushStackElement();
cursors.setStates(
args.source,
CursorChangeReason.Explicit,
CursorState.ensureInEditableRange(
context,
CursorMoveCommands.addCursorDown(context, cursors.getAll())
)
);
cursors.reveal(true, RevealTarget.BottomMost);
}
}
@editorAction
......
/*---------------------------------------------------------------------------------------------
* 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 { withMockCodeEditor } from "vs/editor/test/common/mocks/mockCodeEditor";
import { Selection } from "vs/editor/common/core/selection";
import { InsertCursorAbove, InsertCursorBelow } from "vs/editor/contrib/multicursor/common/multicursor";
import { Handler } from "vs/editor/common/editorCommon";
suite('Multicursor', () => {
test('issue #2205: Multi-cursor pastes in reverse order', () => {
withMockCodeEditor([
'abc',
'def'
], {}, (editor, cursor) => {
let addCursorUpAction = new InsertCursorAbove();
editor.setSelection(new Selection(2, 1, 2, 1));
addCursorUpAction.run(null, editor, {});
assert.equal(cursor.getSelections().length, 2);
editor.trigger('test', Handler.Paste, { text: '1\n2' });
// cursorCommand(cursor, H.Paste, { text: '1\n2' });
assert.equal(editor.getModel().getLineContent(1), '1abc');
assert.equal(editor.getModel().getLineContent(2), '2def');
});
});
test('issue #1336: Insert cursor below on last line adds a cursor to the end of the current line', () => {
withMockCodeEditor([
'abc'
], {}, (editor, cursor) => {
let addCursorDownAction = new InsertCursorBelow();
addCursorDownAction.run(null, editor, {});
assert.equal(cursor.getSelections().length, 1);
});
});
});
......@@ -599,37 +599,37 @@ suite('Editor Controller - Cursor', () => {
// 01234 56789012345678 0
// let LINE1 = ' \tMy First Line\t ';
moveTo(thisCursor, 1, 1);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
moveTo(thisCursor, 1, 2);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
moveTo(thisCursor, 1, 5);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
moveTo(thisCursor, 1, 19);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
moveTo(thisCursor, 1, 20);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
moveTo(thisCursor, 1, 21);
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 2, 1));
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 3, 1));
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 4, 1));
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 5, 1));
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 5, LINE5.length + 1));
cursorCommand(thisCursor, H.ExpandLineSelection);
CoreCommands.ExpandLineSelection.runCoreEditorCommand(thisCursor, {});
assertCursor(thisCursor, new Selection(1, 1, 5, LINE5.length + 1));
});
......@@ -1501,34 +1501,6 @@ suite('Editor Controller - Regression tests', () => {
mode.dispose();
});
test('issue #1336: Insert cursor below on last line adds a cursor to the end of the current line', () => {
usingCursor({
text: [
'abc'
],
}, (model, cursor) => {
cursorCommand(cursor, H.AddCursorDown);
assert.equal(cursor.getSelections().length, 1);
});
});
test('issue #2205: Multi-cursor pastes in reverse order', () => {
usingCursor({
text: [
'abc',
'def'
],
}, (model, cursor) => {
moveTo(cursor, 2, 1, false);
cursorCommand(cursor, H.AddCursorUp);
assert.equal(cursor.getSelections().length, 2);
cursorCommand(cursor, H.Paste, { text: '1\n2' });
assert.equal(model.getLineContent(1), '1abc');
assert.equal(model.getLineContent(2), '2def');
});
});
test('issue #10212: Pasting entire line does not replace selection', () => {
usingCursor({
text: [
......@@ -1653,13 +1625,17 @@ suite('Editor Controller - Regression tests', () => {
moveTo(cursor, 1, 1, false);
function assertWordRight(col, expectedCol) {
cursorCommand(cursor, col === 1 ? H.WordSelect : H.WordSelectDrag, {
let args = {
position: {
lineNumber: 1,
column: col
},
preference: 'right'
});
}
};
if (col === 1) {
CoreCommands.WordSelect.runCoreEditorCommand(cursor, args);
} else {
CoreCommands.WordSelectDrag.runCoreEditorCommand(cursor, args);
}
assert.equal(cursor.getSelection().startColumn, 1, 'TEST FOR ' + col);
assert.equal(cursor.getSelection().endColumn, expectedCol, 'TEST FOR ' + col);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册