mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-29 19:59:19 +01:00
Move more editing operations out of cursor.ts
This commit is contained in:
@@ -29,6 +29,7 @@ import * as editorOptions from 'vs/editor/common/config/editorOptions';
|
||||
import { CursorEventType, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { ViewModelCursors } from "vs/editor/common/viewModel/viewModelCursors";
|
||||
import { CommonEditorRegistry } from "vs/editor/common/editorCommonExtensions";
|
||||
|
||||
let EDITOR_ID = 0;
|
||||
|
||||
@@ -667,6 +668,7 @@ export abstract class CommonCodeEditor extends Disposable implements editorCommo
|
||||
return;
|
||||
}
|
||||
|
||||
// Special case for pasting
|
||||
if (handlerId === editorCommon.Handler.Paste) {
|
||||
if (!this.cursor || typeof payload.text !== 'string' || payload.text.length === 0) {
|
||||
// nothing to do
|
||||
@@ -683,15 +685,25 @@ export abstract class CommonCodeEditor extends Disposable implements editorCommo
|
||||
return;
|
||||
}
|
||||
|
||||
let candidate = this.getAction(handlerId);
|
||||
if (candidate !== null) {
|
||||
TPromise.as(candidate.run()).done(null, onUnexpectedError);
|
||||
} else {
|
||||
if (!this.cursor) {
|
||||
return;
|
||||
}
|
||||
this.cursor.trigger(source, handlerId, payload);
|
||||
const action = this.getAction(handlerId);
|
||||
if (action) {
|
||||
TPromise.as(action.run()).done(null, onUnexpectedError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const command = CommonEditorRegistry.getEditorCommand(handlerId);
|
||||
if (command) {
|
||||
payload = payload || {};
|
||||
payload.source = source;
|
||||
TPromise.as(command.runEditorCommand(null, this, payload)).done(null, onUnexpectedError);
|
||||
return;
|
||||
}
|
||||
|
||||
this.cursor.trigger(source, handlerId, payload);
|
||||
}
|
||||
|
||||
public _getCursors(): ICursors {
|
||||
|
||||
@@ -24,6 +24,8 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { IEditorService } from 'vs/platform/editor/common/editor';
|
||||
import { TypeOperations } from "vs/editor/common/controller/cursorTypeOperations";
|
||||
import { DeleteOperations } from "vs/editor/common/controller/cursorDeleteOperations";
|
||||
|
||||
const CORE_WEIGHT = KeybindingsRegistry.WEIGHT.editorCore();
|
||||
|
||||
@@ -1398,6 +1400,120 @@ export namespace CoreNavigationCommands {
|
||||
}
|
||||
|
||||
export namespace CoreEditingCommands {
|
||||
|
||||
export const LineBreakInsert: EditorCommand = registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'lineBreakInsert',
|
||||
precondition: EditorContextKeys.writable,
|
||||
kbOpts: {
|
||||
weight: CORE_WEIGHT,
|
||||
kbExpr: EditorContextKeys.textFocus,
|
||||
primary: null,
|
||||
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_O }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
|
||||
editor.pushUndoStop();
|
||||
editor.executeCommands(this.id, TypeOperations.lineBreakInsert(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
|
||||
}
|
||||
});
|
||||
|
||||
export const Outdent: EditorCommand = registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'outdent',
|
||||
precondition: EditorContextKeys.writable,
|
||||
kbOpts: {
|
||||
weight: CORE_WEIGHT,
|
||||
kbExpr: ContextKeyExpr.and(
|
||||
EditorContextKeys.textFocus,
|
||||
EditorContextKeys.tabDoesNotMoveFocus
|
||||
),
|
||||
primary: KeyMod.Shift | KeyCode.Tab
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
|
||||
editor.pushUndoStop();
|
||||
editor.executeCommands(this.id, TypeOperations.outdent(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
});
|
||||
|
||||
export const Tab: EditorCommand = registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'tab',
|
||||
precondition: EditorContextKeys.writable,
|
||||
kbOpts: {
|
||||
weight: CORE_WEIGHT,
|
||||
kbExpr: ContextKeyExpr.and(
|
||||
EditorContextKeys.textFocus,
|
||||
EditorContextKeys.tabDoesNotMoveFocus
|
||||
),
|
||||
primary: KeyCode.Tab
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
|
||||
editor.pushUndoStop();
|
||||
editor.executeCommands(this.id, TypeOperations.tab(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
});
|
||||
|
||||
export const DeleteLeft: EditorCommand = registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: '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] }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
|
||||
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections());
|
||||
if (shouldPushStackElementBefore) {
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
editor.executeCommands(this.id, commands);
|
||||
}
|
||||
});
|
||||
|
||||
export const DeleteRight: EditorCommand = registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: '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] }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void {
|
||||
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteRight(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections());
|
||||
if (shouldPushStackElementBefore) {
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
editor.executeCommands(this.id, commands);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
namespace Config {
|
||||
@@ -1412,88 +1528,10 @@ namespace Config {
|
||||
return getCodeEditor(activeEditor);
|
||||
}
|
||||
|
||||
function withCodeEditorFromCommandHandler(accessor: ServicesAccessor, callback: (editor: editorCommon.ICommonCodeEditor) => void): void {
|
||||
let editor = findFocusedEditor(accessor);
|
||||
if (editor) {
|
||||
callback(editor);
|
||||
}
|
||||
}
|
||||
|
||||
function triggerEditorHandler(handlerId: string, accessor: ServicesAccessor, args: any): void {
|
||||
withCodeEditorFromCommandHandler(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 }
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
class BaseTextInputAwareCommand extends Command {
|
||||
|
||||
private readonly _editorHandler: string | EditorCommand;
|
||||
|
||||
@@ -504,21 +504,12 @@ export class Cursor extends Disposable implements ICursors {
|
||||
private _registerHandlers(): void {
|
||||
let H = editorCommon.Handler;
|
||||
|
||||
this._handlers[H.LineInsertAfter] = (args) => this._lineInsertAfter(args);
|
||||
this._handlers[H.LineBreakInsert] = (args) => this._lineBreakInsert(args);
|
||||
|
||||
this._handlers[H.Type] = (args) => this._type(args);
|
||||
this._handlers[H.ReplacePreviousChar] = (args) => this._replacePreviousChar(args);
|
||||
this._handlers[H.CompositionStart] = (args) => this._compositionStart(args);
|
||||
this._handlers[H.CompositionEnd] = (args) => this._compositionEnd(args);
|
||||
this._handlers[H.Tab] = (args) => this._tab(args);
|
||||
this._handlers[H.Indent] = (args) => this._indent(args);
|
||||
this._handlers[H.Outdent] = (args) => this._outdent(args);
|
||||
this._handlers[H.Paste] = (args) => this._paste(args);
|
||||
|
||||
this._handlers[H.DeleteLeft] = (args) => this._deleteLeft(args);
|
||||
this._handlers[H.DeleteRight] = (args) => this._deleteRight(args);
|
||||
|
||||
this._handlers[H.Cut] = (args) => this._cut(args);
|
||||
|
||||
this._handlers[H.Undo] = (args) => this._undo(args);
|
||||
@@ -542,6 +533,7 @@ export class Cursor extends Disposable implements ICursors {
|
||||
|
||||
// -------------------- START editing operations
|
||||
|
||||
// TODO@Alex: remove
|
||||
private _getAllCursorsModelState(sorted: boolean = false): SingleCursorState[] {
|
||||
let cursors = this._cursors.getAll();
|
||||
|
||||
@@ -558,14 +550,6 @@ export class Cursor extends Disposable implements ICursors {
|
||||
return r;
|
||||
}
|
||||
|
||||
private _lineInsertAfter(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return TypeOperations.lineInsertAfter(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _lineBreakInsert(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return TypeOperations.lineBreakInsert(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _type(args: CursorOperationArgs<{ text: string; }>): EditOperationResult {
|
||||
const text = args.eventData.text;
|
||||
|
||||
@@ -613,18 +597,6 @@ export class Cursor extends Disposable implements ICursors {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _tab(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return TypeOperations.tab(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _indent(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return TypeOperations.indent(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _outdent(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return TypeOperations.outdent(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _distributePasteToCursors(args: CursorOperationArgs<{ pasteOnNewLine: boolean; text: string; }>): string[] {
|
||||
if (args.eventData.pasteOnNewLine) {
|
||||
return null;
|
||||
@@ -659,14 +631,6 @@ export class Cursor extends Disposable implements ICursors {
|
||||
}
|
||||
}
|
||||
|
||||
private _deleteLeft(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return DeleteOperations.deleteLeft(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _deleteRight(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return DeleteOperations.deleteRight(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
private _cut(args: CursorOperationArgs<void>): EditOperationResult {
|
||||
return DeleteOperations.cut(this.context.config, this.context.model, this._getAllCursorsModelState());
|
||||
}
|
||||
|
||||
@@ -7,22 +7,23 @@
|
||||
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
|
||||
import { SingleCursorState, CursorColumns, CursorConfiguration, ICursorSimpleModel, EditOperationResult } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { ICommand } from "vs/editor/common/editorCommon";
|
||||
|
||||
export class DeleteOperations {
|
||||
|
||||
public static deleteRight(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static deleteRight(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): [boolean, ICommand[]] {
|
||||
let commands: ICommand[] = [];
|
||||
let shouldPushStackElementBefore = false;
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
|
||||
let deleteSelection: Range = cursor.selection;
|
||||
let deleteSelection: Range = cursor;
|
||||
|
||||
if (deleteSelection.isEmpty()) {
|
||||
let position = cursor.position;
|
||||
let position = cursor.getPosition();
|
||||
let rightOfPosition = MoveOperations.right(config, model, position.lineNumber, position.column);
|
||||
deleteSelection = new Range(
|
||||
rightOfPosition.lineNumber,
|
||||
@@ -44,21 +45,17 @@ export class DeleteOperations {
|
||||
|
||||
commands[i] = new ReplaceCommand(deleteSelection, '');
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: shouldPushStackElementBefore,
|
||||
shouldPushStackElementAfter: false
|
||||
});
|
||||
return [shouldPushStackElementBefore, commands];
|
||||
}
|
||||
|
||||
private static _isAutoClosingPairDelete(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): boolean {
|
||||
private static _isAutoClosingPairDelete(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): boolean {
|
||||
if (!config.autoClosingBrackets) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
const selection = cursor.selection;
|
||||
const position = cursor.position;
|
||||
const selection = cursors[i];
|
||||
const position = selection.getPosition();
|
||||
|
||||
if (!selection.isEmpty()) {
|
||||
return false;
|
||||
@@ -82,11 +79,11 @@ export class DeleteOperations {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static _runAutoClosingPairDelete(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
private static _runAutoClosingPairDelete(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): [boolean, ICommand[]] {
|
||||
let commands: ICommand[] = [];
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
const position = cursor.position;
|
||||
const position = cursor.getPosition();
|
||||
const deleteSelection = new Range(
|
||||
position.lineNumber,
|
||||
position.column - 1,
|
||||
@@ -95,13 +92,10 @@ export class DeleteOperations {
|
||||
);
|
||||
commands[i] = new ReplaceCommand(deleteSelection, '');
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: true,
|
||||
shouldPushStackElementAfter: false
|
||||
});
|
||||
return [true, commands];
|
||||
}
|
||||
|
||||
public static deleteLeft(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static deleteLeft(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): [boolean, ICommand[]] {
|
||||
|
||||
if (this._isAutoClosingPairDelete(config, model, cursors)) {
|
||||
return this._runAutoClosingPairDelete(config, model, cursors);
|
||||
@@ -112,10 +106,10 @@ export class DeleteOperations {
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
|
||||
let deleteSelection: Range = cursor.selection;
|
||||
let deleteSelection: Range = cursor;
|
||||
|
||||
if (deleteSelection.isEmpty()) {
|
||||
let position = cursor.position;
|
||||
let position = cursor.getPosition();
|
||||
|
||||
if (config.useTabStops && position.column > 1) {
|
||||
let lineContent = model.getLineContent(position.lineNumber);
|
||||
@@ -158,10 +152,7 @@ export class DeleteOperations {
|
||||
|
||||
commands[i] = new ReplaceCommand(deleteSelection, '');
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: shouldPushStackElementBefore,
|
||||
shouldPushStackElementAfter: false
|
||||
});
|
||||
return [shouldPushStackElementBefore, commands];
|
||||
}
|
||||
|
||||
public static cut(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
|
||||
@@ -21,38 +21,32 @@ import { CursorChangeReason } from "vs/editor/common/controller/cursorEvents";
|
||||
|
||||
export class TypeOperations {
|
||||
|
||||
public static indent(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static indent(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): ICommand[] {
|
||||
let commands: ICommand[] = [];
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
commands[i] = new ShiftCommand(cursor.selection, {
|
||||
commands[i] = new ShiftCommand(cursor, {
|
||||
isUnshift: false,
|
||||
tabSize: config.tabSize,
|
||||
oneIndent: config.oneIndent,
|
||||
useTabStops: config.useTabStops
|
||||
});
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: true,
|
||||
shouldPushStackElementAfter: true
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static outdent(config: CursorConfiguration, model: ICursorSimpleModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static outdent(config: CursorConfiguration, model: ICursorSimpleModel, cursors: Selection[]): ICommand[] {
|
||||
let commands: ICommand[] = [];
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
commands[i] = new ShiftCommand(cursor.selection, {
|
||||
commands[i] = new ShiftCommand(cursor, {
|
||||
isUnshift: true,
|
||||
tabSize: config.tabSize,
|
||||
oneIndent: config.oneIndent,
|
||||
useTabStops: config.useTabStops
|
||||
});
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: true,
|
||||
shouldPushStackElementAfter: true
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static shiftIndent(config: CursorConfiguration, indentation: string, count?: number): string {
|
||||
@@ -172,11 +166,10 @@ export class TypeOperations {
|
||||
return new ReplaceCommand(selection, typeText, insertsAutoWhitespace);
|
||||
}
|
||||
|
||||
public static tab(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static tab(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 selection = cursor.selection;
|
||||
const selection = cursors[i];
|
||||
|
||||
if (selection.isEmpty()) {
|
||||
|
||||
@@ -211,10 +204,7 @@ export class TypeOperations {
|
||||
});
|
||||
}
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: true,
|
||||
shouldPushStackElementAfter: true
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static replacePreviousChar(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[], txt: string, replaceCharCnt: number): EditOperationResult {
|
||||
@@ -600,29 +590,23 @@ export class TypeOperations {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public static lineInsertAfter(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static lineInsertAfter(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 position = cursor.position;
|
||||
let column = model.getLineMaxColumn(position.lineNumber);
|
||||
commands[i] = this._enter(config, model, false, new Range(position.lineNumber, column, position.lineNumber, column));
|
||||
let lineNumber = cursor.positionLineNumber;
|
||||
let column = model.getLineMaxColumn(lineNumber);
|
||||
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 lineBreakInsert(config: CursorConfiguration, model: ITokenizedModel, cursors: SingleCursorState[]): EditOperationResult {
|
||||
public static lineBreakInsert(config: CursorConfiguration, model: ITokenizedModel, cursors: Selection[]): ICommand[] {
|
||||
let commands: ICommand[] = [];
|
||||
for (let i = 0, len = cursors.length; i < len; i++) {
|
||||
const cursor = cursors[i];
|
||||
commands[i] = this._enter(config, model, true, cursor.selection);
|
||||
commands[i] = this._enter(config, model, true, cursor);
|
||||
}
|
||||
return new EditOperationResult(commands, {
|
||||
shouldPushStackElementBefore: true,
|
||||
shouldPushStackElementAfter: false,
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2071,18 +2071,8 @@ export var Handler = {
|
||||
CompositionEnd: 'compositionEnd',
|
||||
Paste: 'paste',
|
||||
|
||||
Tab: 'tab',
|
||||
Indent: 'indent',
|
||||
Outdent: 'outdent',
|
||||
|
||||
DeleteLeft: 'deleteLeft',
|
||||
DeleteRight: 'deleteRight',
|
||||
|
||||
Cut: 'cut',
|
||||
|
||||
Undo: 'undo',
|
||||
Redo: 'redo',
|
||||
|
||||
LineInsertAfter: 'lineInsertAfter',
|
||||
LineBreakInsert: 'lineBreakInsert',
|
||||
};
|
||||
|
||||
@@ -74,22 +74,6 @@ export abstract class EditorAction extends ConfigEditorCommand {
|
||||
public abstract run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor, args: any): void | TPromise<void>;
|
||||
}
|
||||
|
||||
export interface IHandlerActionOptions extends IActionOptions {
|
||||
handlerId: string;
|
||||
}
|
||||
export abstract class HandlerEditorAction extends EditorAction {
|
||||
private _handlerId: string;
|
||||
|
||||
constructor(opts: IHandlerActionOptions) {
|
||||
super(opts);
|
||||
this._handlerId = opts.handlerId;
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
editor.trigger(this.id, this._handlerId, null);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Editor Actions
|
||||
|
||||
export function editorAction(ctor: { new (): EditorAction; }): void {
|
||||
|
||||
@@ -9,16 +9,17 @@ import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
|
||||
import { SortLinesCommand } from 'vs/editor/contrib/linesOperations/common/sortLinesCommand';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { TrimTrailingWhitespaceCommand } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
|
||||
import { Handler, ICommand, ICommonCodeEditor, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
import { ICommand, ICommonCodeEditor, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { ReplaceCommand, ReplaceCommandThatPreservesSelection } from 'vs/editor/common/commands/replaceCommand';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { editorAction, ServicesAccessor, IActionOptions, EditorAction, HandlerEditorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { editorAction, ServicesAccessor, IActionOptions, EditorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { CopyLinesCommand } from './copyLinesCommand';
|
||||
import { DeleteLinesCommand } from './deleteLinesCommand';
|
||||
import { MoveLinesCommand } from './moveLinesCommand';
|
||||
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
|
||||
import { CoreEditingCommands } from "vs/editor/common/controller/coreCommands";
|
||||
|
||||
// copy lines
|
||||
|
||||
@@ -296,37 +297,45 @@ class DeleteLinesAction extends AbstractRemoveLinesAction {
|
||||
}
|
||||
|
||||
@editorAction
|
||||
class IndentLinesAction extends HandlerEditorAction {
|
||||
export class IndentLinesAction extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.action.indentLines',
|
||||
label: nls.localize('lines.indent', "Indent Line"),
|
||||
alias: 'Indent Line',
|
||||
precondition: EditorContextKeys.writable,
|
||||
handlerId: Handler.Indent,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_CLOSE_SQUARE_BRACKET
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
|
||||
editor.pushUndoStop();
|
||||
editor.executeCommands(this.id, TypeOperations.indent(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
}
|
||||
|
||||
@editorAction
|
||||
class OutdentLinesAction extends HandlerEditorAction {
|
||||
class OutdentLinesAction extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.action.outdentLines',
|
||||
label: nls.localize('lines.outdent', "Outdent Line"),
|
||||
alias: 'Outdent Line',
|
||||
precondition: EditorContextKeys.writable,
|
||||
handlerId: Handler.Outdent,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_OPEN_SQUARE_BRACKET
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
|
||||
CoreEditingCommands.Outdent.runEditorCommand(null, editor, null);
|
||||
}
|
||||
}
|
||||
|
||||
@editorAction
|
||||
@@ -351,20 +360,24 @@ export class InsertLineBeforeAction extends EditorAction {
|
||||
}
|
||||
|
||||
@editorAction
|
||||
class InsertLineAfterAction extends HandlerEditorAction {
|
||||
export class InsertLineAfterAction extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.action.insertLineAfter',
|
||||
label: nls.localize('lines.insertAfter', "Insert Line Below"),
|
||||
alias: 'Insert Line Below',
|
||||
precondition: EditorContextKeys.writable,
|
||||
handlerId: Handler.LineInsertAfter,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Enter
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
|
||||
editor.pushUndoStop();
|
||||
editor.executeCommands(this.id, TypeOperations.lineInsertAfter(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractDeleteAllToBoundaryAction extends EditorAction {
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Handler, IModel } from 'vs/editor/common/editorCommon';
|
||||
import { Handler, IModel, DefaultEndOfLine } from 'vs/editor/common/editorCommon';
|
||||
import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
|
||||
import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction, DeleteAllRightAction, InsertLineBeforeAction } from 'vs/editor/contrib/linesOperations/common/linesOperations';
|
||||
import { DeleteAllLeftAction, JoinLinesAction, TransposeAction, UpperCaseAction, LowerCaseAction, DeleteAllRightAction, InsertLineBeforeAction, InsertLineAfterAction, IndentLinesAction } from 'vs/editor/contrib/linesOperations/common/linesOperations';
|
||||
import { Cursor } from "vs/editor/common/controller/cursor";
|
||||
import { Model } from "vs/editor/common/model/model";
|
||||
import { CoreEditingCommands } from "vs/editor/common/controller/coreCommands";
|
||||
|
||||
suite('Editor Contrib - Line Operations', () => {
|
||||
suite('DeleteAllLeftAction', () => {
|
||||
@@ -531,4 +533,75 @@ suite('Editor Contrib - Line Operations', () => {
|
||||
assert.equal(model.getLineContent(4), 'Third line');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('InsertLineAfterAction', () => {
|
||||
function testInsertLineAfter(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 insertLineAfterAction = new InsertLineAfterAction();
|
||||
|
||||
insertLineAfterAction.run(null, editor);
|
||||
callback(editor.getModel(), cursor);
|
||||
});
|
||||
}
|
||||
|
||||
testInsertLineAfter(1, 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');
|
||||
});
|
||||
|
||||
testInsertLineAfter(2, 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');
|
||||
});
|
||||
|
||||
testInsertLineAfter(3, 3, (model, cursor) => {
|
||||
assert.deepEqual(cursor.getSelection(), new Selection(4, 1, 4, 1));
|
||||
assert.equal(model.getLineContent(1), 'First line');
|
||||
assert.equal(model.getLineContent(2), 'Second line');
|
||||
assert.equal(model.getLineContent(3), 'Third line');
|
||||
assert.equal(model.getLineContent(4), '');
|
||||
});
|
||||
});
|
||||
|
||||
test('Bug 18276:[editor] Indentation broken when selection is empty', () => {
|
||||
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'function baz() {'
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
let indentLinesAction = new IndentLinesAction();
|
||||
editor.setPosition(new Position(1, 2));
|
||||
|
||||
indentLinesAction.run(null, editor);
|
||||
assert.equal(model.getLineContent(1), '\tfunction baz() {');
|
||||
assert.deepEqual(editor.getSelection(), new Selection(1, 3, 1, 3));
|
||||
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), '\tf\tunction baz() {');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,7 +24,9 @@ import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { viewModelHelper } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { CoreNavigationCommands } from 'vs/editor/common/controller/coreCommands';
|
||||
import { CoreNavigationCommands, CoreEditingCommands } from 'vs/editor/common/controller/coreCommands';
|
||||
import { withMockCodeEditor } from "vs/editor/test/common/mocks/mockCodeEditor";
|
||||
import { TextModel } from "vs/editor/common/model/textModel";
|
||||
|
||||
let H = Handler;
|
||||
|
||||
@@ -1119,22 +1121,24 @@ class IndentRulesMode extends MockMode {
|
||||
|
||||
suite('Editor Controller - Regression tests', () => {
|
||||
test('Bug 9121: Auto indent + undo + redo is funky', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
''
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: false
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
},
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1');
|
||||
|
||||
cursorCommand(cursor, H.Tab, {});
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2');
|
||||
|
||||
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
|
||||
@@ -1146,16 +1150,16 @@ suite('Editor Controller - Regression tests', () => {
|
||||
CoreNavigationCommands.CursorLeft.runCoreEditorCommand(cursor, {});
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\n\tx', 'assert5');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t\nx', 'assert6');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert7');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert8');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert9');
|
||||
|
||||
cursorCommand(cursor, H.Undo, {});
|
||||
@@ -1176,219 +1180,234 @@ suite('Editor Controller - Regression tests', () => {
|
||||
cursorCommand(cursor, H.Redo, {});
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert15');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
|
||||
|
||||
test('bug #16543: Tab should indent to correct indentation spot immediately', () => {
|
||||
let mode = new OnEnterMode(IndentAction.Indent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'function baz() {',
|
||||
'\tfunction hello() { // something here',
|
||||
'\t',
|
||||
'',
|
||||
'\t}',
|
||||
'}'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
}, (model, cursor) => {
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 4, 1, false);
|
||||
assertCursor(cursor, new Selection(4, 1, 4, 1));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(4), '\t\t');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('bug #2938 (1): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
let mode = new OnEnterMode(IndentAction.Indent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
}, (model, cursor) => {
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 4, 2, false);
|
||||
assertCursor(cursor, new Selection(4, 2, 4, 2));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(4), '\t\t\t');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
|
||||
test('bug #2938 (2): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
let mode = new OnEnterMode(IndentAction.Indent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
' ',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
}, (model, cursor) => {
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 4, 1, false);
|
||||
assertCursor(cursor, new Selection(4, 1, 4, 1));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(4), '\t\t\t');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('bug #2938 (3): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
let mode = new OnEnterMode(IndentAction.Indent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t\t\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
}, (model, cursor) => {
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 4, 3, false);
|
||||
assertCursor(cursor, new Selection(4, 3, 4, 3));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(4), '\t\t\t\t');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('bug #2938 (4): When pressing Tab on white-space only lines, indent straight to the right spot (similar to empty lines)', () => {
|
||||
let mode = new OnEnterMode(IndentAction.Indent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'\tfunction baz() {',
|
||||
'\t\tfunction hello() { // something here',
|
||||
'\t\t',
|
||||
'\t\t\t\t',
|
||||
'\t\t}',
|
||||
'\t}'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
}, (model, cursor) => {
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 4, 4, false);
|
||||
assertCursor(cursor, new Selection(4, 4, 4, 4));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(4), '\t\t\t\t\t');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('Bug 18276:[editor] Indentation broken when selection is empty', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
'function baz() {'
|
||||
],
|
||||
modelOpts: {
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
}, (model, cursor) => {
|
||||
moveTo(cursor, 1, 2, false);
|
||||
assertCursor(cursor, new Selection(1, 2, 1, 2));
|
||||
|
||||
cursorCommand(cursor, H.Indent, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(1), '\tfunction baz() {');
|
||||
|
||||
assertCursor(cursor, new Selection(1, 3, 1, 3));
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
assert.equal(model.getLineContent(1), '\tf\tunction baz() {');
|
||||
});
|
||||
});
|
||||
|
||||
test('bug #16815:Shift+Tab doesn\'t go back to tabstop', () => {
|
||||
let mode = new OnEnterMode(IndentAction.IndentOutdent);
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' function baz() {'
|
||||
],
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 1, 6, false);
|
||||
assertCursor(cursor, new Selection(1, 6, 1, 6));
|
||||
|
||||
cursorCommand(cursor, H.Outdent, null, 'keyboard');
|
||||
CoreEditingCommands.Outdent.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' function baz() {');
|
||||
assertCursor(cursor, new Selection(1, 5, 1, 5));
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('Bug #18293:[regression][editor] Can\'t outdent whitespace line', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' '
|
||||
],
|
||||
modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 1, 7, false);
|
||||
assertCursor(cursor, new Selection(1, 7, 1, 7));
|
||||
|
||||
cursorCommand(cursor, H.Outdent, null, 'keyboard');
|
||||
CoreEditingCommands.Outdent.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' ');
|
||||
assertCursor(cursor, new Selection(1, 5, 1, 5));
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('Bug #16657: [editor] Tab on empty line of zero indentation moves cursor to position (1,1)', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'function baz() {',
|
||||
'\tfunction hello() { // something here',
|
||||
'\t',
|
||||
@@ -1396,22 +1415,26 @@ suite('Editor Controller - Regression tests', () => {
|
||||
'\t}',
|
||||
'}',
|
||||
''
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 7, 1, false);
|
||||
assertCursor(cursor, new Selection(7, 1, 7, 1));
|
||||
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(7), '\t');
|
||||
assertCursor(cursor, new Selection(7, 2, 7, 2));
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('bug #16740: [editor] Cut line doesn\'t quite cut the last line', () => {
|
||||
@@ -1480,24 +1503,33 @@ suite('Editor Controller - Regression tests', () => {
|
||||
|
||||
test('issue #1140: Backspace stops prematurely', () => {
|
||||
let mode = new SurroundingMode();
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'function baz() {',
|
||||
' return 1;',
|
||||
'};'
|
||||
],
|
||||
languageIdentifier: mode.getLanguageIdentifier(),
|
||||
modelOpts: { tabSize: 4, insertSpaces: true, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
tabSize: 4,
|
||||
insertSpaces: true,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 3, 2, false);
|
||||
moveTo(cursor, 1, 14, true);
|
||||
assertCursor(cursor, new Selection(3, 2, 1, 14));
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft);
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assertCursor(cursor, new Selection(1, 14, 1, 14));
|
||||
assert.equal(model.getLineCount(), 1);
|
||||
assert.equal(model.getLineContent(1), 'function baz(;');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
@@ -1520,15 +1552,22 @@ suite('Editor Controller - Regression tests', () => {
|
||||
});
|
||||
|
||||
test('issue #3071: Investigate why undo stack gets corrupted', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'some lines',
|
||||
'and more lines',
|
||||
'just some text',
|
||||
],
|
||||
languageIdentifier: null,
|
||||
modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 1, 1, false);
|
||||
moveTo(cursor, 3, 4, true);
|
||||
|
||||
@@ -1540,7 +1579,7 @@ suite('Editor Controller - Regression tests', () => {
|
||||
}
|
||||
});
|
||||
|
||||
cursorCommand(cursor, H.Tab);
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(), [
|
||||
'\t just some text'
|
||||
].join('\n'), '001');
|
||||
@@ -1559,6 +1598,8 @@ suite('Editor Controller - Regression tests', () => {
|
||||
'just some text',
|
||||
].join('\n'), '003');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #12950: Cannot Double Click To Insert Emoji Using OSX Emoji Panel', () => {
|
||||
@@ -1584,35 +1625,55 @@ suite('Editor Controller - Regression tests', () => {
|
||||
});
|
||||
|
||||
test('issue #3463: pressing tab adds spaces, but not as many as for a tab', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'function a() {',
|
||||
'\tvar a = {',
|
||||
'\t\tx: 3',
|
||||
'\t};',
|
||||
'}',
|
||||
],
|
||||
modelOpts: { insertSpaces: true, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 3, 2, false);
|
||||
cursorCommand(cursor, H.Tab);
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(3), '\t \tx: 3');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #4312: trying to type a tab character over a sequence of spaces results in unexpected behaviour', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'var foo = 123; // this is a comment',
|
||||
'var bar = 4; // another comment'
|
||||
],
|
||||
modelOpts: { insertSpaces: false, tabSize: 4, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
moveTo(cursor, 1, 15, false);
|
||||
moveTo(cursor, 1, 22, true);
|
||||
cursorCommand(cursor, H.Tab);
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), 'var foo = 123;\t// this is a comment');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #832: word right', () => {
|
||||
@@ -1810,70 +1871,80 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
});
|
||||
|
||||
test('Cursor honors insertSpaces configuration on tab', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' \tMy First Line\t ',
|
||||
'My Second Line123',
|
||||
' Third Line',
|
||||
'',
|
||||
'1'
|
||||
],
|
||||
modelOpts: { insertSpaces: true, tabSize: 13, detectIndentation: false, defaultEOL: DefaultEndOfLine.LF, trimAutoWhitespace: true }
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 13,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
// Tab on column 1
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 1) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), ' My Second Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 2
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 2) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'M y Second Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 3
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 3) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 4
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 4) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 5
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 5) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My S econd Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 5
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 5) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My S econd Line123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 13
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 13) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My Second Li ne123');
|
||||
cursorCommand(cursor, H.Undo, null, 'keyboard');
|
||||
|
||||
// Tab on column 14
|
||||
assert.equal(model.getLineContent(2), 'My Second Line123');
|
||||
cursorCommand(cursor, CoreNavigationCommands.MoveTo.id, { position: new Position(2, 14) }, 'keyboard');
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'My Second Lin e123');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('Enter auto-indents with insertSpaces setting 1', () => {
|
||||
@@ -1930,48 +2001,6 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
mode.dispose();
|
||||
});
|
||||
|
||||
test('Insert line after', () => {
|
||||
let testInsertLineAfter = (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.LineInsertAfter, null, 'keyboard');
|
||||
callback(model, cursor);
|
||||
});
|
||||
};
|
||||
|
||||
testInsertLineAfter(1, 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');
|
||||
});
|
||||
|
||||
testInsertLineAfter(2, 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');
|
||||
});
|
||||
|
||||
testInsertLineAfter(3, 3, (model, cursor) => {
|
||||
assertCursor(cursor, new Selection(4, 1, 4, 1));
|
||||
assert.equal(model.getLineContent(1), 'First line');
|
||||
assert.equal(model.getLineContent(2), 'Second line');
|
||||
assert.equal(model.getLineContent(3), 'Third line');
|
||||
assert.equal(model.getLineContent(4), '');
|
||||
});
|
||||
});
|
||||
|
||||
test('removeAutoWhitespace off', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
@@ -2071,25 +2100,27 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
});
|
||||
|
||||
test('removeAutoWhitespace on: removes only whitespace the cursor added 2', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' if (a) {',
|
||||
' ',
|
||||
'',
|
||||
'',
|
||||
' }'
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
|
||||
moveTo(cursor, 3, 1);
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' if (a) {');
|
||||
assert.equal(model.getLineContent(2), ' ');
|
||||
assert.equal(model.getLineContent(3), ' ');
|
||||
@@ -2097,7 +2128,7 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
assert.equal(model.getLineContent(5), ' }');
|
||||
|
||||
moveTo(cursor, 4, 1);
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' if (a) {');
|
||||
assert.equal(model.getLineContent(2), ' ');
|
||||
assert.equal(model.getLineContent(3), '');
|
||||
@@ -2112,21 +2143,25 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
assert.equal(model.getLineContent(4), '');
|
||||
assert.equal(model.getLineContent(5), ' }something');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('removeAutoWhitespace on: test 1', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' some line abc '
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
|
||||
// Move cursor to the end, verify that we do not trim whitespaces if line has values
|
||||
moveTo(cursor, 1, model.getLineContent(1).length + 1);
|
||||
@@ -2141,7 +2176,7 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
assert.equal(model.getLineContent(3), ' ');
|
||||
|
||||
// More whitespaces
|
||||
cursorCommand(cursor, H.Tab, null, 'keyboard');
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' some line abc ');
|
||||
assert.equal(model.getLineContent(2), '');
|
||||
assert.equal(model.getLineContent(3), ' ');
|
||||
@@ -2172,63 +2207,65 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
assert.equal(model.getLineContent(4), '');
|
||||
assert.equal(model.getLineContent(5), '');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('UseTabStops is off', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' x',
|
||||
' a ',
|
||||
' '
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
editorOpts: {
|
||||
useTabStops: false
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model, useTabStops: false }, (editor, cursor) => {
|
||||
// DeleteLeft removes just one whitespace
|
||||
moveTo(cursor, 2, 9);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), ' a ');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('Backspace removes whitespaces with tab size', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
' \t \t x',
|
||||
' a ',
|
||||
' '
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: true,
|
||||
tabSize: 4,
|
||||
detectIndentation: false,
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
trimAutoWhitespace: true
|
||||
},
|
||||
editorOpts: {
|
||||
useTabStops: true
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model, useTabStops: true }, (editor, cursor) => {
|
||||
// DeleteLeft does not remove tab size, because some text exists before
|
||||
moveTo(cursor, 2, model.getLineContent(2).length + 1);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), ' a ');
|
||||
|
||||
// DeleteLeft removes tab size = 4
|
||||
moveTo(cursor, 2, 9);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), ' a ');
|
||||
|
||||
// DeleteLeft removes tab size = 4
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), 'a ');
|
||||
|
||||
// Undo DeleteLeft - get us back to original indentation
|
||||
@@ -2237,57 +2274,61 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
|
||||
// Nothing is broken when cursor is in (1,1)
|
||||
moveTo(cursor, 1, 1);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' \t \t x');
|
||||
|
||||
// DeleteLeft stops at tab stops even in mixed whitespace case
|
||||
moveTo(cursor, 1, 10);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' \t \t x');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' \t \tx');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), ' \tx');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(1), 'x');
|
||||
|
||||
// DeleteLeft on last line
|
||||
moveTo(cursor, 3, model.getLineContent(3).length + 1);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(3), '');
|
||||
|
||||
// DeleteLeft with removing new line symbol
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'x\n a ');
|
||||
|
||||
// In case of selection DeleteLeft only deletes selected text
|
||||
moveTo(cursor, 2, 3);
|
||||
moveTo(cursor, 2, 4, true);
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getLineContent(2), ' a ');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('PR #5423: Auto indent + undo + redo is funky', () => {
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
''
|
||||
],
|
||||
modelOpts: {
|
||||
].join('\n'),
|
||||
{
|
||||
defaultEOL: DefaultEndOfLine.LF,
|
||||
detectIndentation: false,
|
||||
insertSpaces: false,
|
||||
tabSize: 4,
|
||||
trimAutoWhitespace: true
|
||||
}
|
||||
}, (model, cursor) => {
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1');
|
||||
|
||||
cursorCommand(cursor, H.Tab, {});
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\t', 'assert2');
|
||||
|
||||
cursorCommand(cursor, H.Type, { text: 'y' }, 'keyboard');
|
||||
@@ -2302,19 +2343,19 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
CoreNavigationCommands.CursorLeft.runCoreEditorCommand(cursor, {});
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\n\tx', 'assert5');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\ty\nx', 'assert6');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tyx', 'assert7');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\n\tx', 'assert8');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '\nx', 'assert9');
|
||||
|
||||
cursorCommand(cursor, H.DeleteLeft, {});
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert10');
|
||||
|
||||
cursorCommand(cursor, H.Undo, {});
|
||||
@@ -2335,6 +2376,8 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
cursorCommand(cursor, H.Redo, {});
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'x', 'assert16');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3247,23 +3290,26 @@ suite('autoClosingPairs', () => {
|
||||
|
||||
test('All cursors should do the same thing when deleting left', () => {
|
||||
let mode = new AutoClosingMode();
|
||||
usingCursor({
|
||||
text: [
|
||||
let model = Model.createFromString(
|
||||
[
|
||||
'var a = ()'
|
||||
],
|
||||
languageIdentifier: mode.getLanguageIdentifier()
|
||||
}, (model, cursor) => {
|
||||
].join('\n'),
|
||||
TextModel.DEFAULT_CREATION_OPTIONS,
|
||||
mode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
cursor.setSelections('test', [
|
||||
new Selection(1, 4, 1, 4),
|
||||
new Selection(1, 10, 1, 10),
|
||||
]);
|
||||
|
||||
// delete left
|
||||
cursorCommand(cursor, H.DeleteLeft, null, 'keyboard');
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
|
||||
assert.equal(model.getValue(), 'va a = )');
|
||||
});
|
||||
model.dispose();
|
||||
mode.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ import { StandardTokenType } from 'vs/editor/common/modes';
|
||||
import { DEFAULT_WORD_REGEXP } from 'vs/editor/common/model/wordHelper';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import { IDecorationOptions, IModelDecorationOptions, IModelDeltaDecoration, TrackedRangeStickiness, Handler } from 'vs/editor/common/editorCommon';
|
||||
import { IDecorationOptions, IModelDecorationOptions, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/editorCommon';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -37,6 +37,7 @@ import { FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/pref
|
||||
import { IListService } from 'vs/platform/list/browser/listService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { CoreEditingCommands } from "vs/editor/common/controller/coreCommands";
|
||||
|
||||
const HOVER_DELAY = 300;
|
||||
const LAUNCH_JSON_REGEX = /launch\.json$/;
|
||||
@@ -434,7 +435,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
// Check if there are more characters on a line after a "configurations": [, if yes enter a newline
|
||||
if (this.editor.getModel().getLineLastNonWhitespaceColumn(position.lineNumber) > position.column) {
|
||||
this.editor.setPosition(position);
|
||||
this.editor.trigger(this.getId(), Handler.LineBreakInsert, undefined);
|
||||
CoreEditingCommands.LineBreakInsert.runEditorCommand(null, this.editor, null);
|
||||
}
|
||||
// Check if there is already an empty line to insert suggest, if yes just place the cursor
|
||||
if (this.editor.getModel().getLineLastNonWhitespaceColumn(position.lineNumber + 1) === 0) {
|
||||
|
||||
@@ -9,8 +9,9 @@ import nls = require('vs/nls');
|
||||
import { BasicEmmetEditorAction } from 'vs/workbench/parts/emmet/electron-browser/emmetActions';
|
||||
|
||||
import { editorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { Handler, ICommonCodeEditor } from 'vs/editor/common/editorCommon';
|
||||
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { CoreEditingCommands } from "vs/editor/common/controller/coreCommands";
|
||||
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -40,6 +41,6 @@ class ExpandAbbreviationAction extends BasicEmmetEditorAction {
|
||||
|
||||
protected noExpansionOccurred(editor: ICommonCodeEditor): void {
|
||||
// forward the tab key back to the editor
|
||||
editor.trigger('emmet', Handler.Tab, {});
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import { ICommonCodeEditor, Handler } from 'vs/editor/common/editorCommon';
|
||||
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
|
||||
import strings = require('vs/base/common/strings');
|
||||
import snippets = require('vs/editor/contrib/snippet/common/snippet');
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
||||
import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { CoreEditingCommands } from "vs/editor/common/controller/coreCommands";
|
||||
|
||||
import emmet = require('emmet');
|
||||
|
||||
@@ -140,7 +141,7 @@ export class EditorAccessor implements emmet.Editor {
|
||||
// During Expand Abbreviation action, if the expanded abbr is the same as the text it intends to replace,
|
||||
// then treat it as a no-op and return TAB to the editor
|
||||
if (this._emmetActionName === 'expand_abbreviation' && (value === textToReplace || value === textToReplace + '${0}')) {
|
||||
this._editor.trigger('emmet', Handler.Tab, {});
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, this._editor, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user