未验证 提交 b4702d56 编写于 作者: A Alex Dima

Adopt EditorAutoIndentStrategy

上级 e625e615
......@@ -11,6 +11,7 @@ import { Selection, SelectionDirection } from 'vs/editor/common/core/selection';
import { ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
export interface IShiftCommandOpts {
isUnshift: boolean;
......@@ -18,6 +19,7 @@ export interface IShiftCommandOpts {
indentSize: number;
insertSpaces: boolean;
useTabStops: boolean;
autoIndent: EditorAutoIndentStrategy;
}
const repeatCache: { [str: string]: string[]; } = Object.create(null);
......@@ -137,7 +139,7 @@ export class ShiftCommand implements ICommand {
// The current line is "miss-aligned", so let's see if this is expected...
// This can only happen when it has trailing commas in the indent
if (model.isCheapToTokenize(lineNumber - 1)) {
let enterAction = LanguageConfigurationRegistry.getRawEnterActionAtPosition(model, lineNumber - 1, model.getLineMaxColumn(lineNumber - 1));
let enterAction = LanguageConfigurationRegistry.getRawEnterActionAtPosition(this._opts.autoIndent, model, lineNumber - 1, model.getLineMaxColumn(lineNumber - 1));
if (enterAction) {
extraSpaces = previousLineExtraSpaces;
if (enterAction.appendText) {
......
......@@ -103,7 +103,7 @@ export class CursorConfiguration {
public readonly autoClosingQuotes: EditorAutoClosingStrategy;
public readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
public readonly autoSurround: EditorAutoSurroundStrategy;
public readonly autoIndent2: EditorAutoIndentStrategy;
public readonly autoIndent: EditorAutoIndentStrategy;
public readonly autoClosingPairsOpen2: Map<string, StandardAutoClosingPairConditional[]>;
public readonly autoClosingPairsClose2: Map<string, StandardAutoClosingPairConditional[]>;
public readonly surroundingPairs: CharacterMap;
......@@ -155,7 +155,7 @@ export class CursorConfiguration {
this.autoClosingQuotes = options.get(EditorOption.autoClosingQuotes);
this.autoClosingOvertype = options.get(EditorOption.autoClosingOvertype);
this.autoSurround = options.get(EditorOption.autoSurround);
this.autoIndent2 = options.get(EditorOption.autoIndent);
this.autoIndent = options.get(EditorOption.autoIndent);
this.autoClosingPairsOpen2 = new Map<string, StandardAutoClosingPairConditional[]>();
this.autoClosingPairsClose2 = new Map<string, StandardAutoClosingPairConditional[]>();
......
......@@ -35,7 +35,8 @@ export class TypeOperations {
tabSize: config.tabSize,
indentSize: config.indentSize,
insertSpaces: config.insertSpaces,
useTabStops: config.useTabStops
useTabStops: config.useTabStops,
autoIndent: config.autoIndent
});
}
return commands;
......@@ -49,7 +50,8 @@ export class TypeOperations {
tabSize: config.tabSize,
indentSize: config.indentSize,
insertSpaces: config.insertSpaces,
useTabStops: config.useTabStops
useTabStops: config.useTabStops,
autoIndent: config.autoIndent
});
}
return commands;
......@@ -150,15 +152,15 @@ export class TypeOperations {
let action: IndentAction | EnterAction | null = null;
let indentation: string = '';
let expectedIndentAction = config.autoIndent ? LanguageConfigurationRegistry.getInheritIndentForLine(model, lineNumber, false) : null;
const expectedIndentAction = LanguageConfigurationRegistry.getInheritIndentForLine(config.autoIndent, model, lineNumber, false);
if (expectedIndentAction) {
action = expectedIndentAction.action;
indentation = expectedIndentAction.indentation;
} else if (lineNumber > 1) {
let lastLineNumber: number;
for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {
let lineText = model.getLineContent(lastLineNumber);
let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText);
const lineText = model.getLineContent(lastLineNumber);
const nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText);
if (nonWhitespaceIdx >= 0) {
break;
}
......@@ -169,8 +171,8 @@ export class TypeOperations {
return null;
}
let maxColumn = model.getLineMaxColumn(lastLineNumber);
let expectedEnterAction = LanguageConfigurationRegistry.getEnterAction(model, new Range(lastLineNumber, maxColumn, lastLineNumber, maxColumn));
const maxColumn = model.getLineMaxColumn(lastLineNumber);
const expectedEnterAction = LanguageConfigurationRegistry.getEnterAction(config.autoIndent, model, new Range(lastLineNumber, maxColumn, lastLineNumber, maxColumn));
if (expectedEnterAction) {
indentation = expectedEnterAction.indentation;
action = expectedEnterAction.enterAction;
......@@ -252,7 +254,8 @@ export class TypeOperations {
tabSize: config.tabSize,
indentSize: config.indentSize,
insertSpaces: config.insertSpaces,
useTabStops: config.useTabStops
useTabStops: config.useTabStops,
autoIndent: config.autoIndent
});
}
}
......@@ -290,21 +293,19 @@ export class TypeOperations {
}
private static _enter(config: CursorConfiguration, model: ITextModel, keepPosition: boolean, range: Range): ICommand {
if (config.autoIndent2 === EditorAutoIndentStrategy.None) {
if (config.autoIndent === EditorAutoIndentStrategy.None) {
return TypeOperations._typeCommand(range, '\n', keepPosition);
}
if (!model.isCheapToTokenize(range.getStartPosition().lineNumber) || config.autoIndent2 === EditorAutoIndentStrategy.Keep) {
if (!model.isCheapToTokenize(range.getStartPosition().lineNumber) || config.autoIndent === EditorAutoIndentStrategy.Keep) {
let lineText = model.getLineContent(range.startLineNumber);
let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
}
const autoIndent = config.autoIndent2;
let r = LanguageConfigurationRegistry.getEnterAction(model, range);
const r = LanguageConfigurationRegistry.getEnterAction(config.autoIndent, model, range);
if (r) {
let enterAction = r.enterAction;
let indentation = r.indentation;
const enterAction = r.enterAction;
const indentation = r.indentation;
if (enterAction.indentAction === IndentAction.None) {
// Nothing special
......@@ -316,10 +317,10 @@ export class TypeOperations {
} else if (enterAction.indentAction === IndentAction.IndentOutdent) {
// Ultra special
let normalIndent = config.normalizeIndentation(indentation);
let increasedIndent = config.normalizeIndentation(indentation + enterAction.appendText);
const normalIndent = config.normalizeIndentation(indentation);
const increasedIndent = config.normalizeIndentation(indentation + enterAction.appendText);
let typeText = '\n' + increasedIndent + '\n' + normalIndent;
const typeText = '\n' + increasedIndent + '\n' + normalIndent;
if (keepPosition) {
return new ReplaceCommandWithoutChangingPosition(range, typeText, true);
......@@ -327,72 +328,65 @@ export class TypeOperations {
return new ReplaceCommandWithOffsetCursorState(range, typeText, -1, increasedIndent.length - normalIndent.length, true);
}
} else if (enterAction.indentAction === IndentAction.Outdent) {
let actualIndentation = TypeOperations.unshiftIndent(config, indentation);
const actualIndentation = TypeOperations.unshiftIndent(config, indentation);
return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(actualIndentation + enterAction.appendText), keepPosition);
}
}
// no enter rules applied, we should check indentation rules then.
if (!config.autoIndent) {
// Nothing special
let lineText = model.getLineContent(range.startLineNumber);
let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
}
let ir = LanguageConfigurationRegistry.getIndentForEnter(model, range, {
unshiftIndent: (indent) => {
return TypeOperations.unshiftIndent(config, indent);
},
shiftIndent: (indent) => {
return TypeOperations.shiftIndent(config, indent);
},
normalizeIndentation: (indent) => {
return config.normalizeIndentation(indent);
}
}, config.autoIndent);
const lineText = model.getLineContent(range.startLineNumber);
const indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
let lineText = model.getLineContent(range.startLineNumber);
let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
if (config.autoIndent >= EditorAutoIndentStrategy.Full) {
const ir = LanguageConfigurationRegistry.getIndentForEnter(config.autoIndent, model, range, {
unshiftIndent: (indent) => {
return TypeOperations.unshiftIndent(config, indent);
},
shiftIndent: (indent) => {
return TypeOperations.shiftIndent(config, indent);
},
normalizeIndentation: (indent) => {
return config.normalizeIndentation(indent);
}
});
if (ir) {
let oldEndViewColumn = CursorColumns.visibleColumnFromColumn2(config, model, range.getEndPosition());
let oldEndColumn = range.endColumn;
if (ir) {
let oldEndViewColumn = CursorColumns.visibleColumnFromColumn2(config, model, range.getEndPosition());
const oldEndColumn = range.endColumn;
let beforeText = '\n';
if (indentation !== config.normalizeIndentation(ir.beforeEnter)) {
beforeText = config.normalizeIndentation(ir.beforeEnter) + lineText.substring(indentation.length, range.startColumn - 1) + '\n';
range = new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn);
}
let beforeText = '\n';
if (indentation !== config.normalizeIndentation(ir.beforeEnter)) {
beforeText = config.normalizeIndentation(ir.beforeEnter) + lineText.substring(indentation.length, range.startColumn - 1) + '\n';
range = new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn);
}
let newLineContent = model.getLineContent(range.endLineNumber);
let firstNonWhitespace = strings.firstNonWhitespaceIndex(newLineContent);
if (firstNonWhitespace >= 0) {
range = range.setEndPosition(range.endLineNumber, Math.max(range.endColumn, firstNonWhitespace + 1));
} else {
range = range.setEndPosition(range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
}
const newLineContent = model.getLineContent(range.endLineNumber);
const firstNonWhitespace = strings.firstNonWhitespaceIndex(newLineContent);
if (firstNonWhitespace >= 0) {
range = range.setEndPosition(range.endLineNumber, Math.max(range.endColumn, firstNonWhitespace + 1));
} else {
range = range.setEndPosition(range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
}
if (keepPosition) {
return new ReplaceCommandWithoutChangingPosition(range, beforeText + config.normalizeIndentation(ir.afterEnter), true);
} else {
let offset = 0;
if (oldEndColumn <= firstNonWhitespace + 1) {
if (!config.insertSpaces) {
oldEndViewColumn = Math.ceil(oldEndViewColumn / config.indentSize);
if (keepPosition) {
return new ReplaceCommandWithoutChangingPosition(range, beforeText + config.normalizeIndentation(ir.afterEnter), true);
} else {
let offset = 0;
if (oldEndColumn <= firstNonWhitespace + 1) {
if (!config.insertSpaces) {
oldEndViewColumn = Math.ceil(oldEndViewColumn / config.indentSize);
}
offset = Math.min(oldEndViewColumn + 1 - config.normalizeIndentation(ir.afterEnter).length - 1, 0);
}
offset = Math.min(oldEndViewColumn + 1 - config.normalizeIndentation(ir.afterEnter).length - 1, 0);
return new ReplaceCommandWithOffsetCursorState(range, beforeText + config.normalizeIndentation(ir.afterEnter), 0, offset, true);
}
return new ReplaceCommandWithOffsetCursorState(range, beforeText + config.normalizeIndentation(ir.afterEnter), 0, offset, true);
}
} else {
return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
}
return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
}
private static _isAutoIndentType(config: CursorConfiguration, model: ITextModel, selections: Selection[]): boolean {
if (!config.autoIndent) {
if (config.autoIndent < EditorAutoIndentStrategy.Full) {
return false;
}
......@@ -406,8 +400,8 @@ export class TypeOperations {
}
private static _runAutoIndentType(config: CursorConfiguration, model: ITextModel, range: Range, ch: string): ICommand | null {
let currentIndentation = LanguageConfigurationRegistry.getIndentationAtPosition(model, range.startLineNumber, range.startColumn);
let actualIndentation = LanguageConfigurationRegistry.getIndentActionForType(model, range, ch, {
const currentIndentation = LanguageConfigurationRegistry.getIndentationAtPosition(model, range.startLineNumber, range.startColumn);
const actualIndentation = LanguageConfigurationRegistry.getIndentActionForType(config.autoIndent, model, range, ch, {
shiftIndent: (indentation) => {
return TypeOperations.shiftIndent(config, indentation);
},
......@@ -421,7 +415,7 @@ export class TypeOperations {
}
if (actualIndentation !== config.normalizeIndentation(currentIndentation)) {
let firstNonWhitespace = model.getLineFirstNonWhitespaceColumn(range.startLineNumber);
const firstNonWhitespace = model.getLineFirstNonWhitespaceColumn(range.startLineNumber);
if (firstNonWhitespace === 0) {
return TypeOperations._typeCommand(
new Range(range.startLineNumber, 0, range.endLineNumber, range.endColumn),
......
......@@ -13,7 +13,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes';
import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration';
import { createScopedLineTokens } from 'vs/editor/common/modes/supports';
import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports';
import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair';
import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { IndentConsts, IndentRulesSupport } from 'vs/editor/common/modes/supports/indentRules';
......@@ -352,8 +352,12 @@ export class LanguageConfigurationRegistryImpl {
*
* This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not.
*/
public getInheritIndentForLine(model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null {
let indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id);
public getInheritIndentForLine(autoIndent: EditorAutoIndentStrategy, model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
}
const indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id);
if (!indentRulesSupport) {
return null;
}
......@@ -365,7 +369,7 @@ export class LanguageConfigurationRegistryImpl {
};
}
let precedingUnIgnoredLine = this.getPrecedingValidLine(model, lineNumber, indentRulesSupport);
const precedingUnIgnoredLine = this.getPrecedingValidLine(model, lineNumber, indentRulesSupport);
if (precedingUnIgnoredLine < 0) {
return null;
} else if (precedingUnIgnoredLine < 1) {
......@@ -375,8 +379,7 @@ export class LanguageConfigurationRegistryImpl {
};
}
let precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine);
const precedingUnIgnoredLineContent = model.getLineContent(precedingUnIgnoredLine);
if (indentRulesSupport.shouldIncrease(precedingUnIgnoredLineContent) || indentRulesSupport.shouldIndentNextLine(precedingUnIgnoredLineContent)) {
return {
indentation: strings.getLeadingWhitespace(precedingUnIgnoredLineContent),
......@@ -403,9 +406,9 @@ export class LanguageConfigurationRegistryImpl {
};
}
let previousLine = precedingUnIgnoredLine - 1;
const previousLine = precedingUnIgnoredLine - 1;
let previousLineIndentMetadata = indentRulesSupport.getIndentMetadata(model.getLineContent(previousLine));
const previousLineIndentMetadata = indentRulesSupport.getIndentMetadata(model.getLineContent(previousLine));
if (!(previousLineIndentMetadata & (IndentConsts.INCREASE_MASK | IndentConsts.DECREASE_MASK)) &&
(previousLineIndentMetadata & IndentConsts.INDENT_NEXTLINE_MASK)) {
let stopLine = 0;
......@@ -433,7 +436,7 @@ export class LanguageConfigurationRegistryImpl {
} else {
// search from precedingUnIgnoredLine until we find one whose indent is not temporary
for (let i = precedingUnIgnoredLine; i > 0; i--) {
let lineContent = model.getLineContent(i);
const lineContent = model.getLineContent(i);
if (indentRulesSupport.shouldIncrease(lineContent)) {
return {
indentation: strings.getLeadingWhitespace(lineContent),
......@@ -473,23 +476,27 @@ export class LanguageConfigurationRegistryImpl {
}
}
public getGoodIndentForLine(virtualModel: IVirtualModel, languageId: LanguageId, lineNumber: number, indentConverter: IIndentConverter): string | null {
let indentRulesSupport = this.getIndentRulesSupport(languageId);
public getGoodIndentForLine(autoIndent: EditorAutoIndentStrategy, virtualModel: IVirtualModel, languageId: LanguageId, lineNumber: number, indentConverter: IIndentConverter): string | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
}
const indentRulesSupport = this.getIndentRulesSupport(languageId);
if (!indentRulesSupport) {
return null;
}
let indent = this.getInheritIndentForLine(virtualModel, lineNumber);
let lineContent = virtualModel.getLineContent(lineNumber);
const indent = this.getInheritIndentForLine(autoIndent, virtualModel, lineNumber);
const lineContent = virtualModel.getLineContent(lineNumber);
if (indent) {
let inheritLine = indent.line;
const inheritLine = indent.line;
if (inheritLine !== undefined) {
let onEnterSupport = this._getOnEnterSupport(languageId);
const onEnterSupport = this._getOnEnterSupport(languageId);
let enterResult: EnterAction | null = null;
try {
if (onEnterSupport) {
enterResult = onEnterSupport.onEnter('', virtualModel.getLineContent(inheritLine), '');
enterResult = onEnterSupport.onEnter(autoIndent, '', virtualModel.getLineContent(inheritLine), '');
}
} catch (e) {
onUnexpectedError(e);
......@@ -540,16 +547,17 @@ export class LanguageConfigurationRegistryImpl {
return null;
}
public getIndentForEnter(autoIndent2: EditorAutoIndentStrategy, model: ITextModel, range: Range, indentConverter: IIndentConverter): { beforeEnter: string, afterEnter: string } | null {
public getIndentForEnter(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range, indentConverter: IIndentConverter): { beforeEnter: string, afterEnter: string } | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
}
model.forceTokenization(range.startLineNumber);
let lineTokens = model.getLineTokens(range.startLineNumber);
let beforeEnterText: string;
let afterEnterText: string;
let scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1);
let scopedLineText = scopedLineTokens.getLineContent();
const lineTokens = model.getLineTokens(range.startLineNumber);
const scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1);
const scopedLineText = scopedLineTokens.getLineContent();
let embeddedLanguage = false;
let beforeEnterText: string;
if (scopedLineTokens.firstCharOffset > 0 && lineTokens.getLanguageId(0) !== scopedLineTokens.languageId) {
// we are in the embeded language content
embeddedLanguage = true; // if embeddedLanguage is true, then we don't touch the indentation of current line
......@@ -558,6 +566,7 @@ export class LanguageConfigurationRegistryImpl {
beforeEnterText = lineTokens.getLineContent().substring(0, range.startColumn - 1);
}
let afterEnterText: string;
if (range.isEmpty()) {
afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);
} else {
......@@ -565,31 +574,15 @@ export class LanguageConfigurationRegistryImpl {
afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);
}
let indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);
const indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);
if (!indentRulesSupport) {
return null;
}
let beforeEnterResult = beforeEnterText;
let beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterText);
if (!autoIndent && !embeddedLanguage) {
let beforeEnterIndentAction = this.getInheritIndentForLine(model, range.startLineNumber);
if (indentRulesSupport.shouldDecrease(beforeEnterText)) {
if (beforeEnterIndentAction) {
beforeEnterIndent = beforeEnterIndentAction.indentation;
if (beforeEnterIndentAction.action !== IndentAction.Indent) {
beforeEnterIndent = indentConverter.unshiftIndent(beforeEnterIndent);
}
}
}
beforeEnterResult = beforeEnterIndent + strings.ltrim(strings.ltrim(beforeEnterText, ' '), '\t');
}
const beforeEnterResult = beforeEnterText;
const beforeEnterIndent = strings.getLeadingWhitespace(beforeEnterText);
let virtualModel: IVirtualModel = {
const virtualModel: IVirtualModel = {
getLineTokens: (lineNumber: number) => {
return model.getLineTokens(lineNumber);
},
......@@ -608,10 +601,10 @@ export class LanguageConfigurationRegistryImpl {
}
};
let currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
let afterEnterAction = this.getInheritIndentForLine(virtualModel, range.startLineNumber + 1);
const currentLineIndent = strings.getLeadingWhitespace(lineTokens.getLineContent());
const afterEnterAction = this.getInheritIndentForLine(autoIndent, virtualModel, range.startLineNumber + 1);
if (!afterEnterAction) {
let beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
const beforeEnter = embeddedLanguage ? currentLineIndent : beforeEnterIndent;
return {
beforeEnter: beforeEnter,
afterEnter: beforeEnter
......@@ -638,18 +631,21 @@ export class LanguageConfigurationRegistryImpl {
* We should always allow intentional indentation. It means, if users change the indentation of `lineNumber` and the content of
* this line doesn't match decreaseIndentPattern, we should not adjust the indentation.
*/
public getIndentActionForType(model: ITextModel, range: Range, ch: string, indentConverter: IIndentConverter): string | null {
let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);
let indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);
public getIndentActionForType(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range, ch: string, indentConverter: IIndentConverter): string | null {
if (autoIndent < EditorAutoIndentStrategy.Full) {
return null;
}
const scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);
const indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId);
if (!indentRulesSupport) {
return null;
}
let scopedLineText = scopedLineTokens.getLineContent();
let beforeTypeText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);
let afterTypeText;
const scopedLineText = scopedLineTokens.getLineContent();
const beforeTypeText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);
// selection support
let afterTypeText: string;
if (range.isEmpty()) {
afterTypeText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);
} else {
......@@ -662,13 +658,12 @@ export class LanguageConfigurationRegistryImpl {
if (!indentRulesSupport.shouldDecrease(beforeTypeText + afterTypeText) && indentRulesSupport.shouldDecrease(beforeTypeText + ch + afterTypeText)) {
// after typing `ch`, the content matches decreaseIndentPattern, we should adjust the indent to a good manner.
// 1. Get inherited indent action
let r = this.getInheritIndentForLine(model, range.startLineNumber, false);
const r = this.getInheritIndentForLine(autoIndent, model, range.startLineNumber, false);
if (!r) {
return null;
}
let indentation = r.indentation;
if (r.action !== IndentAction.Indent) {
indentation = indentConverter.unshiftIndent(indentation);
}
......@@ -680,15 +675,13 @@ export class LanguageConfigurationRegistryImpl {
}
public getIndentMetadata(model: ITextModel, lineNumber: number): number | null {
let indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id);
const indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id);
if (!indentRulesSupport) {
return null;
}
if (lineNumber < 1 || lineNumber > model.getLineCount()) {
return null;
}
return indentRulesSupport.getIndentMetadata(model.getLineContent(lineNumber));
}
......@@ -697,21 +690,19 @@ export class LanguageConfigurationRegistryImpl {
// begin onEnter
private _getOnEnterSupport(languageId: LanguageId): OnEnterSupport | null {
let value = this._getRichEditSupport(languageId);
const value = this._getRichEditSupport(languageId);
if (!value) {
return null;
}
return value.onEnter || null;
}
public getRawEnterActionAtPosition(model: ITextModel, lineNumber: number, column: number): EnterAction | null {
let r = this.getEnterAction(model, new Range(lineNumber, column, lineNumber, column));
public getRawEnterActionAtPosition(autoIndent: EditorAutoIndentStrategy, model: ITextModel, lineNumber: number, column: number): EnterAction | null {
const r = this.getEnterAction(autoIndent, model, new Range(lineNumber, column, lineNumber, column));
return r ? r.enterAction : null;
}
public getEnterAction(autoIndent: EditorAutoIndentStrategy.Brackets | EditorAutoIndentStrategy.Advanced | EditorAutoIndentStrategy.Full, model: ITextModel, range: Range): { enterAction: EnterAction; indentation: string; } | null {
let indentation = this.getIndentationAtPosition(model, range.startLineNumber, range.startColumn);
public getEnterAction(autoIndent: EditorAutoIndentStrategy, model: ITextModel, range: Range): { enterAction: EnterAction; indentation: string; } | null {
const scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);
const onEnterSupport = this._getOnEnterSupport(scopedLineTokens.languageId);
if (!onEnterSupport) {
......@@ -763,6 +754,7 @@ export class LanguageConfigurationRegistryImpl {
}
}
let indentation = this.getIndentationAtPosition(model, range.startLineNumber, range.startColumn);
if (enterResult.removeText) {
indentation = indentation.substring(0, indentation.length - enterResult.removeText);
}
......@@ -774,27 +766,25 @@ export class LanguageConfigurationRegistryImpl {
}
public getIndentationAtPosition(model: ITextModel, lineNumber: number, column: number): string {
let lineText = model.getLineContent(lineNumber);
const lineText = model.getLineContent(lineNumber);
let indentation = strings.getLeadingWhitespace(lineText);
if (indentation.length > column - 1) {
indentation = indentation.substring(0, column - 1);
}
return indentation;
}
private getScopedLineTokens(model: ITextModel, lineNumber: number, columnNumber?: number) {
private getScopedLineTokens(model: ITextModel, lineNumber: number, columnNumber?: number): ScopedLineTokens {
model.forceTokenization(lineNumber);
let lineTokens = model.getLineTokens(lineNumber);
let column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1);
let scopedLineTokens = createScopedLineTokens(lineTokens, column);
return scopedLineTokens;
const lineTokens = model.getLineTokens(lineNumber);
const column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1);
return createScopedLineTokens(lineTokens, column);
}
// end onEnter
public getBracketsSupport(languageId: LanguageId): RichEditBrackets | null {
let value = this._getRichEditSupport(languageId);
const value = this._getRichEditSupport(languageId);
if (!value) {
return null;
}
......
......@@ -470,6 +470,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
if (!model.isCheapToTokenize(range.getStartPosition().lineNumber)) {
return;
}
const autoIndent = this.editor.getOption(EditorOption.autoIndent);
const { tabSize, indentSize, insertSpaces } = model.getOptions();
this.editor.pushUndoStop();
let textEdits: TextEdit[] = [];
......@@ -499,7 +500,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
let firstLineText = model.getLineContent(startLineNumber);
if (!/\S/.test(firstLineText.substring(0, range.startColumn - 1))) {
let indentOfFirstLine = LanguageConfigurationRegistry.getGoodIndentForLine(model, model.getLanguageIdentifier().id, startLineNumber, indentConverter);
let indentOfFirstLine = LanguageConfigurationRegistry.getGoodIndentForLine(autoIndent, model, model.getLanguageIdentifier().id, startLineNumber, indentConverter);
if (indentOfFirstLine !== null) {
let oldIndentation = strings.getLeadingWhitespace(firstLineText);
......@@ -557,7 +558,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
}
}
};
let indentOfSecondLine = LanguageConfigurationRegistry.getGoodIndentForLine(virtualModel, model.getLanguageIdentifier().id, startLineNumber + 1, indentConverter);
let indentOfSecondLine = LanguageConfigurationRegistry.getGoodIndentForLine(autoIndent, virtualModel, model.getLanguageIdentifier().id, startLineNumber + 1, indentConverter);
if (indentOfSecondLine !== null) {
let newSpaceCntOfSecondLine = indentUtils.getSpaceCnt(indentOfSecondLine, tabSize);
let oldSpaceCntOfSecondLine = indentUtils.getSpaceCnt(strings.getLeadingWhitespace(model.getLineContent(startLineNumber + 1)), tabSize);
......
......@@ -118,7 +118,7 @@ export class MoveLinesCommand implements ICommand {
return model.getLineContent(lineNumber);
}
};
let indentOfMovingLine = LanguageConfigurationRegistry.getGoodIndentForLine(virtualModel, model.getLanguageIdAtPosition(
let indentOfMovingLine = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(
movingLineNumber, 1), s.startLineNumber, indentConverter);
if (indentOfMovingLine !== null) {
let oldIndentation = strings.getLeadingWhitespace(model.getLineContent(movingLineNumber));
......@@ -153,7 +153,7 @@ export class MoveLinesCommand implements ICommand {
}
};
let newIndentatOfMovingBlock = LanguageConfigurationRegistry.getGoodIndentForLine(virtualModel, model.getLanguageIdAtPosition(
let newIndentatOfMovingBlock = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(
movingLineNumber, 1), s.startLineNumber + 1, indentConverter);
if (newIndentatOfMovingBlock !== null) {
......@@ -198,7 +198,7 @@ export class MoveLinesCommand implements ICommand {
}
} else {
// it doesn't match any onEnter rule, let's check indentation rules then.
let indentOfFirstLine = LanguageConfigurationRegistry.getGoodIndentForLine(virtualModel, model.getLanguageIdAtPosition(s.startLineNumber, 1), movingLineNumber, indentConverter);
let indentOfFirstLine = LanguageConfigurationRegistry.getGoodIndentForLine(this._autoIndent, virtualModel, model.getLanguageIdAtPosition(s.startLineNumber, 1), movingLineNumber, indentConverter);
if (indentOfFirstLine !== null) {
// adjust the indentation of the moving block
let oldIndent = strings.getLeadingWhitespace(model.getLineContent(s.startLineNumber));
......@@ -252,7 +252,7 @@ export class MoveLinesCommand implements ICommand {
}
let maxColumn = model.getLineMaxColumn(validPrecedingLine);
let enter = LanguageConfigurationRegistry.getEnterAction(model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));
let enter = LanguageConfigurationRegistry.getEnterAction(this._autoIndent, model, new Range(validPrecedingLine, maxColumn, validPrecedingLine, maxColumn));
if (enter) {
let enterPrefix = enter.indentation;
......
......@@ -9,21 +9,22 @@ import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageCo
import { MoveLinesCommand } from 'vs/editor/contrib/linesOperations/moveLinesCommand';
import { testCommand } from 'vs/editor/test/browser/testCommand';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
function testMoveLinesDownCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
testCommand(lines, null, selection, (sel) => new MoveLinesCommand(sel, true, false), expectedLines, expectedSelection);
testCommand(lines, null, selection, (sel) => new MoveLinesCommand(sel, true, EditorAutoIndentStrategy.Advanced), expectedLines, expectedSelection);
}
function testMoveLinesUpCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
testCommand(lines, null, selection, (sel) => new MoveLinesCommand(sel, false, false), expectedLines, expectedSelection);
testCommand(lines, null, selection, (sel) => new MoveLinesCommand(sel, false, EditorAutoIndentStrategy.Advanced), expectedLines, expectedSelection);
}
function testMoveLinesDownWithIndentCommand(languageId: LanguageIdentifier, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
testCommand(lines, languageId, selection, (sel) => new MoveLinesCommand(sel, true, true), expectedLines, expectedSelection);
testCommand(lines, languageId, selection, (sel) => new MoveLinesCommand(sel, true, EditorAutoIndentStrategy.Full), expectedLines, expectedSelection);
}
function testMoveLinesUpWithIndentCommand(languageId: LanguageIdentifier, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
testCommand(lines, languageId, selection, (sel) => new MoveLinesCommand(sel, false, true), expectedLines, expectedSelection);
testCommand(lines, languageId, selection, (sel) => new MoveLinesCommand(sel, false, EditorAutoIndentStrategy.Full), expectedLines, expectedSelection);
}
suite('Editor Contrib - Move Lines Command', () => {
......
......@@ -14,6 +14,7 @@ import { getEditOperation, testCommand } from 'vs/editor/test/browser/testComman
import { withEditorModel } from 'vs/editor/test/common/editorTestUtils';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
/**
* Create single edit operation
......@@ -50,6 +51,7 @@ function testShiftCommand(lines: string[], languageIdentifier: LanguageIdentifie
indentSize: 4,
insertSpaces: false,
useTabStops: useTabStops,
autoIndent: EditorAutoIndentStrategy.Full,
}), expectedLines, expectedSelection);
}
......@@ -60,6 +62,7 @@ function testUnshiftCommand(lines: string[], languageIdentifier: LanguageIdentif
indentSize: 4,
insertSpaces: false,
useTabStops: useTabStops,
autoIndent: EditorAutoIndentStrategy.Full,
}), expectedLines, expectedSelection);
}
......@@ -672,7 +675,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
useTabStops: false
useTabStops: false,
autoIndent: EditorAutoIndentStrategy.Full,
}),
[
' Written | Numeric',
......@@ -717,7 +721,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
useTabStops: false
useTabStops: false,
autoIndent: EditorAutoIndentStrategy.Full,
}),
[
' Written | Numeric',
......@@ -762,7 +767,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
useTabStops: false
useTabStops: false,
autoIndent: EditorAutoIndentStrategy.Full,
}),
[
' Written | Numeric',
......@@ -807,7 +813,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
useTabStops: false
useTabStops: false,
autoIndent: EditorAutoIndentStrategy.Full,
}),
[
' Written | Numeric',
......@@ -841,7 +848,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
useTabStops: true
useTabStops: true,
autoIndent: EditorAutoIndentStrategy.Full,
}),
[
'\tHello world!',
......@@ -951,7 +959,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: tabSize,
indentSize: indentSize,
insertSpaces: insertSpaces,
useTabStops: true
useTabStops: true,
autoIndent: EditorAutoIndentStrategy.Full,
});
let actual = getEditOperation(model, op);
assert.deepEqual(actual, expected);
......@@ -965,7 +974,8 @@ suite('Editor Commands - ShiftCommand', () => {
tabSize: tabSize,
indentSize: indentSize,
insertSpaces: insertSpaces,
useTabStops: true
useTabStops: true,
autoIndent: EditorAutoIndentStrategy.Full,
});
let actual = getEditOperation(model, op);
assert.deepEqual(actual, expected);
......
......@@ -6,6 +6,7 @@ import * as assert from 'assert';
import { CharacterPair, IndentAction } from 'vs/editor/common/modes/languageConfiguration';
import { OnEnterSupport } from 'vs/editor/common/modes/supports/onEnter';
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
suite('OnEnter', () => {
......@@ -18,7 +19,7 @@ suite('OnEnter', () => {
brackets: brackets
});
let testIndentAction = (beforeText: string, afterText: string, expected: IndentAction) => {
let actual = support.onEnter('', beforeText, afterText);
let actual = support.onEnter(EditorAutoIndentStrategy.Advanced, '', beforeText, afterText);
if (expected === IndentAction.None) {
assert.equal(actual, null);
} else {
......@@ -51,7 +52,7 @@ suite('OnEnter', () => {
regExpRules: javascriptOnEnterRules
});
let testIndentAction = (oneLineAboveText: string, beforeText: string, afterText: string, expectedIndentAction: IndentAction | null, expectedAppendText: string | null, removeText: number = 0) => {
let actual = support.onEnter(oneLineAboveText, beforeText, afterText);
let actual = support.onEnter(EditorAutoIndentStrategy.Advanced, oneLineAboveText, beforeText, afterText);
if (expectedIndentAction === null) {
assert.equal(actual, null, 'isNull:' + beforeText);
} else {
......@@ -132,4 +133,4 @@ suite('OnEnter', () => {
testIndentAction('', ' * test() {', '', IndentAction.Indent, null, 0);
testIndentAction(' ', ' * test() {', '', IndentAction.Indent, null, 0);
});
});
\ No newline at end of file
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册