From 57917f7fc8a9f70f9a1792fd40cab3af3fea8da3 Mon Sep 17 00:00:00 2001 From: vince-fugnitto Date: Wed, 11 Dec 2019 18:28:07 -0500 Subject: [PATCH] Fix indentation when using preferences tree Fixes #5052 - fixes the indentation when updating/setting a preference using the `preferences-tree` widget. - the current implementation had a hardcoded value of `tabSize`=3 and `insertSpaces`=true which meant that if the `settings.json` file had different formatting, it would insert incorrectly. - added a new method `detectIndentation` which attempts to detect the current indentation (tabSize and indent type) based on the content of the file. Signed-off-by: vince-fugnitto --- .../abstract-resource-preference-provider.ts | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/preferences/src/browser/abstract-resource-preference-provider.ts b/packages/preferences/src/browser/abstract-resource-preference-provider.ts index d73c5ea13dc79..2fb665c2984ef 100644 --- a/packages/preferences/src/browser/abstract-resource-preference-provider.ts +++ b/packages/preferences/src/browser/abstract-resource-preference-provider.ts @@ -23,6 +23,7 @@ import { MessageService, Resource, ResourceProvider, Disposable } from '@theia/c import { PreferenceProvider, PreferenceSchemaProvider, PreferenceScope, PreferenceProviderDataChange } from '@theia/core/lib/browser'; import URI from '@theia/core/lib/common/uri'; import { PreferenceConfigurations } from '@theia/core/lib/browser/preferences/preference-configurations'; +import { EditorManager, TextEditorDocument } from '@theia/editor/lib/browser'; @injectable() export abstract class AbstractResourcePreferenceProvider extends PreferenceProvider { @@ -30,6 +31,7 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi protected preferences: { [key: string]: any } = {}; protected resource: Promise; + @inject(EditorManager) protected readonly editorManager: EditorManager; @inject(ResourceProvider) protected readonly resourceProvider: ResourceProvider; @inject(MessageService) protected readonly messageService: MessageService; @inject(PreferenceSchemaProvider) protected readonly schemaProvider: PreferenceSchemaProvider; @@ -102,9 +104,15 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi return true; } try { + const editor = await this.editorManager.getByUri(new URI(resourceUri!)); + let tabSize: number = 0; + let insertSpaces: boolean = true; + if (editor) { + [tabSize, insertSpaces] = this.detectIndentation(editor.editor.document); + } let newContent = ''; if (path.length || value !== undefined) { - const formattingOptions = { tabSize: 3, insertSpaces: true, eol: '' }; + const formattingOptions = { tabSize, insertSpaces, eol: '' }; const edits = jsoncparser.modify(content, path, value, { formattingOptions }); newContent = jsoncparser.applyEdits(content, edits); } @@ -221,4 +229,33 @@ export abstract class AbstractResourcePreferenceProvider extends PreferenceProvi } } + /** + * Detect the minimum indentation and type of indentation to be used + * as formatting options when using `jsoncparser`. + * @param text the preference text editor document. + * + * @returns a tuple representing the indentation size, and if it spaces. + */ + protected detectIndentation(text: TextEditorDocument): [number, boolean] { + // Get the number of lines present in the text document. + const lineCount = text.lineCount; + // Store the current index which will be used iterate over the document. + let index = 0; + // Iterate over the each line in the text document, getting the first indentation that is not zero. + while (index < lineCount) { + // Get the line content of the document a the given index. + const line = text.getLineContent(index + 1); + // Determine how many leading spaces are present in the document. + const indentation = line.search(/\S|$/); + // Return the first non-zero indentation. + if (indentation > 0) { + // Determine if the line is indented with spaces or tabs. + const isSpaces = !line.startsWith('\t'); + return [indentation, isSpaces]; + } + index++; + } + return [0, true]; + } + }