Skip to content

Commit 207f26d

Browse files
authored
Merge pull request microsoft#166455 from microsoft/alex/pr-155450
Separate tab size and indent size (PR microsoft#155450)
2 parents 7c466b8 + 484e0cb commit 207f26d

File tree

12 files changed

+310
-42
lines changed

12 files changed

+310
-42
lines changed

src/vs/editor/common/config/editorConfigurationSchema.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ const editorConfiguration: IConfigurationNode = {
2626
minimum: 1,
2727
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#`')
2828
},
29-
// 'editor.indentSize': {
30-
// 'anyOf': [
31-
// {
32-
// type: 'string',
33-
// enum: ['tabSize']
34-
// },
35-
// {
36-
// type: 'number',
37-
// minimum: 1
38-
// }
39-
// ],
40-
// default: 'tabSize',
41-
// 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.")
42-
// },
29+
'editor.indentSize': {
30+
'anyOf': [
31+
{
32+
type: 'string',
33+
enum: ['tabSize']
34+
},
35+
{
36+
type: 'number',
37+
minimum: 1
38+
}
39+
],
40+
default: 'tabSize',
41+
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.")
42+
},
4343
'editor.insertSpaces': {
4444
type: 'boolean',
4545
default: EDITOR_MODEL_DEFAULTS.insertSpaces,

src/vs/editor/common/model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ export class TextModelResolvedOptions {
440440
bracketPairColorizationOptions: BracketPairColorizationOptions;
441441
}) {
442442
this.tabSize = Math.max(1, src.tabSize | 0);
443-
this.indentSize = src.tabSize | 0;
443+
this.indentSize = Math.max(1, src.indentSize | 0);
444444
this.insertSpaces = Boolean(src.insertSpaces);
445445
this.defaultEOL = src.defaultEOL | 0;
446446
this.trimAutoWhitespace = Boolean(src.trimAutoWhitespace);

src/vs/editor/contrib/indentation/browser/indentation.ts

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ export class IndentationToTabsAction extends EditorAction {
208208

209209
export class ChangeIndentationSizeAction extends EditorAction {
210210

211-
constructor(private readonly insertSpaces: boolean, opts: IActionOptions) {
211+
constructor(private readonly insertSpaces: boolean, private readonly displaySizeOnly: boolean, opts: IActionOptions) {
212212
super(opts);
213213
}
214214

@@ -222,11 +222,20 @@ export class ChangeIndentationSizeAction extends EditorAction {
222222
}
223223

224224
const creationOpts = modelService.getCreationOptions(model.getLanguageId(), model.uri, model.isForSimpleWidget);
225+
const modelOpts = model.getOptions();
225226
const picks = [1, 2, 3, 4, 5, 6, 7, 8].map(n => ({
226227
id: n.toString(),
227228
label: n.toString(),
228229
// add description for tabSize value set in the configuration
229-
description: n === creationOpts.tabSize ? nls.localize('configuredTabSize', "Configured Tab Size") : undefined
230+
description: (
231+
n === creationOpts.tabSize && n === modelOpts.tabSize
232+
? nls.localize('configuredTabSize', "Configured Tab Size")
233+
: n === creationOpts.tabSize
234+
? nls.localize('defaultTabSize', "Default Tab Size")
235+
: n === modelOpts.tabSize
236+
? nls.localize('currentTabSize', "Current Tab Size")
237+
: undefined
238+
)
230239
}));
231240

232241
// auto focus the tabSize set for the current editor
@@ -236,10 +245,18 @@ export class ChangeIndentationSizeAction extends EditorAction {
236245
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 => {
237246
if (pick) {
238247
if (model && !model.isDisposed()) {
239-
model.updateOptions({
240-
tabSize: parseInt(pick.label, 10),
241-
insertSpaces: this.insertSpaces
242-
});
248+
const pickedVal = parseInt(pick.label, 10);
249+
if (this.displaySizeOnly) {
250+
model.updateOptions({
251+
tabSize: pickedVal
252+
});
253+
} else {
254+
model.updateOptions({
255+
tabSize: this.insertSpaces ? undefined : pickedVal,
256+
indentSize: pickedVal,
257+
insertSpaces: this.insertSpaces
258+
});
259+
}
243260
}
244261
}
245262
});
@@ -252,7 +269,7 @@ export class IndentUsingTabs extends ChangeIndentationSizeAction {
252269
public static readonly ID = 'editor.action.indentUsingTabs';
253270

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

268285
constructor() {
269-
super(true, {
286+
super(true, false, {
270287
id: IndentUsingSpaces.ID,
271288
label: nls.localize('indentUsingSpaces', "Indent Using Spaces"),
272289
alias: 'Indent Using Spaces',
@@ -275,6 +292,20 @@ export class IndentUsingSpaces extends ChangeIndentationSizeAction {
275292
}
276293
}
277294

295+
export class ChangeTabDisplaySize extends ChangeIndentationSizeAction {
296+
297+
public static readonly ID = 'editor.action.changeTabDisplaySize';
298+
299+
constructor() {
300+
super(true, true, {
301+
id: ChangeTabDisplaySize.ID,
302+
label: nls.localize('changeTabDisplaySize', "Change Tab Display Size"),
303+
alias: 'Change Tab Display Size',
304+
precondition: undefined
305+
});
306+
}
307+
}
308+
278309
export class DetectIndentation extends EditorAction {
279310

280311
public static readonly ID = 'editor.action.detectIndentation';
@@ -694,6 +725,7 @@ registerEditorAction(IndentationToSpacesAction);
694725
registerEditorAction(IndentationToTabsAction);
695726
registerEditorAction(IndentUsingTabs);
696727
registerEditorAction(IndentUsingSpaces);
728+
registerEditorAction(ChangeTabDisplaySize);
697729
registerEditorAction(DetectIndentation);
698730
registerEditorAction(ReindentLinesAction);
699731
registerEditorAction(ReindentSelectedLinesAction);

src/vs/editor/contrib/snippet/test/browser/snippetSession.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ suite('SnippetSession', function () {
706706
test('Tabs don\'t get replaced with spaces in snippet transformations #103818', function () {
707707
const model = editor.getModel()!;
708708
model.setValue('\n{\n \n}');
709-
model.updateOptions({ insertSpaces: true, tabSize: 2 });
709+
model.updateOptions({ insertSpaces: true, indentSize: 2 });
710710
editor.setSelections([new Selection(1, 1, 1, 1), new Selection(3, 6, 3, 6)]);
711711
const session = new SnippetSession(editor, [
712712
'function animate () {',

src/vs/editor/test/common/model/textModelWithTokens.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ suite('TextModelWithTokens regression tests', () => {
699699
});
700700

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

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

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

src/vs/workbench/api/browser/mainThreadEditor.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export class MainThreadTextEditorProperties {
8080
return {
8181
insertSpaces: modelOptions.insertSpaces,
8282
tabSize: modelOptions.tabSize,
83+
indentSize: modelOptions.indentSize,
8384
cursorStyle: cursorStyle,
8485
lineNumbers: lineNumbers
8586
};
@@ -146,6 +147,7 @@ export class MainThreadTextEditorProperties {
146147
}
147148
return (
148149
a.tabSize === b.tabSize
150+
&& a.indentSize === b.indentSize
149151
&& a.insertSpaces === b.insertSpaces
150152
&& a.cursorStyle === b.cursorStyle
151153
&& a.lineNumbers === b.lineNumbers
@@ -376,6 +378,13 @@ export class MainThreadTextEditor {
376378
if (typeof newConfiguration.tabSize !== 'undefined') {
377379
newOpts.tabSize = newConfiguration.tabSize;
378380
}
381+
if (typeof newConfiguration.indentSize !== 'undefined') {
382+
if (newConfiguration.indentSize === 'tabSize') {
383+
newOpts.indentSize = newOpts.tabSize || creationOpts.tabSize;
384+
} else {
385+
newOpts.indentSize = newConfiguration.indentSize;
386+
}
387+
}
379388
this._model.updateOptions(newOpts);
380389
}
381390

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,15 @@ export interface MainThreadDocumentsShape extends IDisposable {
203203

204204
export interface ITextEditorConfigurationUpdate {
205205
tabSize?: number | 'auto';
206+
indentSize?: number | 'tabSize';
206207
insertSpaces?: boolean | 'auto';
207208
cursorStyle?: TextEditorCursorStyle;
208209
lineNumbers?: RenderLineNumbersType;
209210
}
210211

211212
export interface IResolvedTextEditorConfiguration {
212213
tabSize: number;
214+
indentSize: number;
213215
insertSpaces: boolean;
214216
cursorStyle: TextEditorCursorStyle;
215217
lineNumbers: RenderLineNumbersType;

src/vs/workbench/api/common/extHostTextEditor.ts

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export class ExtHostTextEditorOptions {
143143
private _logService: ILogService;
144144

145145
private _tabSize!: number;
146+
private _indentSize!: number;
146147
private _insertSpaces!: boolean;
147148
private _cursorStyle!: TextEditorCursorStyle;
148149
private _lineNumbers!: TextEditorLineNumbersStyle;
@@ -164,6 +165,12 @@ export class ExtHostTextEditorOptions {
164165
set tabSize(value: number | string) {
165166
that._setTabSize(value);
166167
},
168+
get indentSize(): number | 'tabSize' {
169+
return that._indentSize;
170+
},
171+
set indentSize(value: number | 'tabSize') {
172+
that._setIndentSize(value);
173+
},
167174
get insertSpaces(): boolean | string {
168175
return that._insertSpaces;
169176
},
@@ -187,6 +194,7 @@ export class ExtHostTextEditorOptions {
187194

188195
public _accept(source: IResolvedTextEditorConfiguration): void {
189196
this._tabSize = source.tabSize;
197+
this._indentSize = source.indentSize;
190198
this._insertSpaces = source.insertSpaces;
191199
this._cursorStyle = source.cursorStyle;
192200
this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers);
@@ -231,6 +239,45 @@ export class ExtHostTextEditorOptions {
231239
}));
232240
}
233241

242+
// --- internal: indentSize
243+
244+
private _validateIndentSize(value: number | string): number | 'tabSize' | null {
245+
if (value === 'tabSize') {
246+
return 'tabSize';
247+
}
248+
if (typeof value === 'number') {
249+
const r = Math.floor(value);
250+
return (r > 0 ? r : null);
251+
}
252+
if (typeof value === 'string') {
253+
const r = parseInt(value, 10);
254+
if (isNaN(r)) {
255+
return null;
256+
}
257+
return (r > 0 ? r : null);
258+
}
259+
return null;
260+
}
261+
262+
private _setIndentSize(value: number | string) {
263+
const indentSize = this._validateIndentSize(value);
264+
if (indentSize === null) {
265+
// ignore invalid call
266+
return;
267+
}
268+
if (typeof indentSize === 'number') {
269+
if (this._indentSize === indentSize) {
270+
// nothing to do
271+
return;
272+
}
273+
// reflect the new indentSize value immediately
274+
this._indentSize = indentSize;
275+
}
276+
this._warnOnError('setIndentSize', this._proxy.$trySetOptions(this._id, {
277+
indentSize: indentSize
278+
}));
279+
}
280+
234281
// --- internal: insert spaces
235282

236283
private _validateInsertSpaces(value: boolean | string): boolean | 'auto' {
@@ -298,18 +345,18 @@ export class ExtHostTextEditorOptions {
298345
}
299346
}
300347

301-
// if (typeof newOptions.indentSize !== 'undefined') {
302-
// const indentSize = this._validateIndentSize(newOptions.indentSize);
303-
// if (indentSize === 'tabSize') {
304-
// hasUpdate = true;
305-
// bulkConfigurationUpdate.indentSize = indentSize;
306-
// } else if (typeof indentSize === 'number' && this._indentSize !== indentSize) {
307-
// // reflect the new indentSize value immediately
308-
// this._indentSize = indentSize;
309-
// hasUpdate = true;
310-
// bulkConfigurationUpdate.indentSize = indentSize;
311-
// }
312-
// }
348+
if (typeof newOptions.indentSize !== 'undefined') {
349+
const indentSize = this._validateIndentSize(newOptions.indentSize);
350+
if (indentSize === 'tabSize') {
351+
hasUpdate = true;
352+
bulkConfigurationUpdate.indentSize = indentSize;
353+
} else if (typeof indentSize === 'number' && this._indentSize !== indentSize) {
354+
// reflect the new indentSize value immediately
355+
this._indentSize = indentSize;
356+
hasUpdate = true;
357+
bulkConfigurationUpdate.indentSize = indentSize;
358+
}
359+
}
313360

314361
if (typeof newOptions.insertSpaces !== 'undefined') {
315362
const insertSpaces = this._validateInsertSpaces(newOptions.insertSpaces);

0 commit comments

Comments
 (0)