From 8346bdc04d5bbaad133c6377bf8863a2d298d55a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Dec 2019 02:17:50 +0100 Subject: Rearrange code --- editors/code/src/ctx.ts | 2 +- editors/code/src/highlighting.ts | 211 +++++++++++++++++++-------------------- 2 files changed, 106 insertions(+), 107 deletions(-) (limited to 'editors') diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 39eddfcbd..30dd9811c 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -65,7 +65,7 @@ export class Ctx { async sendRequestWithRetry( method: string, param: any, - token: vscode.CancellationToken, + token?: vscode.CancellationToken, ): Promise { await this.client.onReady(); for (const delay of [2, 4, 6, 8, 10, null]) { diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 247673b5c..4c2e7f67b 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -47,7 +47,7 @@ export function activateHighlighting(ctx: Ctx) { const params: lc.TextDocumentIdentifier = { uri: editor.document.uri.toString(), }; - const decorations = await ctx.client.sendRequest( + const decorations = await ctx.sendRequestWithRetry( 'rust-analyzer/decorationsRequest', params, ); @@ -62,7 +62,7 @@ interface PublishDecorationsParams { decorations: Decoration[]; } -export interface Decoration { +interface Decoration { range: lc.Range; tag: string; bindingHash?: string; @@ -81,116 +81,17 @@ function fancify(seed: string, shade: 'light' | 'dark') { return `hsl(${h},${s}%,${l}%)`; } -function createDecorationFromTextmate( - themeStyle: scopes.TextMateRuleSettings, -): vscode.TextEditorDecorationType { - const decorationOptions: vscode.DecorationRenderOptions = {}; - decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; - - if (themeStyle.foreground) { - decorationOptions.color = themeStyle.foreground; - } - - if (themeStyle.background) { - decorationOptions.backgroundColor = themeStyle.background; - } - - if (themeStyle.fontStyle) { - const parts: string[] = themeStyle.fontStyle.split(' '); - parts.forEach(part => { - switch (part) { - case 'italic': - decorationOptions.fontStyle = 'italic'; - break; - case 'bold': - decorationOptions.fontWeight = 'bold'; - break; - case 'underline': - decorationOptions.textDecoration = 'underline'; - break; - default: - break; - } - }); - } - return vscode.window.createTextEditorDecorationType(decorationOptions); -} - class Highlighter { private ctx: Ctx; - - constructor(ctx: Ctx) { - this.ctx = ctx; - } - - private static initDecorations(): Map< - string, - vscode.TextEditorDecorationType - > { - const decoration = ( - tag: string, - textDecoration?: string, - ): [string, vscode.TextEditorDecorationType] => { - const rule = scopesMapper.toRule(tag, scopes.find); - - if (rule) { - const decor = createDecorationFromTextmate(rule); - return [tag, decor]; - } else { - const fallBackTag = 'ralsp.' + tag; - // console.log(' '); - // console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); - // console.log(scopesMapper.find(tag)); - // console.log('Falling back to values defined in: ' + fallBackTag); - // console.log(' '); - const color = new vscode.ThemeColor(fallBackTag); - const decor = vscode.window.createTextEditorDecorationType({ - color, - textDecoration, - }); - return [tag, decor]; - } - }; - - const decorations: Iterable<[ - string, - vscode.TextEditorDecorationType, - ]> = [ - decoration('comment'), - decoration('string'), - decoration('keyword'), - decoration('keyword.control'), - decoration('keyword.unsafe'), - decoration('function'), - decoration('parameter'), - decoration('constant'), - decoration('type.builtin'), - decoration('type.generic'), - decoration('type.lifetime'), - decoration('type.param'), - decoration('type.self'), - decoration('type'), - decoration('text'), - decoration('attribute'), - decoration('literal'), - decoration('literal.numeric'), - decoration('literal.char'), - decoration('literal.byte'), - decoration('macro'), - decoration('variable'), - decoration('variable.mut', 'underline'), - decoration('field'), - decoration('module'), - ]; - - return new Map(decorations); - } - private decorations: Map< string, vscode.TextEditorDecorationType > | null = null; + constructor(ctx: Ctx) { + this.ctx = ctx; + } + public removeHighlights() { if (this.decorations == null) { return; @@ -210,7 +111,7 @@ class Highlighter { // Note: decoration objects need to be kept around so we can dispose them // if the user disables syntax highlighting if (this.decorations == null) { - this.decorations = Highlighter.initDecorations(); + this.decorations = initDecorations(); } const byTag: Map = new Map(); @@ -266,3 +167,101 @@ class Highlighter { } } } + +function initDecorations(): Map< + string, + vscode.TextEditorDecorationType +> { + const decoration = ( + tag: string, + textDecoration?: string, + ): [string, vscode.TextEditorDecorationType] => { + const rule = scopesMapper.toRule(tag, scopes.find); + + if (rule) { + const decor = createDecorationFromTextmate(rule); + return [tag, decor]; + } else { + const fallBackTag = 'ralsp.' + tag; + // console.log(' '); + // console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); + // console.log(scopesMapper.find(tag)); + // console.log('Falling back to values defined in: ' + fallBackTag); + // console.log(' '); + const color = new vscode.ThemeColor(fallBackTag); + const decor = vscode.window.createTextEditorDecorationType({ + color, + textDecoration, + }); + return [tag, decor]; + } + }; + + const decorations: Iterable<[ + string, + vscode.TextEditorDecorationType, + ]> = [ + decoration('comment'), + decoration('string'), + decoration('keyword'), + decoration('keyword.control'), + decoration('keyword.unsafe'), + decoration('function'), + decoration('parameter'), + decoration('constant'), + decoration('type.builtin'), + decoration('type.generic'), + decoration('type.lifetime'), + decoration('type.param'), + decoration('type.self'), + decoration('type'), + decoration('text'), + decoration('attribute'), + decoration('literal'), + decoration('literal.numeric'), + decoration('literal.char'), + decoration('literal.byte'), + decoration('macro'), + decoration('variable'), + decoration('variable.mut', 'underline'), + decoration('field'), + decoration('module'), + ]; + + return new Map(decorations); +} + +function createDecorationFromTextmate( + themeStyle: scopes.TextMateRuleSettings, +): vscode.TextEditorDecorationType { + const decorationOptions: vscode.DecorationRenderOptions = {}; + decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; + + if (themeStyle.foreground) { + decorationOptions.color = themeStyle.foreground; + } + + if (themeStyle.background) { + decorationOptions.backgroundColor = themeStyle.background; + } + + if (themeStyle.fontStyle) { + const parts: string[] = themeStyle.fontStyle.split(' '); + parts.forEach(part => { + switch (part) { + case 'italic': + decorationOptions.fontStyle = 'italic'; + break; + case 'bold': + decorationOptions.fontWeight = 'bold'; + break; + case 'underline': + decorationOptions.textDecoration = 'underline'; + break; + default: + break; + } + }); + } + return vscode.window.createTextEditorDecorationType(decorationOptions); +} -- cgit v1.2.3 From 6561634c687cad2d1b7041b45b618d1c336f2e68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Dec 2019 02:21:57 +0100 Subject: Remove trivial helpers --- editors/code/src/scopes.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'editors') diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index cb250b853..465556333 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -82,9 +82,9 @@ function loadThemeNamed(themeName: string) { function loadThemeFile(themePath: string) { const themeContent = [themePath] - .filter(isFile) - .map(readFileText) - .map(parseJSON) + .filter(it => fs.statSync(it).isFile()) + .map(it => fs.readFileSync(it, 'utf8')) + .map(it => jsonc.parse(it)) .filter(theme => theme); themeContent @@ -132,15 +132,3 @@ function loadColors(textMateRules: TextMateRule[]): void { } }); } - -function isFile(filePath: string): boolean { - return [filePath].map(fs.statSync).every(stat => stat.isFile()); -} - -function readFileText(filePath: string): string { - return fs.readFileSync(filePath, 'utf8'); -} - -function parseJSON(content: string): any { - return jsonc.parse(content); -} -- cgit v1.2.3 From 96de8076ff50096a0ae62c5eb7a2e9c77971b552 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Dec 2019 02:27:26 +0100 Subject: Use optional value shortcut --- editors/code/src/scopes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'editors') diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 465556333..f98b57452 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -9,9 +9,9 @@ export interface TextMateRule { } export interface TextMateRuleSettings { - foreground: string | undefined; - background: string | undefined; - fontStyle: string | undefined; + foreground?: string; + background?: string; + fontStyle?: string; } // Current theme colors -- cgit v1.2.3 From cfb086592995a54828f23734a260d387db9ea926 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Dec 2019 02:30:43 +0100 Subject: Reduce scope --- editors/code/src/scopes.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'editors') diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index f98b57452..1229f0fb9 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -42,18 +42,20 @@ export function load() { } } -function filterThemeExtensions(extension: vscode.Extension): boolean { - return ( - extension.extensionKind === vscode.ExtensionKind.UI && - extension.packageJSON.contributes && - extension.packageJSON.contributes.themes - ); -} + // Find current theme on disk function loadThemeNamed(themeName: string) { + function isTheme(extension: vscode.Extension): boolean { + return ( + extension.extensionKind === vscode.ExtensionKind.UI && + extension.packageJSON.contributes && + extension.packageJSON.contributes.themes + ); + } + const themePaths = vscode.extensions.all - .filter(filterThemeExtensions) + .filter(isTheme) .reduce((list, extension) => { return extension.packageJSON.contributes.themes .filter( -- cgit v1.2.3 From f984ef26528eca686abbb946b3b363dfe6d74822 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Dec 2019 03:33:00 +0100 Subject: Switch impure functional style to pure imperative --- editors/code/src/config.ts | 2 - editors/code/src/highlighting.ts | 8 ++- editors/code/src/scopes.ts | 150 ++++++++++++++++----------------------- editors/code/tsconfig.json | 2 +- 4 files changed, 67 insertions(+), 95 deletions(-) (limited to 'editors') diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index e323110a4..f63d1ddce 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -1,5 +1,4 @@ import * as vscode from 'vscode'; -import * as scopes from './scopes'; import * as scopesMapper from './scopes_mapper'; const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; @@ -60,7 +59,6 @@ export class Config { if (config.has('highlightingOn')) { this.highlightingOn = config.get('highlightingOn') as boolean; if (this.highlightingOn) { - scopes.load(); scopesMapper.load(); } } diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 4c2e7f67b..5e9cbe0de 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -3,7 +3,7 @@ import * as lc from 'vscode-languageclient'; import * as seedrandom_ from 'seedrandom'; const seedrandom = seedrandom_; // https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 -import * as scopes from './scopes'; +import { loadThemeColors, TextMateRuleSettings } from './scopes'; import * as scopesMapper from './scopes_mapper'; import { Ctx } from './ctx'; @@ -172,11 +172,13 @@ function initDecorations(): Map< string, vscode.TextEditorDecorationType > { + const themeColors = loadThemeColors(); + const decoration = ( tag: string, textDecoration?: string, ): [string, vscode.TextEditorDecorationType] => { - const rule = scopesMapper.toRule(tag, scopes.find); + const rule = scopesMapper.toRule(tag, it => themeColors.get(it)); if (rule) { const decor = createDecorationFromTextmate(rule); @@ -232,7 +234,7 @@ function initDecorations(): Map< } function createDecorationFromTextmate( - themeStyle: scopes.TextMateRuleSettings, + themeStyle: TextMateRuleSettings, ): vscode.TextEditorDecorationType { const decorationOptions: vscode.DecorationRenderOptions = {}; decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 1229f0fb9..73fabbf54 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -3,28 +3,14 @@ import * as jsonc from 'jsonc-parser'; import * as path from 'path'; import * as vscode from 'vscode'; -export interface TextMateRule { - scope: string | string[]; - settings: TextMateRuleSettings; -} - export interface TextMateRuleSettings { foreground?: string; background?: string; fontStyle?: string; } -// Current theme colors -const rules = new Map(); - -export function find(scope: string): TextMateRuleSettings | undefined { - return rules.get(scope); -} - // Load all textmate scopes in the currently active theme -export function load() { - // Remove any previous theme - rules.clear(); +export function loadThemeColors(): Map { // Find out current color theme const themeName = vscode.workspace .getConfiguration('workbench') @@ -32,20 +18,12 @@ export function load() { if (typeof themeName !== 'string') { // console.warn('workbench.colorTheme is', themeName) - return; - } - // Try to load colors from that theme - try { - loadThemeNamed(themeName); - } catch (e) { - // console.warn('failed to load theme', themeName, e) + return new Map(); } + return loadThemeNamed(themeName); } - - -// Find current theme on disk -function loadThemeNamed(themeName: string) { +function loadThemeNamed(themeName: string): Map { function isTheme(extension: vscode.Extension): boolean { return ( extension.extensionKind === vscode.ExtensionKind.UI && @@ -54,83 +32,77 @@ function loadThemeNamed(themeName: string) { ); } - const themePaths = vscode.extensions.all + let themePaths = vscode.extensions.all .filter(isTheme) - .reduce((list, extension) => { - return extension.packageJSON.contributes.themes - .filter( - (element: any) => - (element.id || element.label) === themeName, - ) - .map((element: any) => - path.join(extension.extensionPath, element.path), - ) - .concat(list); - }, Array()); - - themePaths.forEach(loadThemeFile); + .flatMap(ext => { + return ext.packageJSON.contributes.themes + .filter((it: any) => (it.id || it.label) === themeName) + .map((it: any) => path.join(ext.extensionPath, it.path)); + }) + + const res = new Map(); + for (const themePath of themePaths) { + mergeInto(res, loadThemeFile(themePath)) + } - const tokenColorCustomizations: [any] = [ - vscode.workspace - .getConfiguration('editor') - .get('tokenColorCustomizations'), - ]; + const customizations: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); + mergeInto(res, loadColors(customizations?.textMateRules ?? [])) - tokenColorCustomizations - .filter(custom => custom && custom.textMateRules) - .map(custom => custom.textMateRules) - .forEach(loadColors); + return res; } -function loadThemeFile(themePath: string) { - const themeContent = [themePath] - .filter(it => fs.statSync(it).isFile()) - .map(it => fs.readFileSync(it, 'utf8')) - .map(it => jsonc.parse(it)) - .filter(theme => theme); +function loadThemeFile(themePath: string): Map { + let text; + try { + text = fs.readFileSync(themePath, 'utf8') + } catch { + return new Map(); + } + const obj = jsonc.parse(text); + const tokenColors = obj?.tokenColors ?? []; + const res = loadColors(tokenColors); + + for (const include in obj?.include ?? []) { + const includePath = path.join(path.dirname(themePath), include); + const tmp = loadThemeFile(includePath); + mergeInto(res, tmp); + } + + return res; +} - themeContent - .filter(theme => theme.tokenColors) - .map(theme => theme.tokenColors) - .forEach(loadColors); +interface TextMateRule { + scope: string | string[]; + settings: TextMateRuleSettings; +} - themeContent - .filter(theme => theme.include) - .map(theme => path.join(path.dirname(themePath), theme.include)) - .forEach(loadThemeFile); +function loadColors(textMateRules: TextMateRule[]): Map { + const res = new Map(); + for (const rule of textMateRules) { + const scopes = typeof rule.scope === 'string' + ? [rule.scope] + : rule.scope; + for (const scope of scopes) { + res.set(scope, rule.settings) + } + } + return res } function mergeRuleSettings( defaultSetting: TextMateRuleSettings | undefined, override: TextMateRuleSettings, ): TextMateRuleSettings { - if (defaultSetting === undefined) { - return override; + return { + foreground: defaultSetting?.foreground ?? override.foreground, + background: defaultSetting?.background ?? override.background, + fontStyle: defaultSetting?.fontStyle ?? override.fontStyle, } - const mergedRule = defaultSetting; - - mergedRule.background = override.background || defaultSetting.background; - mergedRule.foreground = override.foreground || defaultSetting.foreground; - mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; - - return mergedRule; } -function updateRules( - scope: string, - updatedSettings: TextMateRuleSettings, -): void { - [rules.get(scope)] - .map(settings => mergeRuleSettings(settings, updatedSettings)) - .forEach(settings => rules.set(scope, settings)); -} - -function loadColors(textMateRules: TextMateRule[]): void { - textMateRules.forEach(rule => { - if (typeof rule.scope === 'string') { - updateRules(rule.scope, rule.settings); - } else if (rule.scope instanceof Array) { - rule.scope.forEach(scope => updateRules(scope, rule.settings)); - } - }); +function mergeInto(dst: Map, addition: Map) { + addition.forEach((value, key) => { + const merged = mergeRuleSettings(dst.get(key), value) + dst.set(key, merged) + }) } diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index fe3b40f34..e60eb8e5e 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -4,7 +4,7 @@ "target": "es2018", "outDir": "out", "lib": [ - "es2018" + "es2019" ], "sourceMap": true, "rootDir": "src", -- cgit v1.2.3