From 9f6e7a7e9f614a47ca88cf6b26b820593e8e12d1 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 23 Aug 2021 15:21:51 +0200 Subject: [PATCH] Implements language configurable colorizedBracketPairs property. --- extensions/html/language-configuration.json | 4 ++ .../tags-language-configuration.json | 5 +++ .../model/bracketPairColorizer/brackets.ts | 15 ++------ .../common/modes/languageConfiguration.ts | 6 ++- .../modes/languageConfigurationRegistry.ts | 7 +++- .../common/modes/supports/characterPair.ts | 15 +++++++- src/vs/monaco.d.ts | 5 +++ .../languageConfigurationExtensionPoint.ts | 38 +++++++++++++++++++ 8 files changed, 81 insertions(+), 14 deletions(-) diff --git a/extensions/html/language-configuration.json b/extensions/html/language-configuration.json index 51e103a6926..7144df93b2a 100644 --- a/extensions/html/language-configuration.json +++ b/extensions/html/language-configuration.json @@ -24,6 +24,10 @@ { "open": "(", "close": ")" }, { "open": "<", "close": ">" } ], + "colorizedBracketPairs": [ + ["{", "}"], + ["(", ")"] + ], "folding": { "markers": { "start": "^\\s*", diff --git a/extensions/javascript/tags-language-configuration.json b/extensions/javascript/tags-language-configuration.json index fa04cf1756f..0d5bcc51ccf 100644 --- a/extensions/javascript/tags-language-configuration.json +++ b/extensions/javascript/tags-language-configuration.json @@ -8,6 +8,11 @@ ["(", ")"], ["<", ">"] ], + "colorizedBracketPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], "autoClosingPairs": [ { "open": "{", "close": "}" }, { "open": "[", "close": "]" }, diff --git a/src/vs/editor/common/model/bracketPairColorizer/brackets.ts b/src/vs/editor/common/model/bracketPairColorizer/brackets.ts index 2a80b49af6c..1a8f21d2673 100644 --- a/src/vs/editor/common/model/bracketPairColorizer/brackets.ts +++ b/src/vs/editor/common/model/bracketPairColorizer/brackets.ts @@ -12,22 +12,15 @@ import { Token, TokenKind } from './tokenizer'; export class BracketTokens { static createFromLanguage(languageId: LanguageId, customBracketPairs: readonly [string, string][]): BracketTokens { - const brackets = [...(LanguageConfigurationRegistry.getBracketsSupport(languageId)?.brackets || [])]; + const brackets = [...(LanguageConfigurationRegistry.getColorizedBracketPairs(languageId))]; const tokens = new BracketTokens(); let idxOffset = 0; for (const pair of brackets) { - const brackets = [ - ...pair.open.map((value, idx) => ({ value, kind: TokenKind.OpeningBracket, idx: idx + idxOffset })), - ...pair.close.map((value, idx) => ({ value, kind: TokenKind.ClosingBracket, idx: idx + idxOffset })), - ]; - - idxOffset += Math.max(pair.open.length, pair.close.length); - - for (const bracket of brackets) { - tokens.addBracket(languageId, bracket.value, bracket.kind, bracket.idx); - } + tokens.addBracket(languageId, pair[0], TokenKind.OpeningBracket, idxOffset); + tokens.addBracket(languageId, pair[1], TokenKind.ClosingBracket, idxOffset); + idxOffset++; } for (const pair of customBracketPairs) { diff --git a/src/vs/editor/common/modes/languageConfiguration.ts b/src/vs/editor/common/modes/languageConfiguration.ts index 3095d806b39..f345fcb8485 100644 --- a/src/vs/editor/common/modes/languageConfiguration.ts +++ b/src/vs/editor/common/modes/languageConfiguration.ts @@ -60,7 +60,11 @@ export interface LanguageConfiguration { * settings will be used. */ surroundingPairs?: IAutoClosingPair[]; - + /** + * Defines a list of bracket pairs that are colorized depending on their nesting level. + * If not set, the configured brackets will be used. + */ + colorizedBracketPairs?: CharacterPair[]; /** * Defines what characters must be after the cursor for bracket or quote autoclosing to occur when using the \'languageDefined\' autoclosing setting. * diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index 53960efcbd0..7e6e3b7258b 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -11,7 +11,7 @@ import { Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper'; import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; -import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional, CompleteEnterAction, AutoClosingPairs } from 'vs/editor/common/modes/languageConfiguration'; +import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional, CompleteEnterAction, AutoClosingPairs, CharacterPair } from 'vs/editor/common/modes/languageConfiguration'; import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports'; import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair'; import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter'; @@ -198,6 +198,7 @@ class LanguageConfigurationEntries { result.surroundingPairs = conf.surroundingPairs || result.surroundingPairs; result.autoCloseBefore = conf.autoCloseBefore || result.autoCloseBefore; result.folding = conf.folding || result.folding; + result.colorizedBracketPairs = conf.colorizedBracketPairs || result.colorizedBracketPairs; result.__electricCharacterSupport = conf.__electricCharacterSupport || result.__electricCharacterSupport; } return result; @@ -827,6 +828,10 @@ export class LanguageConfigurationRegistryImpl { } return value.brackets || null; } + + public getColorizedBracketPairs(languageId: LanguageId): CharacterPair[] { + return this._getRichEditSupport(languageId)?.characterPair.getColorizedBrackets() || []; + } } export const LanguageConfigurationRegistry = new LanguageConfigurationRegistryImpl(); diff --git a/src/vs/editor/common/modes/supports/characterPair.ts b/src/vs/editor/common/modes/supports/characterPair.ts index b7cfa2ecdd7..1999d082ad7 100644 --- a/src/vs/editor/common/modes/supports/characterPair.ts +++ b/src/vs/editor/common/modes/supports/characterPair.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IAutoClosingPair, StandardAutoClosingPairConditional, LanguageConfiguration } from 'vs/editor/common/modes/languageConfiguration'; +import { IAutoClosingPair, StandardAutoClosingPairConditional, LanguageConfiguration, CharacterPair } from 'vs/editor/common/modes/languageConfiguration'; import { ScopedLineTokens } from 'vs/editor/common/modes/supports'; export class CharacterPairSupport { @@ -14,6 +14,7 @@ export class CharacterPairSupport { private readonly _autoClosingPairs: StandardAutoClosingPairConditional[]; private readonly _surroundingPairs: IAutoClosingPair[]; private readonly _autoCloseBefore: string; + private readonly _colorizedBracketPairs: CharacterPair[]; constructor(config: LanguageConfiguration) { if (config.autoClosingPairs) { @@ -24,6 +25,14 @@ export class CharacterPairSupport { this._autoClosingPairs = []; } + if (config.colorizedBracketPairs) { + this._colorizedBracketPairs = config.colorizedBracketPairs.map(b => [b[0], b[1]]); + } else if (config.brackets) { + this._colorizedBracketPairs = config.brackets.map(b => [b[0], b[1]]); + } else { + this._colorizedBracketPairs = []; + } + if (config.__electricCharacterSupport && config.__electricCharacterSupport.docComment) { const docComment = config.__electricCharacterSupport.docComment; // IDocComment is legacy, only partially supported @@ -57,4 +66,8 @@ export class CharacterPairSupport { public getSurroundingPairs(): IAutoClosingPair[] { return this._surroundingPairs; } + + public getColorizedBrackets(): CharacterPair[] { + return this._colorizedBracketPairs; + } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 3fc8c1656b2..aeb3ff6cb19 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5503,6 +5503,11 @@ declare namespace monaco.languages { * settings will be used. */ surroundingPairs?: IAutoClosingPair[]; + /** + * Defines a list of bracket pairs that are colorized depending on their nesting level. + * If not set, the configured brackets will be used. + */ + colorizedBracketPairs?: CharacterPair[]; /** * Defines what characters must be after the cursor for bracket or quote autoclosing to occur when using the \'languageDefined\' autoclosing setting. * diff --git a/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts b/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts index 65af515c377..c0de661e52d 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint.ts @@ -49,6 +49,7 @@ interface ILanguageConfiguration { brackets?: CharacterPair[]; autoClosingPairs?: Array; surroundingPairs?: Array; + colorizedBracketPairs?: Array; wordPattern?: string | IRegExp; indentationRules?: IIndentationRules; folding?: FoldingRules; @@ -268,6 +269,30 @@ export class LanguageConfigurationFileHandler { return result; } + private _extractValidColorizedBracketPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CharacterPair[] | null { + const source = configuration.colorizedBracketPairs; + if (typeof source === 'undefined') { + return null; + } + if (!Array.isArray(source)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`colorizedBracketPairs\` to be an array.`); + return null; + } + + let result: CharacterPair[] | null = null; + for (let i = 0, len = source.length; i < len; i++) { + const pair = source[i]; + if (!isCharacterPair(pair)) { + console.warn(`[${languageIdentifier.language}]: language configuration: expected \`colorizedBracketPairs[${i}]\` to be an array of two strings.`); + continue; + } + result = result || []; + result.push([pair[0], pair[1]]); + + } + return result; + } + private _extractValidOnEnterRules(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): OnEnterRule[] | null { const source = configuration.onEnterRules; if (typeof source === 'undefined') { @@ -365,6 +390,11 @@ export class LanguageConfigurationFileHandler { richEditConfig.surroundingPairs = surroundingPairs; } + const colorizedBracketPairs = this._extractValidColorizedBracketPairs(languageIdentifier, configuration); + if (colorizedBracketPairs) { + richEditConfig.colorizedBracketPairs = colorizedBracketPairs; + } + const autoCloseBefore = configuration.autoCloseBefore; if (typeof autoCloseBefore === 'string') { richEditConfig.autoCloseBefore = autoCloseBefore; @@ -521,6 +551,14 @@ const schema: IJSONSchema = { $ref: '#definitions/bracketPair' } }, + colorizedBracketPairs: { + default: [['(', ')'], ['[', ']'], ['{', '}']], + description: nls.localize('schema.colorizedBracketPairs', 'Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.'), + type: 'array', + items: { + $ref: '#definitions/bracketPair' + } + }, autoClosingPairs: { default: [['(', ')'], ['[', ']'], ['{', '}']], description: nls.localize('schema.autoClosingPairs', 'Defines the bracket pairs. When a opening bracket is entered, the closing bracket is inserted automatically.'),