提交 af1cf7a4 编写于 作者: A Alex Dima

Move type operations out of oneCursor

上级 297b28ab
......@@ -1402,7 +1402,7 @@ export class Cursor extends EventEmitter {
}
} else {
this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.actualType(oneCursor, text, false, oneCtx));
this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: IOneCursorOperationContext) => OneCursorOp.actualType(oneCursor, text, oneCtx));
}
return true;
......
......@@ -8,7 +8,7 @@ import { Position } from 'vs/editor/common/core/position';
import { CharCode } from 'vs/base/common/charCode';
import * as strings from 'vs/base/common/strings';
import { IModeConfiguration } from 'vs/editor/common/controller/oneCursor';
import { IConfigurationChangedEvent, TextModelResolvedOptions, IConfiguration } from 'vs/editor/common/editorCommon';
import { ICommand, CursorChangeReason, IConfigurationChangedEvent, TextModelResolvedOptions, IConfiguration } from 'vs/editor/common/editorCommon';
import { TextModel } from 'vs/editor/common/model/textModel';
export interface CharacterMap {
......@@ -74,6 +74,53 @@ export interface ICursorSimpleModel {
getLineLastNonWhitespaceColumn(lineNumber: number): number;
}
export class EditOperationResult {
_editOperationBrand: void;
readonly command: ICommand;
readonly shouldPushStackElementBefore: boolean;
readonly shouldPushStackElementAfter: boolean;
readonly isAutoWhitespaceCommand: boolean;
readonly shouldRevealHorizontal: boolean;
readonly cursorPositionChangeReason: CursorChangeReason;
constructor(
command: ICommand,
opts?: {
shouldPushStackElementBefore: boolean;
shouldPushStackElementAfter: boolean;
isAutoWhitespaceCommand?: boolean;
shouldRevealHorizontal?: boolean;
cursorPositionChangeReason?: CursorChangeReason;
}
) {
this.command = command;
this.shouldPushStackElementBefore = false;
this.shouldPushStackElementAfter = false;
this.isAutoWhitespaceCommand = false;
this.shouldRevealHorizontal = true;
this.cursorPositionChangeReason = CursorChangeReason.NotSet;
if (typeof opts !== 'undefined') {
if (typeof opts.shouldPushStackElementBefore !== 'undefined') {
this.shouldPushStackElementBefore = opts.shouldPushStackElementBefore;
}
if (typeof opts.shouldPushStackElementAfter !== 'undefined') {
this.shouldPushStackElementAfter = opts.shouldPushStackElementAfter;
}
if (typeof opts.isAutoWhitespaceCommand !== 'undefined') {
this.isAutoWhitespaceCommand = opts.isAutoWhitespaceCommand;
}
if (typeof opts.shouldRevealHorizontal !== 'undefined') {
this.shouldRevealHorizontal = opts.shouldRevealHorizontal;
}
if (typeof opts.cursorPositionChangeReason !== 'undefined') {
this.cursorPositionChangeReason = opts.cursorPositionChangeReason;
}
}
}
}
/**
* Common operations that work and make sense both on the model and on the view model.
*/
......
......@@ -5,60 +5,12 @@
'use strict';
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
import { CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { EditOperationResult, CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { Range } from 'vs/editor/common/core/range';
import { ICommand, CursorChangeReason } from 'vs/editor/common/editorCommon';
import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations';
import { CursorModelState } from 'vs/editor/common/controller/oneCursor';
import * as strings from 'vs/base/common/strings';
export class EditOperationResult {
_editOperationBrand: void;
readonly command: ICommand;
readonly shouldPushStackElementBefore: boolean;
readonly shouldPushStackElementAfter: boolean;
readonly isAutoWhitespaceCommand: boolean;
readonly shouldRevealHorizontal: boolean;
readonly cursorPositionChangeReason: CursorChangeReason;
constructor(
command: ICommand,
opts?: {
shouldPushStackElementBefore: boolean;
shouldPushStackElementAfter: boolean;
isAutoWhitespaceCommand?: boolean;
shouldRevealHorizontal?: boolean;
cursorPositionChangeReason?: CursorChangeReason;
}
) {
this.command = command;
this.shouldPushStackElementBefore = false;
this.shouldPushStackElementAfter = false;
this.isAutoWhitespaceCommand = false;
this.shouldRevealHorizontal = true;
this.cursorPositionChangeReason = CursorChangeReason.NotSet;
if (typeof opts !== 'undefined') {
if (typeof opts.shouldPushStackElementBefore !== 'undefined') {
this.shouldPushStackElementBefore = opts.shouldPushStackElementBefore;
}
if (typeof opts.shouldPushStackElementAfter !== 'undefined') {
this.shouldPushStackElementAfter = opts.shouldPushStackElementAfter;
}
if (typeof opts.isAutoWhitespaceCommand !== 'undefined') {
this.isAutoWhitespaceCommand = opts.isAutoWhitespaceCommand;
}
if (typeof opts.shouldRevealHorizontal !== 'undefined') {
this.shouldRevealHorizontal = opts.shouldRevealHorizontal;
}
if (typeof opts.cursorPositionChangeReason !== 'undefined') {
this.cursorPositionChangeReason = opts.cursorPositionChangeReason;
}
}
}
}
export class DeleteOperations {
public static deleteRight(config: CursorConfiguration, model: ICursorSimpleModel, cursor: CursorModelState): EditOperationResult {
......
......@@ -4,18 +4,21 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ReplaceCommand, ReplaceCommandWithoutChangingPosition, ReplaceCommandWithOffsetCursorState } from 'vs/editor/common/commands/replaceCommand';
import { CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { EditOperationResult, CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { Range } from 'vs/editor/common/core/range';
import { CursorChangeReason, ICommand } from 'vs/editor/common/editorCommon';
import { CursorModelState } from 'vs/editor/common/controller/oneCursor';
import * as strings from 'vs/base/common/strings';
import { EditOperationResult } from 'vs/editor/common/controller/cursorDeleteOperations';
import { ShiftCommand } from 'vs/editor/common/commands/shiftCommand';
import { Selection } from 'vs/editor/common/core/selection';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { ITokenizedModel } from 'vs/editor/common/editorCommon';
import { IndentAction } from 'vs/editor/common/modes/languageConfiguration';
import { CharCode } from 'vs/base/common/charCode';
import { SurroundSelectionCommand } from 'vs/editor/common/commands/surroundSelectionCommand';
import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
export class TypeOperations {
......@@ -187,7 +190,7 @@ export class TypeOperations {
}
}
static _enter(config: CursorConfiguration, model: ITokenizedModel, keepPosition: boolean, range: Range): EditOperationResult {
private static _enter(config: CursorConfiguration, model: ITokenizedModel, keepPosition: boolean, range: Range): EditOperationResult {
let r = LanguageConfigurationRegistry.getEnterActionAtPosition(model, range.startLineNumber, range.startColumn);
let enterAction = r.enterAction;
......@@ -229,4 +232,223 @@ export class TypeOperations {
isAutoWhitespaceCommand: true
});
}
private static _typeInterceptorEnter(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (ch !== '\n') {
return null;
}
return TypeOperations._enter(config, model, false, cursor.selection);
}
private static _typeInterceptorAutoClosingCloseChar(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (!selection.isEmpty() || !config.autoClosingPairsClose.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineText = model.getLineContent(position.lineNumber);
let beforeCharacter = lineText.charAt(position.column - 1);
if (beforeCharacter !== ch) {
return null;
}
let typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1);
return new EditOperationResult(new ReplaceCommand(typeSelection, ch));
}
private static _typeInterceptorAutoClosingOpenChar(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (!selection.isEmpty() || !config.autoClosingPairsOpen.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineText = model.getLineContent(position.lineNumber);
let beforeCharacter = lineText.charAt(position.column - 1);
// Only consider auto closing the pair if a space follows or if another autoclosed pair follows
if (beforeCharacter) {
let isBeforeCloseBrace = false;
for (let closeBrace in config.autoClosingPairsClose) {
if (beforeCharacter === closeBrace) {
isBeforeCloseBrace = true;
break;
}
}
if (!isBeforeCloseBrace && !/\s/.test(beforeCharacter)) {
return null;
}
}
let lineTokens = model.getLineTokens(position.lineNumber, false);
let shouldAutoClosePair = false;
try {
shouldAutoClosePair = LanguageConfigurationRegistry.shouldAutoClosePair(ch, lineTokens, position.column);
} catch (e) {
onUnexpectedError(e);
}
if (!shouldAutoClosePair) {
return null;
}
let closeCharacter = config.autoClosingPairsOpen[ch];
return new EditOperationResult(new ReplaceCommandWithOffsetCursorState(selection, ch + closeCharacter, 0, -closeCharacter.length), {
shouldPushStackElementBefore: true,
shouldPushStackElementAfter: false
});
}
private static _typeInterceptorSurroundSelection(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (selection.isEmpty() || !config.surroundingPairs.hasOwnProperty(ch)) {
return null;
}
let selectionContainsOnlyWhitespace = true;
for (let lineNumber = selection.startLineNumber; lineNumber <= selection.endLineNumber; lineNumber++) {
let lineText = model.getLineContent(lineNumber);
let startIndex = (lineNumber === selection.startLineNumber ? selection.startColumn - 1 : 0);
let endIndex = (lineNumber === selection.endLineNumber ? selection.endColumn - 1 : lineText.length);
for (let charIndex = startIndex; charIndex < endIndex; charIndex++) {
let charCode = lineText.charCodeAt(charIndex);
if (charCode !== CharCode.Tab && charCode !== CharCode.Space) {
selectionContainsOnlyWhitespace = false;
// Break outer loop
lineNumber = selection.endLineNumber + 1;
// Break inner loop
charIndex = endIndex;
}
}
}
if (selectionContainsOnlyWhitespace) {
return null;
}
let closeCharacter = config.surroundingPairs[ch];
return new EditOperationResult(new SurroundSelectionCommand(selection, ch, closeCharacter), {
shouldPushStackElementBefore: true,
shouldPushStackElementAfter: true
});
}
private static _typeInterceptorElectricChar(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.electricChars.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineTokens = model.getLineTokens(position.lineNumber, false);
let electricAction: IElectricAction;
try {
electricAction = LanguageConfigurationRegistry.onElectricCharacter(ch, lineTokens, position.column);
} catch (e) {
onUnexpectedError(e);
}
if (!electricAction) {
return null;
}
if (electricAction.appendText) {
return new EditOperationResult(new ReplaceCommandWithOffsetCursorState(cursor.selection, ch + electricAction.appendText, 0, -electricAction.appendText.length), {
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: true
});
}
if (electricAction.matchOpenBracket) {
let match = model.findMatchingBracketUp(electricAction.matchOpenBracket, {
lineNumber: position.lineNumber,
column: position.column
});
if (match) {
let matchLine = model.getLineContent(match.startLineNumber);
let matchLineIndentation = strings.getLeadingWhitespace(matchLine);
let newIndentation = config.normalizeIndentation(matchLineIndentation);
let lineText = model.getLineContent(position.lineNumber);
let lineFirstNonBlankColumn = model.getLineFirstNonWhitespaceColumn(position.lineNumber) || position.column;
let prefix = lineText.substring(lineFirstNonBlankColumn - 1, position.column - 1);
let typeText = newIndentation + prefix + ch;
let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column);
return new EditOperationResult(new ReplaceCommand(typeSelection, typeText), {
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: true
});
}
}
return null;
}
public static typeWithInterceptors(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
let r: EditOperationResult = null;
r = r || this._typeInterceptorEnter(config, model, cursor, ch);
r = r || this._typeInterceptorAutoClosingCloseChar(config, model, cursor, ch);
r = r || this._typeInterceptorAutoClosingOpenChar(config, model, cursor, ch);
r = r || this._typeInterceptorSurroundSelection(config, model, cursor, ch);
r = r || this._typeInterceptorElectricChar(config, model, cursor, ch);
r = r || this.typeWithoutInterceptors(config, model, cursor, ch);
return r;
}
public static typeWithoutInterceptors(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState, str: string): EditOperationResult {
return new EditOperationResult(TypeOperations.typeCommand(cursor.selection, str, false));
}
public static lineInsertBefore(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState): EditOperationResult {
let lineNumber = cursor.position.lineNumber;
if (lineNumber === 1) {
return new EditOperationResult(new ReplaceCommandWithoutChangingPosition(new Range(1, 1, 1, 1), '\n'));
}
lineNumber--;
let column = model.getLineMaxColumn(lineNumber);
return this._enter(config, model, false, new Range(lineNumber, column, lineNumber, column));
}
public static lineInsertAfter(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState): EditOperationResult {
let position = cursor.position;
let column = model.getLineMaxColumn(position.lineNumber);
return this._enter(config, model, false, new Range(position.lineNumber, column, position.lineNumber, column));
}
public static lineBreakInsert(config: CursorConfiguration, model: ITokenizedModel, cursor: CursorModelState): EditOperationResult {
return this._enter(config, model, true, cursor.selection);
}
}
......@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { EditOperationResult, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { Position } from 'vs/editor/common/core/position';
import { CharCode } from 'vs/base/common/charCode';
import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier';
import { MoveOperationResult } from 'vs/editor/common/controller/cursorMoveOperations';
import { CursorChangeReason } from 'vs/editor/common/editorCommon';
import { CursorModelState } from 'vs/editor/common/controller/oneCursor';
import { DeleteOperations, EditOperationResult } from 'vs/editor/common/controller/cursorDeleteOperations';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import * as strings from 'vs/base/common/strings';
import { Range } from 'vs/editor/common/core/range';
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
......
......@@ -4,24 +4,18 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError, illegalArgument } from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import { ReplaceCommand, ReplaceCommandWithOffsetCursorState, ReplaceCommandWithoutChangingPosition } from 'vs/editor/common/commands/replaceCommand';
import { SurroundSelectionCommand } from 'vs/editor/common/commands/surroundSelectionCommand';
import { illegalArgument } from 'vs/base/common/errors';
import { CursorMoveHelper, IColumnSelectResult } from 'vs/editor/common/controller/cursorMoveHelper';
import { CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { EditOperationResult, CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection, SelectionDirection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { CharCode } from 'vs/base/common/charCode';
import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { IDisposable } from 'vs/base/common/lifecycle';
import { MoveOperations, MoveOperationResult } from 'vs/editor/common/controller/cursorMoveOperations';
import { WordType, WordOperations, WordNavigationType } from 'vs/editor/common/controller/cursorWordOperations';
import { ColumnSelection } from 'vs/editor/common/controller/cursorColumnSelection';
import { DeleteOperations, EditOperationResult } from 'vs/editor/common/controller/cursorDeleteOperations';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
export interface IOneCursorOperationContext {
......@@ -1218,235 +1212,39 @@ export class OneCursorOp {
public static lineInsertBefore(cursor: OneCursor, ctx: IOneCursorOperationContext): boolean {
let lineNumber = cursor.modelState.position.lineNumber;
if (lineNumber === 1) {
ctx.executeCommand = new ReplaceCommandWithoutChangingPosition(new Range(1, 1, 1, 1), '\n');
return true;
}
lineNumber--;
let column = cursor.model.getLineMaxColumn(lineNumber);
return this._applyEditOperation(
ctx,
TypeOperations.lineInsertBefore(cursor.config, cursor.model, cursor.modelState)
);
return this._enter(cursor, false, ctx, new Range(lineNumber, column, lineNumber, column));
}
public static lineInsertAfter(cursor: OneCursor, ctx: IOneCursorOperationContext): boolean {
let position = cursor.modelState.position;
let column = cursor.model.getLineMaxColumn(position.lineNumber);
return this._enter(cursor, false, ctx, new Range(position.lineNumber, column, position.lineNumber, column));
return this._applyEditOperation(
ctx,
TypeOperations.lineInsertAfter(cursor.config, cursor.model, cursor.modelState)
);
}
public static lineBreakInsert(cursor: OneCursor, ctx: IOneCursorOperationContext): boolean {
return this._enter(cursor, true, ctx, cursor.modelState.selection);
}
private static _enter(cursor: OneCursor, keepPosition: boolean, ctx: IOneCursorOperationContext, range: Range): boolean {
return this._applyEditOperation(
ctx,
TypeOperations._enter(cursor.config, cursor.model, keepPosition, range)
TypeOperations.lineBreakInsert(cursor.config, cursor.model, cursor.modelState)
);
}
private static _typeInterceptorEnter(config: CursorConfiguration, model: editorCommon.ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (ch !== '\n') {
return null;
}
return TypeOperations._enter(config, model, false, cursor.selection);
}
private static _typeInterceptorAutoClosingCloseChar(config: CursorConfiguration, model: editorCommon.ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (!selection.isEmpty() || !config.autoClosingPairsClose.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineText = model.getLineContent(position.lineNumber);
let beforeCharacter = lineText.charAt(position.column - 1);
if (beforeCharacter !== ch) {
return null;
}
let typeSelection = new Range(position.lineNumber, position.column, position.lineNumber, position.column + 1);
return new EditOperationResult(new ReplaceCommand(typeSelection, ch));
}
private static _typeInterceptorAutoClosingOpenChar(config: CursorConfiguration, model: editorCommon.ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (!selection.isEmpty() || !config.autoClosingPairsOpen.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineText = model.getLineContent(position.lineNumber);
let beforeCharacter = lineText.charAt(position.column - 1);
// Only consider auto closing the pair if a space follows or if another autoclosed pair follows
if (beforeCharacter) {
let isBeforeCloseBrace = false;
for (let closeBrace in config.autoClosingPairsClose) {
if (beforeCharacter === closeBrace) {
isBeforeCloseBrace = true;
break;
}
}
if (!isBeforeCloseBrace && !/\s/.test(beforeCharacter)) {
return null;
}
}
let lineTokens = model.getLineTokens(position.lineNumber, false);
let shouldAutoClosePair = false;
try {
shouldAutoClosePair = LanguageConfigurationRegistry.shouldAutoClosePair(ch, lineTokens, position.column);
} catch (e) {
onUnexpectedError(e);
}
if (!shouldAutoClosePair) {
return null;
}
let closeCharacter = config.autoClosingPairsOpen[ch];
return new EditOperationResult(new ReplaceCommandWithOffsetCursorState(selection, ch + closeCharacter, 0, -closeCharacter.length), {
shouldPushStackElementBefore: true,
shouldPushStackElementAfter: false
});
}
private static _typeInterceptorSurroundSelection(config: CursorConfiguration, model: editorCommon.ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.autoClosingBrackets) {
return null;
}
let selection = cursor.selection;
if (selection.isEmpty() || !config.surroundingPairs.hasOwnProperty(ch)) {
return null;
}
let selectionContainsOnlyWhitespace = true;
for (let lineNumber = selection.startLineNumber; lineNumber <= selection.endLineNumber; lineNumber++) {
let lineText = model.getLineContent(lineNumber);
let startIndex = (lineNumber === selection.startLineNumber ? selection.startColumn - 1 : 0);
let endIndex = (lineNumber === selection.endLineNumber ? selection.endColumn - 1 : lineText.length);
for (let charIndex = startIndex; charIndex < endIndex; charIndex++) {
let charCode = lineText.charCodeAt(charIndex);
if (charCode !== CharCode.Tab && charCode !== CharCode.Space) {
selectionContainsOnlyWhitespace = false;
// Break outer loop
lineNumber = selection.endLineNumber + 1;
// Break inner loop
charIndex = endIndex;
}
}
}
if (selectionContainsOnlyWhitespace) {
return null;
}
let closeCharacter = config.surroundingPairs[ch];
return new EditOperationResult(new SurroundSelectionCommand(selection, ch, closeCharacter), {
shouldPushStackElementBefore: true,
shouldPushStackElementAfter: true
});
}
private static _typeInterceptorElectricChar(config: CursorConfiguration, model: editorCommon.ITokenizedModel, cursor: CursorModelState, ch: string): EditOperationResult {
if (!config.electricChars.hasOwnProperty(ch)) {
return null;
}
let position = cursor.position;
let lineTokens = model.getLineTokens(position.lineNumber, false);
let electricAction: IElectricAction;
try {
electricAction = LanguageConfigurationRegistry.onElectricCharacter(ch, lineTokens, position.column);
} catch (e) {
onUnexpectedError(e);
}
if (!electricAction) {
return null;
}
if (electricAction.appendText) {
return new EditOperationResult(new ReplaceCommandWithOffsetCursorState(cursor.selection, ch + electricAction.appendText, 0, -electricAction.appendText.length), {
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: true
});
}
if (electricAction.matchOpenBracket) {
let match = model.findMatchingBracketUp(electricAction.matchOpenBracket, {
lineNumber: position.lineNumber,
column: position.column
});
if (match) {
let matchLine = model.getLineContent(match.startLineNumber);
let matchLineIndentation = strings.getLeadingWhitespace(matchLine);
let newIndentation = config.normalizeIndentation(matchLineIndentation);
let lineText = model.getLineContent(position.lineNumber);
let lineFirstNonBlankColumn = model.getLineFirstNonWhitespaceColumn(position.lineNumber) || position.column;
let prefix = lineText.substring(lineFirstNonBlankColumn - 1, position.column - 1);
let typeText = newIndentation + prefix + ch;
let typeSelection = new Range(position.lineNumber, 1, position.lineNumber, position.column);
return new EditOperationResult(new ReplaceCommand(typeSelection, typeText), {
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: true
});
}
}
return null;
}
public static actualType(cursor: OneCursor, text: string, keepPosition: boolean, ctx: IOneCursorOperationContext): boolean {
ctx.executeCommand = TypeOperations.typeCommand(cursor.modelState.selection, text, keepPosition);
return true;
public static actualType(cursor: OneCursor, text: string, ctx: IOneCursorOperationContext): boolean {
return this._applyEditOperation(
ctx,
TypeOperations.typeWithoutInterceptors(cursor.config, cursor.model, cursor.modelState, text)
);
}
public static type(cursor: OneCursor, ch: string, ctx: IOneCursorOperationContext): boolean {
let r: EditOperationResult = null;
r = r || this._typeInterceptorEnter(cursor.config, cursor.model, cursor.modelState, ch);
r = r || this._typeInterceptorAutoClosingCloseChar(cursor.config, cursor.model, cursor.modelState, ch);
r = r || this._typeInterceptorAutoClosingOpenChar(cursor.config, cursor.model, cursor.modelState, ch);
r = r || this._typeInterceptorSurroundSelection(cursor.config, cursor.model, cursor.modelState, ch);
r = r || this._typeInterceptorElectricChar(cursor.config, cursor.model, cursor.modelState, ch);
if (r) {
return this._applyEditOperation(ctx, r);
}
ctx.executeCommand = TypeOperations.typeCommand(cursor.modelState.selection, ch, false);
return true;
return this._applyEditOperation(
ctx,
TypeOperations.typeWithInterceptors(cursor.config, cursor.model, cursor.modelState, ch)
);
}
public static replacePreviousChar(cursor: OneCursor, txt: string, replaceCharCnt: number, ctx: IOneCursorOperationContext): boolean {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册