This commit is contained in:
Alexandru Dima 2019-11-27 17:29:07 +01:00
parent 3f1a2f690a
commit e625e61558
No known key found for this signature in database
GPG key ID: 6E58D7B045760DA0
12 changed files with 128 additions and 72 deletions

View file

@ -40,8 +40,8 @@
"[yaml]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.autoIndent": false
"editor.autoIndent": "advanced"
}
}
}
}
}

View file

@ -256,6 +256,13 @@ function migrateOptions(options: IEditorOptions): void {
enabled: false
};
}
const autoIndent = options.autoIndent;
if (<any>autoIndent === true) {
options.autoIndent = 'full';
} else if (<any>autoIndent === false) {
options.autoIndent = 'advanced';
}
}
function deepCloneAndMigrateOptions(_options: IEditorOptions): IEditorOptions {

View file

@ -31,6 +31,18 @@ export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'bracket
*/
export type EditorAutoClosingOvertypeStrategy = 'always' | 'auto' | 'never';
/**
* Configuration options for auto indentation in the editor
* @internal
*/
export const enum EditorAutoIndentStrategy {
None = 0,
Keep = 1,
Brackets = 2,
Advanced = 3,
Full = 4
}
/**
* Configuration options for the editor.
*/
@ -364,7 +376,7 @@ export interface IEditorOptions {
* Enable auto indentation adjustment.
* Defaults to false.
*/
autoIndent?: boolean;
autoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full';
/**
* Enable format on type.
* Defaults to false.
@ -915,6 +927,20 @@ class EditorEnumOption<K1 extends EditorOption, T extends string, V> extends Bas
//#endregion
//#region autoIndent
function _autoIndentFromString(autoIndent: 'none' | 'keep' | 'brackets' | 'advanced' | 'full'): EditorAutoIndentStrategy {
switch (autoIndent) {
case 'none': return EditorAutoIndentStrategy.None;
case 'keep': return EditorAutoIndentStrategy.Keep;
case 'brackets': return EditorAutoIndentStrategy.Brackets;
case 'advanced': return EditorAutoIndentStrategy.Advanced;
case 'full': return EditorAutoIndentStrategy.Full;
}
}
//#endregion
//#region accessibilitySupport
class EditorAccessibilitySupport extends BaseEditorOption<EditorOption.accessibilitySupport, AccessibilitySupport> {
@ -3146,9 +3172,21 @@ export const EditorOptions = {
description: nls.localize('autoClosingQuotes', "Controls whether the editor should automatically close quotes after the user adds an opening quote.")
}
)),
autoIndent: register(new EditorBooleanOption(
EditorOption.autoIndent, 'autoIndent', true,
{ description: nls.localize('autoIndent', "Controls whether the editor should automatically adjust the indentation when users type, paste or move lines. Extensions with indentation rules of the language must be available.") }
autoIndent: register(new EditorEnumOption(
EditorOption.autoIndent, 'autoIndent',
EditorAutoIndentStrategy.Full, 'full',
['none', 'keep', 'brackets', 'advanced', 'full'],
_autoIndentFromString,
{
enumDescriptions: [
nls.localize('editor.autoIndent.none', "The editor will not insert indentation automatically."),
nls.localize('editor.autoIndent.keep', "The editor will keep the current line's indentation."),
nls.localize('editor.autoIndent.brackets', "The editor will keep the current line's indentation and honor language defined brackets."),
nls.localize('editor.autoIndent.advanced', "The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages."),
nls.localize('editor.autoIndent.full', "The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages."),
],
description: nls.localize('autoIndent', "Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.")
}
)),
automaticLayout: register(new EditorBooleanOption(
EditorOption.automaticLayout, 'automaticLayout', false,

View file

@ -6,7 +6,7 @@
import { CharCode } from 'vs/base/common/charCode';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingOvertypeStrategy, EditorOption } from 'vs/editor/common/config/editorOptions';
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingOvertypeStrategy, EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@ -103,7 +103,7 @@ export class CursorConfiguration {
public readonly autoClosingQuotes: EditorAutoClosingStrategy;
public readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
public readonly autoSurround: EditorAutoSurroundStrategy;
public readonly autoIndent: boolean;
public readonly autoIndent2: 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.autoIndent = options.get(EditorOption.autoIndent);
this.autoIndent2 = options.get(EditorOption.autoIndent);
this.autoClosingPairsOpen2 = new Map<string, StandardAutoClosingPairConditional[]>();
this.autoClosingPairsClose2 = new Map<string, StandardAutoClosingPairConditional[]>();

View file

@ -19,6 +19,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { EnterAction, IndentAction, StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
export class TypeOperations {
@ -289,12 +290,17 @@ export class TypeOperations {
}
private static _enter(config: CursorConfiguration, model: ITextModel, keepPosition: boolean, range: Range): ICommand {
if (!model.isCheapToTokenize(range.getStartPosition().lineNumber)) {
if (config.autoIndent2 === EditorAutoIndentStrategy.None) {
return TypeOperations._typeCommand(range, '\n', keepPosition);
}
if (!model.isCheapToTokenize(range.getStartPosition().lineNumber) || config.autoIndent2 === 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);
if (r) {
let enterAction = r.enterAction;

View file

@ -19,6 +19,7 @@ import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/comm
import { IndentConsts, IndentRulesSupport } from 'vs/editor/common/modes/supports/indentRules';
import { IOnEnterSupportOptions, OnEnterSupport } from 'vs/editor/common/modes/supports/onEnter';
import { RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
/**
* Interface used to support insertion of mode specific comments.
@ -539,12 +540,12 @@ export class LanguageConfigurationRegistryImpl {
return null;
}
public getIndentForEnter(model: ITextModel, range: Range, indentConverter: IIndentConverter, autoIndent: boolean): { beforeEnter: string, afterEnter: string } | null {
public getIndentForEnter(autoIndent2: EditorAutoIndentStrategy, model: ITextModel, range: Range, indentConverter: IIndentConverter): { beforeEnter: string, afterEnter: string } | null {
model.forceTokenization(range.startLineNumber);
let lineTokens = model.getLineTokens(range.startLineNumber);
let beforeEnterText;
let afterEnterText;
let beforeEnterText: string;
let afterEnterText: string;
let scopedLineTokens = createScopedLineTokens(lineTokens, range.startColumn - 1);
let scopedLineText = scopedLineTokens.getLineContent();
@ -709,20 +710,19 @@ export class LanguageConfigurationRegistryImpl {
return r ? r.enterAction : null;
}
public getEnterAction(model: ITextModel, range: Range): { enterAction: EnterAction; indentation: string; } | 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);
let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);
let onEnterSupport = this._getOnEnterSupport(scopedLineTokens.languageId);
const scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn);
const onEnterSupport = this._getOnEnterSupport(scopedLineTokens.languageId);
if (!onEnterSupport) {
return null;
}
let scopedLineText = scopedLineTokens.getLineContent();
let beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);
let afterEnterText;
const scopedLineText = scopedLineTokens.getLineContent();
const beforeEnterText = scopedLineText.substr(0, range.startColumn - 1 - scopedLineTokens.firstCharOffset);
// selection support
let afterEnterText: string;
if (range.isEmpty()) {
afterEnterText = scopedLineText.substr(range.startColumn - 1 - scopedLineTokens.firstCharOffset);
} else {
@ -730,12 +730,10 @@ export class LanguageConfigurationRegistryImpl {
afterEnterText = endScopedLineTokens.getLineContent().substr(range.endColumn - 1 - scopedLineTokens.firstCharOffset);
}
let lineNumber = range.startLineNumber;
let oneLineAboveText = '';
if (lineNumber > 1 && scopedLineTokens.firstCharOffset === 0) {
if (range.startLineNumber > 1 && scopedLineTokens.firstCharOffset === 0) {
// This is not the first line and the entire line belongs to this mode
let oneLineAboveScopedLineTokens = this.getScopedLineTokens(model, lineNumber - 1);
const oneLineAboveScopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber - 1);
if (oneLineAboveScopedLineTokens.languageId === scopedLineTokens.languageId) {
// The line above ends with text belonging to the same mode
oneLineAboveText = oneLineAboveScopedLineTokens.getLineContent();
@ -744,7 +742,7 @@ export class LanguageConfigurationRegistryImpl {
let enterResult: EnterAction | null = null;
try {
enterResult = onEnterSupport.onEnter(oneLineAboveText, beforeEnterText, afterEnterText);
enterResult = onEnterSupport.onEnter(autoIndent, oneLineAboveText, beforeEnterText, afterEnterText);
} catch (e) {
onUnexpectedError(e);
}

View file

@ -6,6 +6,7 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import { CharacterPair, EnterAction, IndentAction, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
export interface IOnEnterSupportOptions {
brackets?: CharacterPair[];
@ -48,46 +49,51 @@ export class OnEnterSupport {
this._regExpRules = opts.regExpRules || [];
}
public onEnter(oneLineAboveText: string, beforeEnterText: string, afterEnterText: string): EnterAction | null {
public onEnter(autoIndent: EditorAutoIndentStrategy, oneLineAboveText: string, beforeEnterText: string, afterEnterText: string): EnterAction | null {
// (1): `regExpRules`
for (let i = 0, len = this._regExpRules.length; i < len; i++) {
let rule = this._regExpRules[i];
const regResult = [{
reg: rule.beforeText,
text: beforeEnterText
}, {
reg: rule.afterText,
text: afterEnterText
}, {
reg: rule.oneLineAboveText,
text: oneLineAboveText
}].every((obj): boolean => {
return obj.reg ? obj.reg.test(obj.text) : true;
});
if (autoIndent >= EditorAutoIndentStrategy.Advanced) {
for (let i = 0, len = this._regExpRules.length; i < len; i++) {
let rule = this._regExpRules[i];
const regResult = [{
reg: rule.beforeText,
text: beforeEnterText
}, {
reg: rule.afterText,
text: afterEnterText
}, {
reg: rule.oneLineAboveText,
text: oneLineAboveText
}].every((obj): boolean => {
return obj.reg ? obj.reg.test(obj.text) : true;
});
if (regResult) {
return rule.action;
if (regResult) {
return rule.action;
}
}
}
// (2): Special indent-outdent
if (beforeEnterText.length > 0 && afterEnterText.length > 0) {
for (let i = 0, len = this._brackets.length; i < len; i++) {
let bracket = this._brackets[i];
if (bracket.openRegExp.test(beforeEnterText) && bracket.closeRegExp.test(afterEnterText)) {
return { indentAction: IndentAction.IndentOutdent };
if (autoIndent >= EditorAutoIndentStrategy.Brackets) {
if (beforeEnterText.length > 0 && afterEnterText.length > 0) {
for (let i = 0, len = this._brackets.length; i < len; i++) {
let bracket = this._brackets[i];
if (bracket.openRegExp.test(beforeEnterText) && bracket.closeRegExp.test(afterEnterText)) {
return { indentAction: IndentAction.IndentOutdent };
}
}
}
}
// (4): Open bracket based logic
if (beforeEnterText.length > 0) {
for (let i = 0, len = this._brackets.length; i < len; i++) {
let bracket = this._brackets[i];
if (bracket.openRegExp.test(beforeEnterText)) {
return { indentAction: IndentAction.Indent };
if (autoIndent >= EditorAutoIndentStrategy.Brackets) {
if (beforeEnterText.length > 0) {
for (let i = 0, len = this._brackets.length; i < len; i++) {
let bracket = this._brackets[i];
if (bracket.openRegExp.test(beforeEnterText)) {
return { indentAction: IndentAction.Indent };
}
}
}
}

View file

@ -22,7 +22,7 @@ import { IndentConsts } from 'vs/editor/common/modes/supports/indentRules';
import { IModelService } from 'vs/editor/common/services/modelService';
import * as indentUtils from 'vs/editor/contrib/indentation/indentUtils';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
export function getReindentEditOperations(model: ITextModel, startLineNumber: number, endLineNumber: number, inheritedIndent?: string): IIdentifiedSingleEditOperation[] {
if (model.getLineCount() === 1 && model.getLineMaxColumn(1) === 1) {
@ -442,7 +442,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
this.callOnModel.clear();
// we are disabled
if (!this.editor.getOption(EditorOption.autoIndent) || this.editor.getOption(EditorOption.formatOnPaste)) {
if (this.editor.getOption(EditorOption.autoIndent) < EditorAutoIndentStrategy.Full || this.editor.getOption(EditorOption.formatOnPaste)) {
return;
}

View file

@ -13,18 +13,19 @@ import { IndentAction } from 'vs/editor/common/modes/languageConfiguration';
import { IIndentConverter, LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { IndentConsts } from 'vs/editor/common/modes/supports/indentRules';
import * as indentUtils from 'vs/editor/contrib/indentation/indentUtils';
import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
export class MoveLinesCommand implements ICommand {
private readonly _selection: Selection;
private readonly _isMovingDown: boolean;
private readonly _autoIndent: boolean;
private readonly _autoIndent: EditorAutoIndentStrategy;
private _selectionId: string | null;
private _moveEndPositionDown?: boolean;
private _moveEndLineSelectionShrink: boolean;
constructor(selection: Selection, isMovingDown: boolean, autoIndent: boolean) {
constructor(selection: Selection, isMovingDown: boolean, autoIndent: EditorAutoIndentStrategy) {
this._selection = selection;
this._isMovingDown = isMovingDown;
this._autoIndent = autoIndent;
@ -288,7 +289,7 @@ export class MoveLinesCommand implements ICommand {
}
private shouldAutoIndent(model: ITextModel, selection: Selection) {
if (!this._autoIndent) {
if (this._autoIndent < EditorAutoIndentStrategy.Full) {
return false;
}
// if it's not easy to tokenize, we stop auto indent.

View file

@ -13,7 +13,7 @@ const global: any = self;
// Set defaults for standalone editor
(<any>EditorOptions.wrappingIndent).defaultValue = WrappingIndent.None;
(<any>EditorOptions.glyphMargin).defaultValue = false;
(<any>EditorOptions.autoIndent).defaultValue = false;
(<any>EditorOptions.autoIndent).defaultValue = 'advanced';
(<any>EditorOptions.overviewRulerLanes).defaultValue = 2;
const api = createMonacoBaseAPI();

View file

@ -2834,7 +2834,7 @@ suite('Editor Controller - Indentation Rules', () => {
],
languageIdentifier: mode.getLanguageIdentifier(),
modelOpts: { insertSpaces: false },
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 1, 12, false);
assertCursor(cursor, new Selection(1, 12, 1, 12));
@ -2857,7 +2857,7 @@ suite('Editor Controller - Indentation Rules', () => {
'\t'
],
languageIdentifier: mode.getLanguageIdentifier(),
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 2, 2, false);
assertCursor(cursor, new Selection(2, 2, 2, 2));
@ -2876,7 +2876,7 @@ suite('Editor Controller - Indentation Rules', () => {
],
languageIdentifier: mode.getLanguageIdentifier(),
modelOpts: { insertSpaces: false },
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 2, 15, false);
assertCursor(cursor, new Selection(2, 15, 2, 15));
@ -2896,7 +2896,7 @@ suite('Editor Controller - Indentation Rules', () => {
],
languageIdentifier: mode.getLanguageIdentifier(),
modelOpts: { insertSpaces: false },
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 2, 14, false);
assertCursor(cursor, new Selection(2, 14, 2, 14));
@ -2924,7 +2924,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: 'full' }, (editor, cursor) => {
moveTo(cursor, 2, 11, false);
assertCursor(cursor, new Selection(2, 11, 2, 11));
@ -2948,7 +2948,7 @@ suite('Editor Controller - Indentation Rules', () => {
'}}'
],
languageIdentifier: mode.getLanguageIdentifier(),
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 3, 13, false);
assertCursor(cursor, new Selection(3, 13, 3, 13));
@ -3084,7 +3084,7 @@ suite('Editor Controller - Indentation Rules', () => {
],
languageIdentifier: mode.getLanguageIdentifier(),
modelOpts: { insertSpaces: false },
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 5, 4, false);
assertCursor(cursor, new Selection(5, 4, 5, 4));
@ -3554,7 +3554,7 @@ suite('Editor Controller - Indentation Rules', () => {
rubyMode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: 'full' }, (editor, cursor) => {
moveTo(cursor, 4, 7, false);
assertCursor(cursor, new Selection(4, 7, 4, 7));
@ -3615,7 +3615,7 @@ suite('Editor Controller - Indentation Rules', () => {
'\t\t'
],
languageIdentifier: mode.getLanguageIdentifier(),
editorOpts: { autoIndent: true }
editorOpts: { autoIndent: 'full' }
}, (model, cursor) => {
moveTo(cursor, 3, 3, false);
assertCursor(cursor, new Selection(3, 3, 3, 3));
@ -3664,7 +3664,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: 'advanced' }, (editor, cursor) => {
moveTo(cursor, 7, 6, false);
assertCursor(cursor, new Selection(7, 6, 7, 6));
@ -3728,7 +3728,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: 'advanced' }, (editor, cursor) => {
moveTo(cursor, 8, 1, false);
assertCursor(cursor, new Selection(8, 1, 8, 1));
@ -3791,7 +3791,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: 'full' }, (editor, cursor) => {
moveTo(cursor, 3, 19, false);
assertCursor(cursor, new Selection(3, 19, 3, 19));

2
src/vs/monaco.d.ts vendored
View file

@ -2775,7 +2775,7 @@ declare namespace monaco.editor {
* Enable auto indentation adjustment.
* Defaults to false.
*/
autoIndent?: boolean;
autoIndent?: 'none' | 'keep' | 'brackets' | 'advanced' | 'full';
/**
* Enable format on type.
* Defaults to false.