提交 d119c924 编写于 作者: T Tim Hutt 提交者: Tim Hutt

Add atomic tabs option

This treats tabs faked using spaces as if they were real tabs meaning that you can't select the middle of them.
上级 78db6d01
...@@ -14,6 +14,7 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel'; ...@@ -14,6 +14,7 @@ import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { EditorOption } from 'vs/editor/common/config/editorOptions';
import * as platform from 'vs/base/common/platform'; import * as platform from 'vs/base/common/platform';
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
export interface IMouseDispatchData { export interface IMouseDispatchData {
position: Position; position: Position;
...@@ -128,24 +129,35 @@ export class ViewController { ...@@ -128,24 +129,35 @@ export class ViewController {
} }
public dispatchMouse(data: IMouseDispatchData): void { public dispatchMouse(data: IMouseDispatchData): void {
let position = data.position;
if (this.viewModel.getTextModelOptions().atomicSoftTabs) {
const minColumn = this.viewModel.getLineMinColumn(position.lineNumber);
const lineContent = this.viewModel.getLineContent(position.lineNumber);
const { tabSize } = this.viewModel.getTextModelOptions();
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest);
if (newPosition !== -1) {
position = new Position(position.lineNumber, newPosition + minColumn);
}
}
const options = this.configuration.options; const options = this.configuration.options;
const selectionClipboardIsOn = (platform.isLinux && options.get(EditorOption.selectionClipboard)); const selectionClipboardIsOn = (platform.isLinux && options.get(EditorOption.selectionClipboard));
const columnSelection = options.get(EditorOption.columnSelection); const columnSelection = options.get(EditorOption.columnSelection);
if (data.middleButton && !selectionClipboardIsOn) { if (data.middleButton && !selectionClipboardIsOn) {
this._columnSelect(data.position, data.mouseColumn, data.inSelectionMode); this._columnSelect(position, data.mouseColumn, data.inSelectionMode);
} else if (data.startedOnLineNumbers) { } else if (data.startedOnLineNumbers) {
// If the dragging started on the gutter, then have operations work on the entire line // If the dragging started on the gutter, then have operations work on the entire line
if (this._hasMulticursorModifier(data)) { if (this._hasMulticursorModifier(data)) {
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._lastCursorLineSelect(data.position); this._lastCursorLineSelect(position);
} else { } else {
this._createCursor(data.position, true); this._createCursor(position, true);
} }
} else { } else {
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._lineSelectDrag(data.position); this._lineSelectDrag(position);
} else { } else {
this._lineSelect(data.position); this._lineSelect(position);
} }
} }
} else if (data.mouseDownCount >= 4) { } else if (data.mouseDownCount >= 4) {
...@@ -153,54 +165,54 @@ export class ViewController { ...@@ -153,54 +165,54 @@ export class ViewController {
} else if (data.mouseDownCount === 3) { } else if (data.mouseDownCount === 3) {
if (this._hasMulticursorModifier(data)) { if (this._hasMulticursorModifier(data)) {
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._lastCursorLineSelectDrag(data.position); this._lastCursorLineSelectDrag(position);
} else { } else {
this._lastCursorLineSelect(data.position); this._lastCursorLineSelect(position);
} }
} else { } else {
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._lineSelectDrag(data.position); this._lineSelectDrag(position);
} else { } else {
this._lineSelect(data.position); this._lineSelect(position);
} }
} }
} else if (data.mouseDownCount === 2) { } else if (data.mouseDownCount === 2) {
if (this._hasMulticursorModifier(data)) { if (this._hasMulticursorModifier(data)) {
this._lastCursorWordSelect(data.position); this._lastCursorWordSelect(position);
} else { } else {
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._wordSelectDrag(data.position); this._wordSelectDrag(position);
} else { } else {
this._wordSelect(data.position); this._wordSelect(position);
} }
} }
} else { } else {
if (this._hasMulticursorModifier(data)) { if (this._hasMulticursorModifier(data)) {
if (!this._hasNonMulticursorModifier(data)) { if (!this._hasNonMulticursorModifier(data)) {
if (data.shiftKey) { if (data.shiftKey) {
this._columnSelect(data.position, data.mouseColumn, true); this._columnSelect(position, data.mouseColumn, true);
} else { } else {
// Do multi-cursor operations only when purely alt is pressed // Do multi-cursor operations only when purely alt is pressed
if (data.inSelectionMode) { if (data.inSelectionMode) {
this._lastCursorMoveToSelect(data.position); this._lastCursorMoveToSelect(position);
} else { } else {
this._createCursor(data.position, false); this._createCursor(position, false);
} }
} }
} }
} else { } else {
if (data.inSelectionMode) { if (data.inSelectionMode) {
if (data.altKey) { if (data.altKey) {
this._columnSelect(data.position, data.mouseColumn, true); this._columnSelect(position, data.mouseColumn, true);
} else { } else {
if (columnSelection) { if (columnSelection) {
this._columnSelect(data.position, data.mouseColumn, true); this._columnSelect(position, data.mouseColumn, true);
} else { } else {
this._moveToSelect(data.position); this._moveToSelect(position);
} }
} }
} else { } else {
this.moveTo(data.position); this.moveTo(position);
} }
} }
} }
......
...@@ -482,6 +482,11 @@ const editorConfiguration: IConfigurationNode = { ...@@ -482,6 +482,11 @@ const editorConfiguration: IConfigurationNode = {
default: EDITOR_MODEL_DEFAULTS.insertSpaces, default: EDITOR_MODEL_DEFAULTS.insertSpaces,
markdownDescription: nls.localize('insertSpaces', "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.") markdownDescription: nls.localize('insertSpaces', "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.")
}, },
'editor.atomicSoftTabs': {
type: 'boolean',
default: EDITOR_MODEL_DEFAULTS.atomicSoftTabs,
markdownDescription: nls.localize('atomicSoftTabs', "Emulate selection behaviour of hard tabs when using soft tabs (spaces) for indentation. This means selection will snap to indentation boundaries.")
},
'editor.detectIndentation': { 'editor.detectIndentation': {
type: 'boolean', type: 'boolean',
default: EDITOR_MODEL_DEFAULTS.detectIndentation, default: EDITOR_MODEL_DEFAULTS.detectIndentation,
......
...@@ -3542,6 +3542,7 @@ export const EDITOR_MODEL_DEFAULTS = { ...@@ -3542,6 +3542,7 @@ export const EDITOR_MODEL_DEFAULTS = {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: true, insertSpaces: true,
atomicSoftTabs: false,
detectIndentation: true, detectIndentation: true,
trimAutoWhitespace: true, trimAutoWhitespace: true,
largeFileOptimizations: true largeFileOptimizations: true
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CharCode } from 'vs/base/common/charCode';
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
export enum Direction {
Left,
Right,
Nearest,
}
export class AtomicTabMoveOperations {
// Get the visible column at the position. If we get to a non-whitespace character first
// or past the end of string then return -1. Note `position` and the return
// value are 0-based.
public static whitespaceVisibleColumn(lineContent: string, position: number, tabSize: number) {
let visibleColumn = 0;
for (let i = 0; i < lineContent.length; ++i) {
if (i === position) {
return visibleColumn;
}
const chCode = lineContent.charCodeAt(i);
switch (chCode) {
case CharCode.Space:
visibleColumn += 1;
break;
case CharCode.Tab:
// Skip to the next multiple of tabSize.
visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);
break;
default:
return -1;
}
}
if (position === lineContent.length) {
return visibleColumn;
}
return -1;
}
// Return the position that should result from a move left, right or to the
// nearest tab, if atomic tabs are enabled. Left and right are used for the
// arrow key movements, nearest is used for mouse selection. It returns
// -1 if atomic tabs are not relevant and you should fall back to normal
// behaviour.
//
// Note, `position` and the return value are 0-based.
public static atomicPosition(lineContent: string, position: number, tabSize: number, direction: Direction): number {
// Get the 0-based visible column corresponding to the position, or return
// -1 if it is not in the initial whitespace.
let visibleColumn = AtomicTabMoveOperations.whitespaceVisibleColumn(lineContent, position, tabSize);
if (visibleColumn === -1) {
return -1;
}
// Is the output left or right of the current position. The case for nearest
// where it is the same as the current position is handled in the switch.
let left: boolean;
switch (direction) {
case Direction.Left:
left = true;
break;
case Direction.Right:
left = false;
break;
case Direction.Nearest:
// The code below assumes the output position is either left or right
// of the input position. If it is the same, return immediately.
if (visibleColumn % tabSize === 0) {
return position;
}
// Go to the nearest indentation.
left = visibleColumn % tabSize <= (tabSize / 2);
break;
}
// The code below won't work if visibleColumn is zero and left is true because
// it takes the mod of a negative number, which behaves oddly. In that case
// we already know what to return.
if (left && visibleColumn === 0) {
return -1;
}
const tmp = visibleColumn + (left ? -1 : tabSize);
const targetVisibleColumn = tmp - tmp % tabSize;
// Find the target visible column. If going right we can just continue from
// where whitespaceVisibleColumn got to. If going left it's easiest to start
// from the beginning because the width of tab characters depend on the
// characters to their left. E.g. ' \t' is one tabSize, but so is '\t'.
if (left) {
visibleColumn = 0;
}
for (let i = (left ? 0 : position); i < lineContent.length; ++i) {
if (visibleColumn === targetVisibleColumn) {
// This is the position we want to get to, but we have one more case
// to handle if going left.
if (left) {
// If the direction is left, we need to keep scanning right to ensure
// that targetVisibleColumn + tabSize is before non-whitespace.
// This is so that when we press left at the end of a partial
// indentation it only goes one character. For example ' foo' with
// tabSize 4, should jump from position 6 to position 5, not 4.
for (let k = i; k < lineContent.length; ++k) {
if (visibleColumn === targetVisibleColumn + tabSize) {
// It is a full indentation.
return i;
}
const chCode = lineContent.charCodeAt(k);
switch (chCode) {
case CharCode.Space:
visibleColumn += 1;
break;
case CharCode.Tab:
visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);
break;
default:
return -1;
}
}
if (visibleColumn === targetVisibleColumn + tabSize) {
return i;
}
// It must have been a partial indentation.
return -1;
} else {
// If going right then we must have been in a complete indentation.
return i;
}
}
const chCode = lineContent.charCodeAt(i);
switch (chCode) {
case CharCode.Space:
visibleColumn += 1;
break;
case CharCode.Tab:
visibleColumn = CursorColumns.nextRenderTabStop(visibleColumn, tabSize);
break;
default:
return -1;
}
}
// This condition handles when the target column is at the end of the line.
if (visibleColumn === targetVisibleColumn) {
return lineContent.length;
}
return -1;
}
}
...@@ -62,6 +62,7 @@ export class CursorConfiguration { ...@@ -62,6 +62,7 @@ export class CursorConfiguration {
public readonly tabSize: number; public readonly tabSize: number;
public readonly indentSize: number; public readonly indentSize: number;
public readonly insertSpaces: boolean; public readonly insertSpaces: boolean;
public readonly atomicSoftTabs: boolean;
public readonly pageSize: number; public readonly pageSize: number;
public readonly lineHeight: number; public readonly lineHeight: number;
public readonly useTabStops: boolean; public readonly useTabStops: boolean;
...@@ -114,6 +115,7 @@ export class CursorConfiguration { ...@@ -114,6 +115,7 @@ export class CursorConfiguration {
this.tabSize = modelOptions.tabSize; this.tabSize = modelOptions.tabSize;
this.indentSize = modelOptions.indentSize; this.indentSize = modelOptions.indentSize;
this.insertSpaces = modelOptions.insertSpaces; this.insertSpaces = modelOptions.insertSpaces;
this.atomicSoftTabs = modelOptions.atomicSoftTabs;
this.lineHeight = options.get(EditorOption.lineHeight); this.lineHeight = options.get(EditorOption.lineHeight);
this.pageSize = Math.max(1, Math.floor(layoutInfo.height / this.lineHeight) - 2); this.pageSize = Math.max(1, Math.floor(layoutInfo.height / this.lineHeight) - 2);
this.useTabStops = options.get(EditorOption.useTabStops); this.useTabStops = options.get(EditorOption.useTabStops);
...@@ -557,14 +559,14 @@ export class CursorColumns { ...@@ -557,14 +559,14 @@ export class CursorColumns {
} }
/** /**
* ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns) * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)
*/ */
public static prevRenderTabStop(column: number, tabSize: number): number { public static prevRenderTabStop(column: number, tabSize: number): number {
return column - 1 - (column - 1) % tabSize; return column - 1 - (column - 1) % tabSize;
} }
/** /**
* ATTENTION: This works with 0-based columns (as oposed to the regular 1-based columns) * ATTENTION: This works with 0-based columns (as opposed to the regular 1-based columns)
*/ */
public static prevIndentTabStop(column: number, indentSize: number): number { public static prevIndentTabStop(column: number, indentSize: number): number {
return column - 1 - (column - 1) % indentSize; return column - 1 - (column - 1) % indentSize;
......
...@@ -8,6 +8,8 @@ import { Position } from 'vs/editor/common/core/position'; ...@@ -8,6 +8,8 @@ import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import * as strings from 'vs/base/common/strings'; import * as strings from 'vs/base/common/strings';
import { Constants } from 'vs/base/common/uint'; import { Constants } from 'vs/base/common/uint';
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
export class CursorPosition { export class CursorPosition {
_cursorPositionBrand: void; _cursorPositionBrand: void;
...@@ -29,14 +31,34 @@ export class MoveOperations { ...@@ -29,14 +31,34 @@ export class MoveOperations {
if (column > model.getLineMinColumn(lineNumber)) { if (column > model.getLineMinColumn(lineNumber)) {
column = column - strings.prevCharLength(model.getLineContent(lineNumber), column - 1); column = column - strings.prevCharLength(model.getLineContent(lineNumber), column - 1);
} else if (lineNumber > 1) { } else if (lineNumber > 1) {
lineNumber = lineNumber - 1; lineNumber -= 1;
column = model.getLineMaxColumn(lineNumber);
}
return new Position(lineNumber, column);
}
public static leftPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position {
const minColumn = model.getLineMinColumn(lineNumber);
if (column > minColumn) {
const lineContent = model.getLineContent(lineNumber);
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left);
if (newPosition !== -1) {
column = minColumn + newPosition;
} else {
column -= strings.prevCharLength(model.getLineContent(lineNumber), column - 1);
}
} else if (lineNumber > 1) {
lineNumber -= 1;
column = model.getLineMaxColumn(lineNumber); column = model.getLineMaxColumn(lineNumber);
} }
return new Position(lineNumber, column); return new Position(lineNumber, column);
} }
public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition {
const pos = MoveOperations.leftPosition(model, lineNumber, column); const pos = config.atomicSoftTabs
? MoveOperations.leftPositionatomicSoftTabs(model, lineNumber, column, config.tabSize)
: MoveOperations.leftPosition(model, lineNumber, column);
return new CursorPosition(pos.lineNumber, pos.column, 0); return new CursorPosition(pos.lineNumber, pos.column, 0);
} }
...@@ -61,14 +83,34 @@ export class MoveOperations { ...@@ -61,14 +83,34 @@ export class MoveOperations {
if (column < model.getLineMaxColumn(lineNumber)) { if (column < model.getLineMaxColumn(lineNumber)) {
column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1); column = column + strings.nextCharLength(model.getLineContent(lineNumber), column - 1);
} else if (lineNumber < model.getLineCount()) { } else if (lineNumber < model.getLineCount()) {
lineNumber = lineNumber + 1; lineNumber += 1;
column = model.getLineMinColumn(lineNumber); column = model.getLineMinColumn(lineNumber);
} }
return new Position(lineNumber, column); return new Position(lineNumber, column);
} }
public static rightPositionatomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position {
const minColumn = model.getLineMinColumn(lineNumber);
if (column < model.getLineMaxColumn(lineNumber)) {
const lineContent = model.getLineContent(lineNumber);
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right);
if (newPosition !== -1) {
column = minColumn + newPosition;
} else {
column += strings.nextCharLength(model.getLineContent(lineNumber), column - 1);
}
} else if (lineNumber < model.getLineCount()) {
lineNumber += 1;
column = minColumn;
}
return new Position(lineNumber, column);
}
public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition { public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition {
const pos = MoveOperations.rightPosition(model, lineNumber, column); const pos = config.atomicSoftTabs
? MoveOperations.rightPositionatomicSoftTabs(model, lineNumber, column, config.tabSize, config.indentSize)
: MoveOperations.rightPosition(model, lineNumber, column);
return new CursorPosition(pos.lineNumber, pos.column, 0); return new CursorPosition(pos.lineNumber, pos.column, 0);
} }
......
...@@ -400,6 +400,7 @@ export class TextModelResolvedOptions { ...@@ -400,6 +400,7 @@ export class TextModelResolvedOptions {
readonly tabSize: number; readonly tabSize: number;
readonly indentSize: number; readonly indentSize: number;
readonly insertSpaces: boolean; readonly insertSpaces: boolean;
readonly atomicSoftTabs: boolean;
readonly defaultEOL: DefaultEndOfLine; readonly defaultEOL: DefaultEndOfLine;
readonly trimAutoWhitespace: boolean; readonly trimAutoWhitespace: boolean;
...@@ -410,12 +411,14 @@ export class TextModelResolvedOptions { ...@@ -410,12 +411,14 @@ export class TextModelResolvedOptions {
tabSize: number; tabSize: number;
indentSize: number; indentSize: number;
insertSpaces: boolean; insertSpaces: boolean;
atomicSoftTabs: boolean;
defaultEOL: DefaultEndOfLine; defaultEOL: DefaultEndOfLine;
trimAutoWhitespace: boolean; trimAutoWhitespace: boolean;
}) { }) {
this.tabSize = Math.max(1, src.tabSize | 0); this.tabSize = Math.max(1, src.tabSize | 0);
this.indentSize = src.tabSize | 0; this.indentSize = src.tabSize | 0;
this.insertSpaces = Boolean(src.insertSpaces); this.insertSpaces = Boolean(src.insertSpaces);
this.atomicSoftTabs = Boolean(src.atomicSoftTabs);
this.defaultEOL = src.defaultEOL | 0; this.defaultEOL = src.defaultEOL | 0;
this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace); this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);
} }
...@@ -428,6 +431,7 @@ export class TextModelResolvedOptions { ...@@ -428,6 +431,7 @@ export class TextModelResolvedOptions {
this.tabSize === other.tabSize this.tabSize === other.tabSize
&& this.indentSize === other.indentSize && this.indentSize === other.indentSize
&& this.insertSpaces === other.insertSpaces && this.insertSpaces === other.insertSpaces
&& this.atomicSoftTabs === other.atomicSoftTabs
&& this.defaultEOL === other.defaultEOL && this.defaultEOL === other.defaultEOL
&& this.trimAutoWhitespace === other.trimAutoWhitespace && this.trimAutoWhitespace === other.trimAutoWhitespace
); );
...@@ -441,6 +445,7 @@ export class TextModelResolvedOptions { ...@@ -441,6 +445,7 @@ export class TextModelResolvedOptions {
tabSize: this.tabSize !== newOpts.tabSize, tabSize: this.tabSize !== newOpts.tabSize,
indentSize: this.indentSize !== newOpts.indentSize, indentSize: this.indentSize !== newOpts.indentSize,
insertSpaces: this.insertSpaces !== newOpts.insertSpaces, insertSpaces: this.insertSpaces !== newOpts.insertSpaces,
atomicSoftTabs: this.atomicSoftTabs !== newOpts.atomicSoftTabs,
trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace, trimAutoWhitespace: this.trimAutoWhitespace !== newOpts.trimAutoWhitespace,
}; };
} }
...@@ -453,6 +458,7 @@ export interface ITextModelCreationOptions { ...@@ -453,6 +458,7 @@ export interface ITextModelCreationOptions {
tabSize: number; tabSize: number;
indentSize: number; indentSize: number;
insertSpaces: boolean; insertSpaces: boolean;
atomicSoftTabs: boolean;
detectIndentation: boolean; detectIndentation: boolean;
trimAutoWhitespace: boolean; trimAutoWhitespace: boolean;
defaultEOL: DefaultEndOfLine; defaultEOL: DefaultEndOfLine;
...@@ -464,6 +470,7 @@ export interface ITextModelUpdateOptions { ...@@ -464,6 +470,7 @@ export interface ITextModelUpdateOptions {
tabSize?: number; tabSize?: number;
indentSize?: number; indentSize?: number;
insertSpaces?: boolean; insertSpaces?: boolean;
atomicSoftTabs?: boolean;
trimAutoWhitespace?: boolean; trimAutoWhitespace?: boolean;
} }
......
...@@ -197,6 +197,7 @@ export class TextModel extends Disposable implements model.ITextModel { ...@@ -197,6 +197,7 @@ export class TextModel extends Disposable implements model.ITextModel {
tabSize: EDITOR_MODEL_DEFAULTS.tabSize, tabSize: EDITOR_MODEL_DEFAULTS.tabSize,
indentSize: EDITOR_MODEL_DEFAULTS.indentSize, indentSize: EDITOR_MODEL_DEFAULTS.indentSize,
insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces, insertSpaces: EDITOR_MODEL_DEFAULTS.insertSpaces,
atomicSoftTabs: EDITOR_MODEL_DEFAULTS.atomicSoftTabs,
detectIndentation: false, detectIndentation: false,
defaultEOL: model.DefaultEndOfLine.LF, defaultEOL: model.DefaultEndOfLine.LF,
trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace, trimAutoWhitespace: EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,
...@@ -210,6 +211,7 @@ export class TextModel extends Disposable implements model.ITextModel { ...@@ -210,6 +211,7 @@ export class TextModel extends Disposable implements model.ITextModel {
tabSize: guessedIndentation.tabSize, tabSize: guessedIndentation.tabSize,
indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize indentSize: guessedIndentation.tabSize, // TODO@Alex: guess indentSize independent of tabSize
insertSpaces: guessedIndentation.insertSpaces, insertSpaces: guessedIndentation.insertSpaces,
atomicSoftTabs: options.atomicSoftTabs,
trimAutoWhitespace: options.trimAutoWhitespace, trimAutoWhitespace: options.trimAutoWhitespace,
defaultEOL: options.defaultEOL defaultEOL: options.defaultEOL
}); });
...@@ -219,6 +221,7 @@ export class TextModel extends Disposable implements model.ITextModel { ...@@ -219,6 +221,7 @@ export class TextModel extends Disposable implements model.ITextModel {
tabSize: options.tabSize, tabSize: options.tabSize,
indentSize: options.indentSize, indentSize: options.indentSize,
insertSpaces: options.insertSpaces, insertSpaces: options.insertSpaces,
atomicSoftTabs: options.atomicSoftTabs,
trimAutoWhitespace: options.trimAutoWhitespace, trimAutoWhitespace: options.trimAutoWhitespace,
defaultEOL: options.defaultEOL defaultEOL: options.defaultEOL
}); });
...@@ -619,12 +622,14 @@ export class TextModel extends Disposable implements model.ITextModel { ...@@ -619,12 +622,14 @@ export class TextModel extends Disposable implements model.ITextModel {
let tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize; let tabSize = (typeof _newOpts.tabSize !== 'undefined') ? _newOpts.tabSize : this._options.tabSize;
let indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize; let indentSize = (typeof _newOpts.indentSize !== 'undefined') ? _newOpts.indentSize : this._options.indentSize;
let insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces; let insertSpaces = (typeof _newOpts.insertSpaces !== 'undefined') ? _newOpts.insertSpaces : this._options.insertSpaces;
let atomicSoftTabs = (typeof _newOpts.atomicSoftTabs !== 'undefined') ? _newOpts.atomicSoftTabs : this._options.atomicSoftTabs;
let trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace; let trimAutoWhitespace = (typeof _newOpts.trimAutoWhitespace !== 'undefined') ? _newOpts.trimAutoWhitespace : this._options.trimAutoWhitespace;
let newOpts = new model.TextModelResolvedOptions({ let newOpts = new model.TextModelResolvedOptions({
tabSize: tabSize, tabSize: tabSize,
indentSize: indentSize, indentSize: indentSize,
insertSpaces: insertSpaces, insertSpaces: insertSpaces,
atomicSoftTabs: atomicSoftTabs,
defaultEOL: this._options.defaultEOL, defaultEOL: this._options.defaultEOL,
trimAutoWhitespace: trimAutoWhitespace trimAutoWhitespace: trimAutoWhitespace
}); });
......
...@@ -104,6 +104,7 @@ export interface IModelOptionsChangedEvent { ...@@ -104,6 +104,7 @@ export interface IModelOptionsChangedEvent {
readonly tabSize: boolean; readonly tabSize: boolean;
readonly indentSize: boolean; readonly indentSize: boolean;
readonly insertSpaces: boolean; readonly insertSpaces: boolean;
readonly atomicSoftTabs: boolean;
readonly trimAutoWhitespace: boolean; readonly trimAutoWhitespace: boolean;
} }
......
...@@ -100,6 +100,7 @@ interface IRawEditorConfig { ...@@ -100,6 +100,7 @@ interface IRawEditorConfig {
tabSize?: any; tabSize?: any;
indentSize?: any; indentSize?: any;
insertSpaces?: any; insertSpaces?: any;
atomicSoftTabs?: any;
detectIndentation?: any; detectIndentation?: any;
trimAutoWhitespace?: any; trimAutoWhitespace?: any;
creationOptions?: any; creationOptions?: any;
...@@ -213,6 +214,11 @@ export class ModelServiceImpl extends Disposable implements IModelService { ...@@ -213,6 +214,11 @@ export class ModelServiceImpl extends Disposable implements IModelService {
insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces)); insertSpaces = (config.editor.insertSpaces === 'false' ? false : Boolean(config.editor.insertSpaces));
} }
let atomicSoftTabs = EDITOR_MODEL_DEFAULTS.atomicSoftTabs;
if (config.editor && typeof config.editor.atomicSoftTabs !== 'undefined') {
atomicSoftTabs = (config.editor.atomicSoftTabs === 'false' ? false : Boolean(config.editor.atomicSoftTabs));
}
let newDefaultEOL = DEFAULT_EOL; let newDefaultEOL = DEFAULT_EOL;
const eol = config.eol; const eol = config.eol;
if (eol === '\r\n') { if (eol === '\r\n') {
...@@ -241,6 +247,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { ...@@ -241,6 +247,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
tabSize: tabSize, tabSize: tabSize,
indentSize: indentSize, indentSize: indentSize,
insertSpaces: insertSpaces, insertSpaces: insertSpaces,
atomicSoftTabs: atomicSoftTabs,
detectIndentation: detectIndentation, detectIndentation: detectIndentation,
defaultEOL: newDefaultEOL, defaultEOL: newDefaultEOL,
trimAutoWhitespace: trimAutoWhitespace, trimAutoWhitespace: trimAutoWhitespace,
......
...@@ -93,6 +93,11 @@ export interface IGlobalEditorOptions { ...@@ -93,6 +93,11 @@ export interface IGlobalEditorOptions {
* Defaults to true. * Defaults to true.
*/ */
insertSpaces?: boolean; insertSpaces?: boolean;
/**
* Treat soft tabs like hard tabs.
* Defaults to false.
*/
atomicSoftTabs?: boolean;
/** /**
* Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents.
* Defaults to true. * Defaults to true.
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/controller/cursorAtomicMoveOperations';
suite('Cursor move command test', () => {
test('Test whitespaceVisibleColumn', () => {
const testCases = [
{
lineContent: ' ',
tabSize: 4,
expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, -1],
},
{
lineContent: ' ',
tabSize: 4,
expected: [0, 1, 2, -1],
},
{
lineContent: '\t',
tabSize: 4,
expected: [0, 4, -1],
},
{
lineContent: '\t ',
tabSize: 4,
expected: [0, 4, 5, -1],
},
{
lineContent: ' \t\t ',
tabSize: 4,
expected: [0, 1, 4, 8, 9, -1],
},
{
lineContent: ' \tA',
tabSize: 4,
expected: [0, 1, 4, -1, -1],
},
{
lineContent: 'A',
tabSize: 4,
expected: [0, -1, -1],
},
{
lineContent: '',
tabSize: 4,
expected: [0, -1],
},
];
for (const testCase of testCases) {
const actual = testCase.expected.map((_, i) => AtomicTabMoveOperations.whitespaceVisibleColumn(testCase.lineContent, i, testCase.tabSize));
assert.deepStrictEqual(actual, testCase.expected);
}
});
test('Test atomicPosition', () => {
const testCases = [
{
lineContent: ' ',
tabSize: 4,
expectedLeft: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1],
expectedRight: [4, 4, 4, 4, 8, 8, 8, 8, -1, -1],
expectedNearest: [0, 0, 0, 4, 4, 4, 4, 8, 8, -1],
},
{
lineContent: ' \t',
tabSize: 4,
expectedLeft: [-1, 0, 0, -1],
expectedRight: [2, 2, -1, -1],
expectedNearest: [0, 0, 2, -1],
},
{
lineContent: '\t ',
tabSize: 4,
expectedLeft: [-1, 0, -1, -1],
expectedRight: [1, -1, -1, -1],
expectedNearest: [0, 1, -1, -1],
},
{
lineContent: ' \t ',
tabSize: 4,
expectedLeft: [-1, 0, 0, -1, -1],
expectedRight: [2, 2, -1, -1, -1],
expectedNearest: [0, 0, 2, -1, -1],
},
{
lineContent: ' A',
tabSize: 4,
expectedLeft: [-1, 0, 0, 0, 0, 4, 4, 4, 4, -1, -1],
expectedRight: [4, 4, 4, 4, 8, 8, 8, 8, -1, -1, -1],
expectedNearest: [0, 0, 0, 4, 4, 4, 4, 8, 8, -1, -1],
},
{
lineContent: ' foo',
tabSize: 4,
expectedLeft: [-1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1],
expectedRight: [4, 4, 4, 4, -1, -1, -1, -1, -1, -1, -1],
expectedNearest: [0, 0, 0, 4, 4, -1, -1, -1, -1, -1, -1],
},
];
for (const testCase of testCases) {
for (const { direction, expected } of [
{
direction: Direction.Left,
expected: testCase.expectedLeft,
},
{
direction: Direction.Right,
expected: testCase.expectedRight,
},
{
direction: Direction.Nearest,
expected: testCase.expectedNearest,
},
]) {
const actual = expected.map((_, i) => AtomicTabMoveOperations.atomicPosition(testCase.lineContent, i, testCase.tabSize, direction));
assert.deepStrictEqual(actual, expected);
}
}
});
});
...@@ -21,6 +21,7 @@ export interface IRelaxedTextModelCreationOptions { ...@@ -21,6 +21,7 @@ export interface IRelaxedTextModelCreationOptions {
tabSize?: number; tabSize?: number;
indentSize?: number; indentSize?: number;
insertSpaces?: boolean; insertSpaces?: boolean;
atomicSoftTabs?: boolean;
detectIndentation?: boolean; detectIndentation?: boolean;
trimAutoWhitespace?: boolean; trimAutoWhitespace?: boolean;
defaultEOL?: DefaultEndOfLine; defaultEOL?: DefaultEndOfLine;
...@@ -33,6 +34,7 @@ export function createTextModel(text: string, _options: IRelaxedTextModelCreatio ...@@ -33,6 +34,7 @@ export function createTextModel(text: string, _options: IRelaxedTextModelCreatio
tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize), tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize),
indentSize: (typeof _options.indentSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.indentSize : _options.indentSize), indentSize: (typeof _options.indentSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.indentSize : _options.indentSize),
insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces), insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces),
atomicSoftTabs: (typeof _options.atomicSoftTabs === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.atomicSoftTabs : _options.atomicSoftTabs),
detectIndentation: (typeof _options.detectIndentation === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.detectIndentation : _options.detectIndentation), detectIndentation: (typeof _options.detectIndentation === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.detectIndentation : _options.detectIndentation),
trimAutoWhitespace: (typeof _options.trimAutoWhitespace === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.trimAutoWhitespace : _options.trimAutoWhitespace), trimAutoWhitespace: (typeof _options.trimAutoWhitespace === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.trimAutoWhitespace : _options.trimAutoWhitespace),
defaultEOL: (typeof _options.defaultEOL === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL : _options.defaultEOL), defaultEOL: (typeof _options.defaultEOL === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.defaultEOL : _options.defaultEOL),
......
...@@ -1095,6 +1095,11 @@ declare namespace monaco.editor { ...@@ -1095,6 +1095,11 @@ declare namespace monaco.editor {
* Defaults to true. * Defaults to true.
*/ */
insertSpaces?: boolean; insertSpaces?: boolean;
/**
* Treat soft tabs like hard tabs.
* Defaults to false.
*/
atomicSoftTabs?: boolean;
/** /**
* Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents. * Controls whether `tabSize` and `insertSpaces` will be automatically detected when a file is opened based on the file contents.
* Defaults to true. * Defaults to true.
...@@ -1575,6 +1580,7 @@ declare namespace monaco.editor { ...@@ -1575,6 +1580,7 @@ declare namespace monaco.editor {
readonly tabSize: number; readonly tabSize: number;
readonly indentSize: number; readonly indentSize: number;
readonly insertSpaces: boolean; readonly insertSpaces: boolean;
readonly atomicSoftTabs: boolean;
readonly defaultEOL: DefaultEndOfLine; readonly defaultEOL: DefaultEndOfLine;
readonly trimAutoWhitespace: boolean; readonly trimAutoWhitespace: boolean;
} }
...@@ -1583,6 +1589,7 @@ declare namespace monaco.editor { ...@@ -1583,6 +1589,7 @@ declare namespace monaco.editor {
tabSize?: number; tabSize?: number;
indentSize?: number; indentSize?: number;
insertSpaces?: boolean; insertSpaces?: boolean;
atomicSoftTabs?: boolean;
trimAutoWhitespace?: boolean; trimAutoWhitespace?: boolean;
} }
...@@ -2452,6 +2459,7 @@ declare namespace monaco.editor { ...@@ -2452,6 +2459,7 @@ declare namespace monaco.editor {
readonly tabSize: boolean; readonly tabSize: boolean;
readonly indentSize: boolean; readonly indentSize: boolean;
readonly insertSpaces: boolean; readonly insertSpaces: boolean;
readonly atomicSoftTabs: boolean;
readonly trimAutoWhitespace: boolean; readonly trimAutoWhitespace: boolean;
} }
......
...@@ -655,6 +655,12 @@ declare module 'vscode' { ...@@ -655,6 +655,12 @@ declare module 'vscode' {
*/ */
insertSpaces?: boolean | string; insertSpaces?: boolean | string;
/**
* When navigating treat soft tabs like hard tabs. This means you can't position
* the cursor in the middle of an indentation, even if it is made of space.
*/
atomicSoftTabs?: boolean;
/** /**
* The rendering style of the cursor in this editor. * The rendering style of the cursor in this editor.
* When getting a text editor's options, this property will always be present. * When getting a text editor's options, this property will always be present.
......
...@@ -80,6 +80,7 @@ export class MainThreadTextEditorProperties { ...@@ -80,6 +80,7 @@ export class MainThreadTextEditorProperties {
insertSpaces: modelOptions.insertSpaces, insertSpaces: modelOptions.insertSpaces,
tabSize: modelOptions.tabSize, tabSize: modelOptions.tabSize,
indentSize: modelOptions.indentSize, indentSize: modelOptions.indentSize,
atomicSoftTabs: modelOptions.atomicSoftTabs,
cursorStyle: cursorStyle, cursorStyle: cursorStyle,
lineNumbers: lineNumbers lineNumbers: lineNumbers
}; };
...@@ -148,6 +149,7 @@ export class MainThreadTextEditorProperties { ...@@ -148,6 +149,7 @@ export class MainThreadTextEditorProperties {
a.tabSize === b.tabSize a.tabSize === b.tabSize
&& a.indentSize === b.indentSize && a.indentSize === b.indentSize
&& a.insertSpaces === b.insertSpaces && a.insertSpaces === b.insertSpaces
&& a.atomicSoftTabs === b.atomicSoftTabs
&& a.cursorStyle === b.cursorStyle && a.cursorStyle === b.cursorStyle
&& a.lineNumbers === b.lineNumbers && a.lineNumbers === b.lineNumbers
); );
...@@ -374,6 +376,9 @@ export class MainThreadTextEditor { ...@@ -374,6 +376,9 @@ export class MainThreadTextEditor {
if (typeof newConfiguration.insertSpaces !== 'undefined') { if (typeof newConfiguration.insertSpaces !== 'undefined') {
newOpts.insertSpaces = newConfiguration.insertSpaces; newOpts.insertSpaces = newConfiguration.insertSpaces;
} }
if (typeof newConfiguration.atomicSoftTabs !== 'undefined') {
newOpts.atomicSoftTabs = newConfiguration.atomicSoftTabs;
}
if (typeof newConfiguration.tabSize !== 'undefined') { if (typeof newConfiguration.tabSize !== 'undefined') {
newOpts.tabSize = newConfiguration.tabSize; newOpts.tabSize = newConfiguration.tabSize;
} }
......
...@@ -233,6 +233,7 @@ export interface ITextEditorConfigurationUpdate { ...@@ -233,6 +233,7 @@ export interface ITextEditorConfigurationUpdate {
tabSize?: number | 'auto'; tabSize?: number | 'auto';
indentSize?: number | 'tabSize'; indentSize?: number | 'tabSize';
insertSpaces?: boolean | 'auto'; insertSpaces?: boolean | 'auto';
atomicSoftTabs?: boolean;
cursorStyle?: TextEditorCursorStyle; cursorStyle?: TextEditorCursorStyle;
lineNumbers?: RenderLineNumbersType; lineNumbers?: RenderLineNumbersType;
} }
...@@ -241,6 +242,7 @@ export interface IResolvedTextEditorConfiguration { ...@@ -241,6 +242,7 @@ export interface IResolvedTextEditorConfiguration {
tabSize: number; tabSize: number;
indentSize: number; indentSize: number;
insertSpaces: boolean; insertSpaces: boolean;
atomicSoftTabs: boolean;
cursorStyle: TextEditorCursorStyle; cursorStyle: TextEditorCursorStyle;
lineNumbers: RenderLineNumbersType; lineNumbers: RenderLineNumbersType;
} }
......
...@@ -143,6 +143,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { ...@@ -143,6 +143,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
private _tabSize!: number; private _tabSize!: number;
private _indentSize!: number; private _indentSize!: number;
private _insertSpaces!: boolean; private _insertSpaces!: boolean;
private _atomicSoftTabs!: boolean;
private _cursorStyle!: TextEditorCursorStyle; private _cursorStyle!: TextEditorCursorStyle;
private _lineNumbers!: TextEditorLineNumbersStyle; private _lineNumbers!: TextEditorLineNumbersStyle;
...@@ -157,6 +158,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { ...@@ -157,6 +158,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
this._tabSize = source.tabSize; this._tabSize = source.tabSize;
this._indentSize = source.indentSize; this._indentSize = source.indentSize;
this._insertSpaces = source.insertSpaces; this._insertSpaces = source.insertSpaces;
this._atomicSoftTabs = source.atomicSoftTabs;
this._cursorStyle = source.cursorStyle; this._cursorStyle = source.cursorStyle;
this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers); this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers);
} }
...@@ -269,6 +271,23 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions { ...@@ -269,6 +271,23 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
})); }));
} }
public get atomicSoftTabs(): boolean {
return this._atomicSoftTabs;
}
public set atomicSoftTabs(value: boolean) {
const atomicSoftTabs = value;
if (this._atomicSoftTabs === atomicSoftTabs) {
// nothing to do
return;
}
// reflect the new atomicSoftTabs value immediately
this._atomicSoftTabs = atomicSoftTabs;
this._warnOnError(this._proxy.$trySetOptions(this._id, {
atomicSoftTabs
}));
}
public get cursorStyle(): TextEditorCursorStyle { public get cursorStyle(): TextEditorCursorStyle {
return this._cursorStyle; return this._cursorStyle;
} }
...@@ -659,4 +678,3 @@ export class ExtHostTextEditor implements vscode.TextEditor { ...@@ -659,4 +678,3 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}); });
} }
} }
...@@ -20,7 +20,7 @@ suite('ExtHostTextEditor', () => { ...@@ -20,7 +20,7 @@ suite('ExtHostTextEditor', () => {
], '\n', 1, 'text', false); ], '\n', 1, 'text', false);
setup(() => { setup(() => {
editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1);
}); });
test('disposed editor', () => { test('disposed editor', () => {
...@@ -47,7 +47,7 @@ suite('ExtHostTextEditor', () => { ...@@ -47,7 +47,7 @@ suite('ExtHostTextEditor', () => {
applyCount += 1; applyCount += 1;
return Promise.resolve(true); return Promise.resolve(true);
} }
}, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1); }, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, atomicSoftTabs: false, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1);
await editor.edit(edit => { }); await editor.edit(edit => { });
assert.equal(applyCount, 0); assert.equal(applyCount, 0);
...@@ -91,6 +91,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -91,6 +91,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}, new NullLogService()); }, new NullLogService());
...@@ -106,6 +107,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -106,6 +107,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: opts.tabSize, tabSize: opts.tabSize,
indentSize: opts.indentSize, indentSize: opts.indentSize,
insertSpaces: opts.insertSpaces, insertSpaces: opts.insertSpaces,
atomicSoftTabs: opts.atomicSoftTabs,
cursorStyle: opts.cursorStyle, cursorStyle: opts.cursorStyle,
lineNumbers: opts.lineNumbers lineNumbers: opts.lineNumbers
}; };
...@@ -118,6 +120,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -118,6 +120,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -130,6 +133,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -130,6 +133,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 1, tabSize: 1,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -142,6 +146,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -142,6 +146,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 2, tabSize: 2,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -154,6 +159,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -154,6 +159,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 2, tabSize: 2,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -166,6 +172,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -166,6 +172,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -178,6 +185,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -178,6 +185,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -190,6 +198,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -190,6 +198,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -202,6 +211,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -202,6 +211,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -214,6 +224,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -214,6 +224,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -226,6 +237,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -226,6 +237,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -238,6 +250,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -238,6 +250,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 1, indentSize: 1,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -250,6 +263,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -250,6 +263,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 2, indentSize: 2,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -262,6 +276,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -262,6 +276,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 2, indentSize: 2,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -274,6 +289,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -274,6 +289,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -286,6 +302,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -286,6 +302,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -298,6 +315,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -298,6 +315,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -310,6 +328,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -310,6 +328,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -322,6 +341,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -322,6 +341,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -334,6 +354,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -334,6 +354,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -346,6 +367,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -346,6 +367,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -358,6 +380,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -358,6 +380,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: true, insertSpaces: true,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -370,6 +393,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -370,6 +393,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -382,6 +406,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -382,6 +406,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: true, insertSpaces: true,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -394,6 +419,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -394,6 +419,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -406,6 +432,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -406,6 +432,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -418,6 +445,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -418,6 +445,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Block, cursorStyle: TextEditorCursorStyle.Block,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -430,6 +458,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -430,6 +458,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -442,6 +471,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -442,6 +471,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.Off lineNumbers: RenderLineNumbersType.Off
}); });
...@@ -452,6 +482,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -452,6 +482,7 @@ suite('ExtHostTextEditorOptions', () => {
opts.assign({ opts.assign({
tabSize: 4, tabSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: TextEditorLineNumbersStyle.On lineNumbers: TextEditorLineNumbersStyle.On
}); });
...@@ -459,6 +490,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -459,6 +490,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -474,6 +506,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -474,6 +506,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: true, insertSpaces: true,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -489,6 +522,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -489,6 +522,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 3, tabSize: 3,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Line, cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On lineNumbers: RenderLineNumbersType.On
}); });
...@@ -504,6 +538,7 @@ suite('ExtHostTextEditorOptions', () => { ...@@ -504,6 +538,7 @@ suite('ExtHostTextEditorOptions', () => {
tabSize: 4, tabSize: 4,
indentSize: 4, indentSize: 4,
insertSpaces: false, insertSpaces: false,
atomicSoftTabs: false,
cursorStyle: TextEditorCursorStyle.Block, cursorStyle: TextEditorCursorStyle.Block,
lineNumbers: RenderLineNumbersType.Relative lineNumbers: RenderLineNumbersType.Relative
}); });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册