Skip to content

Commit

Permalink
Merge pull request #166455 from microsoft/alex/pr-155450
Browse files Browse the repository at this point in the history
Separate tab size and indent size (PR #155450)
  • Loading branch information
alexdima authored Nov 16, 2022
2 parents 7c466b8 + 484e0cb commit 207f26d
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 42 deletions.
28 changes: 14 additions & 14 deletions src/vs/editor/common/config/editorConfigurationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ const editorConfiguration: IConfigurationNode = {
minimum: 1,
markdownDescription: nls.localize('tabSize', "The number of spaces a tab is equal to. This setting is overridden based on the file contents when {0} is on.", '`#editor.detectIndentation#`')
},
// 'editor.indentSize': {
// 'anyOf': [
// {
// type: 'string',
// enum: ['tabSize']
// },
// {
// type: 'number',
// minimum: 1
// }
// ],
// default: 'tabSize',
// markdownDescription: nls.localize('indentSize', "The number of spaces used for indentation or 'tabSize' to use the value from `#editor.tabSize#`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.")
// },
'editor.indentSize': {
'anyOf': [
{
type: 'string',
enum: ['tabSize']
},
{
type: 'number',
minimum: 1
}
],
default: 'tabSize',
markdownDescription: nls.localize('indentSize', "The number of spaces used for indentation or 'tabSize' to use the value from `#editor.tabSize#`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.")
},
'editor.insertSpaces': {
type: 'boolean',
default: EDITOR_MODEL_DEFAULTS.insertSpaces,
Expand Down
2 changes: 1 addition & 1 deletion src/vs/editor/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ export class TextModelResolvedOptions {
bracketPairColorizationOptions: BracketPairColorizationOptions;
}) {
this.tabSize = Math.max(1, src.tabSize | 0);
this.indentSize = src.tabSize | 0;
this.indentSize = Math.max(1, src.indentSize | 0);
this.insertSpaces = Boolean(src.insertSpaces);
this.defaultEOL = src.defaultEOL | 0;
this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);
Expand Down
48 changes: 40 additions & 8 deletions src/vs/editor/contrib/indentation/browser/indentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export class IndentationToTabsAction extends EditorAction {

export class ChangeIndentationSizeAction extends EditorAction {

constructor(private readonly insertSpaces: boolean, opts: IActionOptions) {
constructor(private readonly insertSpaces: boolean, private readonly displaySizeOnly: boolean, opts: IActionOptions) {
super(opts);
}

Expand All @@ -222,11 +222,20 @@ export class ChangeIndentationSizeAction extends EditorAction {
}

const creationOpts = modelService.getCreationOptions(model.getLanguageId(), model.uri, model.isForSimpleWidget);
const modelOpts = model.getOptions();
const picks = [1, 2, 3, 4, 5, 6, 7, 8].map(n => ({
id: n.toString(),
label: n.toString(),
// add description for tabSize value set in the configuration
description: n === creationOpts.tabSize ? nls.localize('configuredTabSize', "Configured Tab Size") : undefined
description: (
n === creationOpts.tabSize && n === modelOpts.tabSize
? nls.localize('configuredTabSize', "Configured Tab Size")
: n === creationOpts.tabSize
? nls.localize('defaultTabSize', "Default Tab Size")
: n === modelOpts.tabSize
? nls.localize('currentTabSize', "Current Tab Size")
: undefined
)
}));

// auto focus the tabSize set for the current editor
Expand All @@ -236,10 +245,18 @@ export class ChangeIndentationSizeAction extends EditorAction {
quickInputService.pick(picks, { placeHolder: nls.localize({ key: 'selectTabWidth', comment: ['Tab corresponds to the tab key'] }, "Select Tab Size for Current File"), activeItem: picks[autoFocusIndex] }).then(pick => {
if (pick) {
if (model && !model.isDisposed()) {
model.updateOptions({
tabSize: parseInt(pick.label, 10),
insertSpaces: this.insertSpaces
});
const pickedVal = parseInt(pick.label, 10);
if (this.displaySizeOnly) {
model.updateOptions({
tabSize: pickedVal
});
} else {
model.updateOptions({
tabSize: this.insertSpaces ? undefined : pickedVal,
indentSize: pickedVal,
insertSpaces: this.insertSpaces
});
}
}
}
});
Expand All @@ -252,7 +269,7 @@ export class IndentUsingTabs extends ChangeIndentationSizeAction {
public static readonly ID = 'editor.action.indentUsingTabs';

constructor() {
super(false, {
super(false, false, {
id: IndentUsingTabs.ID,
label: nls.localize('indentUsingTabs', "Indent Using Tabs"),
alias: 'Indent Using Tabs',
Expand All @@ -266,7 +283,7 @@ export class IndentUsingSpaces extends ChangeIndentationSizeAction {
public static readonly ID = 'editor.action.indentUsingSpaces';

constructor() {
super(true, {
super(true, false, {
id: IndentUsingSpaces.ID,
label: nls.localize('indentUsingSpaces', "Indent Using Spaces"),
alias: 'Indent Using Spaces',
Expand All @@ -275,6 +292,20 @@ export class IndentUsingSpaces extends ChangeIndentationSizeAction {
}
}

export class ChangeTabDisplaySize extends ChangeIndentationSizeAction {

public static readonly ID = 'editor.action.changeTabDisplaySize';

constructor() {
super(true, true, {
id: ChangeTabDisplaySize.ID,
label: nls.localize('changeTabDisplaySize', "Change Tab Display Size"),
alias: 'Change Tab Display Size',
precondition: undefined
});
}
}

export class DetectIndentation extends EditorAction {

public static readonly ID = 'editor.action.detectIndentation';
Expand Down Expand Up @@ -694,6 +725,7 @@ registerEditorAction(IndentationToSpacesAction);
registerEditorAction(IndentationToTabsAction);
registerEditorAction(IndentUsingTabs);
registerEditorAction(IndentUsingSpaces);
registerEditorAction(ChangeTabDisplaySize);
registerEditorAction(DetectIndentation);
registerEditorAction(ReindentLinesAction);
registerEditorAction(ReindentSelectedLinesAction);
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ suite('SnippetSession', function () {
test('Tabs don\'t get replaced with spaces in snippet transformations #103818', function () {
const model = editor.getModel()!;
model.setValue('\n{\n \n}');
model.updateOptions({ insertSpaces: true, tabSize: 2 });
model.updateOptions({ insertSpaces: true, indentSize: 2 });
editor.setSelections([new Selection(1, 1, 1, 1), new Selection(3, 6, 3, 6)]);
const session = new SnippetSession(editor, [
'function animate () {',
Expand Down
4 changes: 2 additions & 2 deletions src/vs/editor/test/common/model/textModelWithTokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ suite('TextModelWithTokens regression tests', () => {
});

suite('TextModel.getLineIndentGuide', () => {
function assertIndentGuides(lines: [number, number, number, number, string][], tabSize: number): void {
function assertIndentGuides(lines: [number, number, number, number, string][], indentSize: number): void {
const languageId = 'testLang';
const disposables = new DisposableStore();
const instantiationService = createModelServices(disposables);
Expand All @@ -708,7 +708,7 @@ suite('TextModel.getLineIndentGuide', () => {

const text = lines.map(l => l[4]).join('\n');
const model = disposables.add(instantiateTextModel(instantiationService, text, languageId));
model.updateOptions({ tabSize: tabSize });
model.updateOptions({ indentSize: indentSize });

const actualIndents = model.guides.getLinesIndentGuides(1, model.getLineCount());

Expand Down
9 changes: 9 additions & 0 deletions src/vs/workbench/api/browser/mainThreadEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class MainThreadTextEditorProperties {
return {
insertSpaces: modelOptions.insertSpaces,
tabSize: modelOptions.tabSize,
indentSize: modelOptions.indentSize,
cursorStyle: cursorStyle,
lineNumbers: lineNumbers
};
Expand Down Expand Up @@ -146,6 +147,7 @@ export class MainThreadTextEditorProperties {
}
return (
a.tabSize === b.tabSize
&& a.indentSize === b.indentSize
&& a.insertSpaces === b.insertSpaces
&& a.cursorStyle === b.cursorStyle
&& a.lineNumbers === b.lineNumbers
Expand Down Expand Up @@ -376,6 +378,13 @@ export class MainThreadTextEditor {
if (typeof newConfiguration.tabSize !== 'undefined') {
newOpts.tabSize = newConfiguration.tabSize;
}
if (typeof newConfiguration.indentSize !== 'undefined') {
if (newConfiguration.indentSize === 'tabSize') {
newOpts.indentSize = newOpts.tabSize || creationOpts.tabSize;
} else {
newOpts.indentSize = newConfiguration.indentSize;
}
}
this._model.updateOptions(newOpts);
}

Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,15 @@ export interface MainThreadDocumentsShape extends IDisposable {

export interface ITextEditorConfigurationUpdate {
tabSize?: number | 'auto';
indentSize?: number | 'tabSize';
insertSpaces?: boolean | 'auto';
cursorStyle?: TextEditorCursorStyle;
lineNumbers?: RenderLineNumbersType;
}

export interface IResolvedTextEditorConfiguration {
tabSize: number;
indentSize: number;
insertSpaces: boolean;
cursorStyle: TextEditorCursorStyle;
lineNumbers: RenderLineNumbersType;
Expand Down
71 changes: 59 additions & 12 deletions src/vs/workbench/api/common/extHostTextEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export class ExtHostTextEditorOptions {
private _logService: ILogService;

private _tabSize!: number;
private _indentSize!: number;
private _insertSpaces!: boolean;
private _cursorStyle!: TextEditorCursorStyle;
private _lineNumbers!: TextEditorLineNumbersStyle;
Expand All @@ -164,6 +165,12 @@ export class ExtHostTextEditorOptions {
set tabSize(value: number | string) {
that._setTabSize(value);
},
get indentSize(): number | 'tabSize' {
return that._indentSize;
},
set indentSize(value: number | 'tabSize') {
that._setIndentSize(value);
},
get insertSpaces(): boolean | string {
return that._insertSpaces;
},
Expand All @@ -187,6 +194,7 @@ export class ExtHostTextEditorOptions {

public _accept(source: IResolvedTextEditorConfiguration): void {
this._tabSize = source.tabSize;
this._indentSize = source.indentSize;
this._insertSpaces = source.insertSpaces;
this._cursorStyle = source.cursorStyle;
this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers);
Expand Down Expand Up @@ -231,6 +239,45 @@ export class ExtHostTextEditorOptions {
}));
}

// --- internal: indentSize

private _validateIndentSize(value: number | string): number | 'tabSize' | null {
if (value === 'tabSize') {
return 'tabSize';
}
if (typeof value === 'number') {
const r = Math.floor(value);
return (r > 0 ? r : null);
}
if (typeof value === 'string') {
const r = parseInt(value, 10);
if (isNaN(r)) {
return null;
}
return (r > 0 ? r : null);
}
return null;
}

private _setIndentSize(value: number | string) {
const indentSize = this._validateIndentSize(value);
if (indentSize === null) {
// ignore invalid call
return;
}
if (typeof indentSize === 'number') {
if (this._indentSize === indentSize) {
// nothing to do
return;
}
// reflect the new indentSize value immediately
this._indentSize = indentSize;
}
this._warnOnError('setIndentSize', this._proxy.$trySetOptions(this._id, {
indentSize: indentSize
}));
}

// --- internal: insert spaces

private _validateInsertSpaces(value: boolean | string): boolean | 'auto' {
Expand Down Expand Up @@ -298,18 +345,18 @@ export class ExtHostTextEditorOptions {
}
}

// if (typeof newOptions.indentSize !== 'undefined') {
// const indentSize = this._validateIndentSize(newOptions.indentSize);
// if (indentSize === 'tabSize') {
// hasUpdate = true;
// bulkConfigurationUpdate.indentSize = indentSize;
// } else if (typeof indentSize === 'number' && this._indentSize !== indentSize) {
// // reflect the new indentSize value immediately
// this._indentSize = indentSize;
// hasUpdate = true;
// bulkConfigurationUpdate.indentSize = indentSize;
// }
// }
if (typeof newOptions.indentSize !== 'undefined') {
const indentSize = this._validateIndentSize(newOptions.indentSize);
if (indentSize === 'tabSize') {
hasUpdate = true;
bulkConfigurationUpdate.indentSize = indentSize;
} else if (typeof indentSize === 'number' && this._indentSize !== indentSize) {
// reflect the new indentSize value immediately
this._indentSize = indentSize;
hasUpdate = true;
bulkConfigurationUpdate.indentSize = indentSize;
}
}

if (typeof newOptions.insertSpaces !== 'undefined') {
const insertSpaces = this._validateInsertSpaces(newOptions.insertSpaces);
Expand Down
Loading

0 comments on commit 207f26d

Please sign in to comment.