From 3e8616cf6df5ba6e5dceba8b834dc63c20bac4d4 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 24 Oct 2019 17:25:23 +0200 Subject: Proof of concept theming and 'tokenColorCustomizations' support. --- editors/code/package-lock.json | 11 ++- editors/code/package.json | 3 +- editors/code/src/config.ts | 6 +- editors/code/src/extension.ts | 10 +-- editors/code/src/highlighting.ts | 94 +++++++++++++++++++------- editors/code/src/scopes.ts | 142 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 231 insertions(+), 35 deletions(-) create mode 100644 editors/code/src/scopes.ts diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index e6bcbfa60..a632c7395 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -598,9 +598,9 @@ } }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.3.tgz", + "integrity": "sha512-Ytgnz23gm2DVftnzqRRz2dOXZbGd2uiajSw/95bPp6v53zPRspQjLm/AfBgqbJ2qfeRXWIOMVLpp86+/5yX39Q==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -720,6 +720,11 @@ "esprima": "^4.0.0" } }, + "jsonc-parser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.1.1.tgz", + "integrity": "sha512-VC0CjnWJylKB1iov4u76/W/5Ef0ydDkjtYWxoZ9t3HdWlSnZQwZL5MgFikaB/EtQ4RmMEw3tmQzuYnZA2/Ja1g==" + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 4b719aada..46b8cd47c 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -32,7 +32,8 @@ }, "dependencies": { "seedrandom": "^3.0.1", - "vscode-languageclient": "^5.3.0-next.4" + "vscode-languageclient": "^5.3.0-next.4", + "jsonc-parser": "^2.1.0" }, "devDependencies": { "@types/glob": "^7.1.1", diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 331936b5e..9f8c810b6 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -1,5 +1,5 @@ import * as vscode from 'vscode'; - +import * as scopes from './scopes'; import { Server } from './server'; const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; @@ -46,7 +46,11 @@ export class Config { public userConfigChanged() { const config = vscode.workspace.getConfiguration('rust-analyzer'); + + Server.highlighter.removeHighlights(); + scopes.load() if (config.has('highlightingOn')) { + this.highlightingOn = config.get('highlightingOn') as boolean; } diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 39fe6efd8..1e1bc1a67 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -91,11 +91,11 @@ export function activate(context: vscode.ExtensionContext) { const allNotifications: Iterable< [string, lc.GenericNotificationHandler] > = [ - [ - 'rust-analyzer/publishDecorations', - notifications.publishDecorations.handle - ] - ]; + [ + 'rust-analyzer/publishDecorations', + notifications.publishDecorations.handle + ] + ]; const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); // The events below are plain old javascript events, triggered and handled by vscode diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index d21d8a06a..4b961170b 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -1,6 +1,8 @@ import seedrandom = require('seedrandom'); import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; +import * as scopes from './scopes' + import { Server } from './server'; @@ -23,6 +25,37 @@ function fancify(seed: string, shade: 'light' | 'dark') { return `hsl(${h},${s}%,${l}%)`; } +function createDecorationFromTextmate(themeStyle: scopes.TextMateRuleSettings): vscode.TextEditorDecorationType { + const options: vscode.DecorationRenderOptions = {} + options.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen + if (themeStyle.foreground) { + options.color = themeStyle.foreground + } + if (themeStyle.background) { + options.backgroundColor = themeStyle.background + } + if (themeStyle.fontStyle) { + const parts: string[] = themeStyle.fontStyle.split(' ') + parts.forEach((part) => { + switch (part) { + case 'italic': + options.fontStyle = 'italic' + break + case 'bold': + options.fontWeight = 'bold' + + break + case 'underline': + options.textDecoration = 'underline' + break + default: + break + } + }) + } + return vscode.window.createTextEditorDecorationType(options) +} + export class Highlighter { private static initDecorations(): Map< string, @@ -32,36 +65,44 @@ export class Highlighter { tag: string, textDecoration?: string ): [string, vscode.TextEditorDecorationType] => { - const color = new vscode.ThemeColor('ralsp.' + tag); - const decor = vscode.window.createTextEditorDecorationType({ - color, - textDecoration - }); - return [tag, decor]; + const scope = scopes.find(tag) + + if (scope) { + const decor = createDecorationFromTextmate(scope); + return [tag, decor]; + } + else { + const color = new vscode.ThemeColor('ralsp.' + tag); + 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'), - decoration('builtin'), - decoration('text'), - decoration('attribute'), - decoration('literal'), - decoration('macro'), - decoration('variable'), - decoration('variable.mut', 'underline'), - decoration('field'), - decoration('module') - ]; + decoration('comment'), + decoration('string'), + decoration('keyword'), + decoration('keyword.control'), + decoration('keyword.unsafe'), + decoration('function'), + decoration('parameter'), + decoration('constant'), + decoration('type'), + decoration('builtin'), + decoration('text'), + decoration('attribute'), + decoration('literal'), + decoration('macro'), + decoration('variable'), + decoration('variable.mut', 'underline'), + decoration('field'), + decoration('module') + ]; return new Map(decorations); } @@ -89,6 +130,8 @@ export 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(); } @@ -133,6 +176,7 @@ export class Highlighter { tag ) as vscode.TextEditorDecorationType; const ranges = byTag.get(tag)!; + editor.setDecorations(dec, ranges); } diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts new file mode 100644 index 000000000..19d309828 --- /dev/null +++ b/editors/code/src/scopes.ts @@ -0,0 +1,142 @@ +import * as fs from 'fs' +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 | undefined + background: string | undefined + fontStyle: string | undefined +} + +// Current theme colors +const colors = new Map() + +export function find(scope: string): TextMateRuleSettings | undefined { + return colors.get(scope) +} + +// Load all textmate scopes in the currently active theme +export function load() { + // Remove any previous theme + colors.clear() + // Find out current color theme + const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme') + + 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) + } +} + +// Find current theme on disk +function loadThemeNamed(themeName: string) { + for (const extension of vscode.extensions.all) { + const extensionPath: string = extension.extensionPath + const extensionPackageJsonPath: string = path.join(extensionPath, 'package.json') + if (!checkFileExists(extensionPackageJsonPath)) { + continue + } + const packageJsonText: string = readFileText(extensionPackageJsonPath) + const packageJson: any = jsonc.parse(packageJsonText) + if (packageJson.contributes && packageJson.contributes.themes) { + for (const theme of packageJson.contributes.themes) { + const id = theme.id || theme.label + if (id === themeName) { + const themeRelativePath: string = theme.path + const themeFullPath: string = path.join(extensionPath, themeRelativePath) + loadThemeFile(themeFullPath) + } + } + } + + const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); + if (customization && customization.textMateRules) { + loadColors(customization.textMateRules) + } + } +} + +function loadThemeFile(themePath: string) { + if (checkFileExists(themePath)) { + const themeContentText: string = readFileText(themePath) + const themeContent: any = jsonc.parse(themeContentText) + + if (themeContent && themeContent.tokenColors) { + loadColors(themeContent.tokenColors) + if (themeContent.include) { + // parse included theme file + const includedThemePath: string = path.join(path.dirname(themePath), themeContent.include) + loadThemeFile(includedThemePath) + } + } + } +} +function mergeRuleSettings(defaultRule: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings { + const mergedRule = defaultRule; + if (override.background) { + mergedRule.background = override.background + } + if (override.foreground) { + mergedRule.foreground = override.foreground + } + if (override.background) { + mergedRule.fontStyle = override.fontStyle + } + return mergedRule; +} + +function loadColors(textMateRules: TextMateRule[]): void { + for (const rule of textMateRules) { + + if (typeof rule.scope === 'string') { + const existingRule = colors.get(rule.scope); + if (existingRule) { + colors.set(rule.scope, mergeRuleSettings(existingRule, rule.settings)) + } + else { + colors.set(rule.scope, rule.settings) + } + } else if (rule.scope instanceof Array) { + for (const scope of rule.scope) { + const existingRule = colors.get(scope); + if (existingRule) { + colors.set(scope, mergeRuleSettings(existingRule, rule.settings)) + } + else { + colors.set(scope, rule.settings) + } + } + } + } +} + +function checkFileExists(filePath: string): boolean { + + const stats = fs.statSync(filePath); + if (stats && stats.isFile()) { + return true; + } else { + console.warn('no such file', filePath) + return false; + } + + +} + +function readFileText(filePath: string, encoding: string = 'utf8'): string { + return fs.readFileSync(filePath, encoding); +} \ No newline at end of file -- cgit v1.2.3 From 8e63644d6645b3e62ec92199a460cccde91c5482 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 24 Oct 2019 17:56:59 +0200 Subject: Only loading `tokenColorCustomizations` once. --- editors/code/src/scopes.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 19d309828..c38f6bb50 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -63,10 +63,10 @@ function loadThemeNamed(themeName: string) { } } - const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); - if (customization && customization.textMateRules) { - loadColors(customization.textMateRules) - } + } + const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); + if (customization && customization.textMateRules) { + loadColors(customization.textMateRules) } } -- cgit v1.2.3 From e6df4c424ad8a938fca849b8b4511a7e32f8cd17 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 24 Oct 2019 17:59:55 +0200 Subject: Fixing linting issues, but also hides failures. Has to be a better approach to error handling. --- editors/code/src/scopes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index c38f6bb50..a099696a9 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -31,14 +31,14 @@ export function load() { const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme') if (typeof themeName !== 'string') { - console.warn('workbench.colorTheme is', themeName) + // 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) + // console.warn('failed to load theme', themeName, e) } } @@ -130,7 +130,7 @@ function checkFileExists(filePath: string): boolean { if (stats && stats.isFile()) { return true; } else { - console.warn('no such file', filePath) + // console.warn('no such file', filePath) return false; } -- cgit v1.2.3 From b59ffb7d417ba978087a1663c002256d684ae49a Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 24 Oct 2019 18:33:36 +0200 Subject: Making it clear we're using default settings. --- editors/code/src/scopes.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index a099696a9..607b8b2dd 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -85,17 +85,13 @@ function loadThemeFile(themePath: string) { } } } -function mergeRuleSettings(defaultRule: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings { - const mergedRule = defaultRule; - if (override.background) { - mergedRule.background = override.background - } - if (override.foreground) { - mergedRule.foreground = override.foreground - } - if (override.background) { - mergedRule.fontStyle = override.fontStyle - } +function mergeRuleSettings(defaultSetting: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings { + const mergedRule = defaultSetting; + + mergedRule.background = override.background || defaultSetting.background + mergedRule.foreground = override.foreground || defaultSetting.foreground + mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; + return mergedRule; } -- cgit v1.2.3 From 5957b851e4451050151722598fa1ff9d41ccf0ff Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sat, 26 Oct 2019 16:29:49 +0200 Subject: Refactor how themes are found in packages without relying on parsing JSONC. However, there is still an issue where themes could have been defined in JSONC - but so far with testing very few of them actually do. The issue was in loading packages and now we're letting VSCode tackle that. Fix: https://github.com/rust-analyzer/rust-analyzer/pull/2061#discussion_r339015610 --- editors/code/package.json | 5 ++--- editors/code/src/scopes.ts | 38 +++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 46b8cd47c..b7ea9fa6f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -32,8 +32,7 @@ }, "dependencies": { "seedrandom": "^3.0.1", - "vscode-languageclient": "^5.3.0-next.4", - "jsonc-parser": "^2.1.0" + "vscode-languageclient": "^5.3.0-next.4" }, "devDependencies": { "@types/glob": "^7.1.1", @@ -494,4 +493,4 @@ } ] } -} +} \ No newline at end of file diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 607b8b2dd..c9c01ba1d 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -1,5 +1,4 @@ import * as fs from 'fs' -import * as jsonc from 'jsonc-parser' import * as path from 'path' import * as vscode from 'vscode' @@ -44,26 +43,21 @@ export function load() { // Find current theme on disk function loadThemeNamed(themeName: string) { - for (const extension of vscode.extensions.all) { - const extensionPath: string = extension.extensionPath - const extensionPackageJsonPath: string = path.join(extensionPath, 'package.json') - if (!checkFileExists(extensionPackageJsonPath)) { - continue - } - const packageJsonText: string = readFileText(extensionPackageJsonPath) - const packageJson: any = jsonc.parse(packageJsonText) - if (packageJson.contributes && packageJson.contributes.themes) { - for (const theme of packageJson.contributes.themes) { - const id = theme.id || theme.label - if (id === themeName) { - const themeRelativePath: string = theme.path - const themeFullPath: string = path.join(extensionPath, themeRelativePath) - loadThemeFile(themeFullPath) - } - } - } - } + const themePaths = vscode.extensions.all + .filter(extension => extension.extensionKind === vscode.ExtensionKind.UI) + .filter(extension => extension.packageJSON.contributes) + .filter(extension => extension.packageJSON.contributes.themes) + .reduce((list, extension) => { + const paths = extension.packageJSON.contributes.themes + .filter((element: any) => (element.id || element.label) === themeName) + .map((element: any) => path.join(extension.extensionPath, element.path)) + return list.concat(paths) + }, Array()); + + + themePaths.forEach(loadThemeFile); + const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); if (customization && customization.textMateRules) { loadColors(customization.textMateRules) @@ -71,9 +65,11 @@ function loadThemeNamed(themeName: string) { } function loadThemeFile(themePath: string) { + if (checkFileExists(themePath)) { const themeContentText: string = readFileText(themePath) - const themeContent: any = jsonc.parse(themeContentText) + + const themeContent: any = JSON.parse(themeContentText) if (themeContent && themeContent.tokenColors) { loadColors(themeContent.tokenColors) -- cgit v1.2.3 From 0ddf47a7ab9d0f616e7296fa9a0b0eb786e4ee59 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sun, 27 Oct 2019 17:57:11 +0100 Subject: Introducing a Scopes Mapper to map from RA scopes to TextMate scopes with fallbacks. Current scopes defined: ``` ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control']], ['function', ['entity.name.function']], ['parameter', ['variable.parameter']], ['type', ['entity.name.type']], ['builtin', ['variable.language', 'support.type', 'support.type']], ['text', ['string', 'string.quoted', 'string.regexp']], ['attribute', ['keyword']], ['literal', ['string', 'string.quoted', 'string.regexp']], ['macro', ['support.other']], ['variable.mut', ['variable']], ['field', ['variable.object.property']], ['module', ['entity.name.section']] ``` Need to complement with further fallbacks as some themes fail. --- editors/code/src/config.ts | 2 ++ editors/code/src/highlighting.ts | 11 ++++++---- editors/code/src/scopes.ts | 18 ++++++++--------- editors/code/src/scopes_mapper.ts | 42 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 editors/code/src/scopes_mapper.ts diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 9f8c810b6..a3fe39098 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import * as scopes from './scopes'; +import * as scopesMapper from './scopes_mapper'; import { Server } from './server'; const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; @@ -49,6 +50,7 @@ export class Config { Server.highlighter.removeHighlights(); scopes.load() + scopesMapper.load() if (config.has('highlightingOn')) { this.highlightingOn = config.get('highlightingOn') as boolean; diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 4b961170b..bc19fae2f 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -2,7 +2,7 @@ import seedrandom = require('seedrandom'); import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; import * as scopes from './scopes' - +import * as scopesMapper from './scopes_mapper'; import { Server } from './server'; @@ -65,10 +65,13 @@ export class Highlighter { tag: string, textDecoration?: string ): [string, vscode.TextEditorDecorationType] => { - const scope = scopes.find(tag) - if (scope) { - const decor = createDecorationFromTextmate(scope); + const foundRule = scopesMapper.toRule(tag, scopes.find) || scopes.find(tag) + + + + if (foundRule) { + const decor = createDecorationFromTextmate(foundRule); return [tag, decor]; } else { diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index c9c01ba1d..470ee716f 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -16,16 +16,16 @@ export interface TextMateRuleSettings { } // Current theme colors -const colors = new Map() +const rules = new Map() export function find(scope: string): TextMateRuleSettings | undefined { - return colors.get(scope) + return rules.get(scope) } // Load all textmate scopes in the currently active theme export function load() { // Remove any previous theme - colors.clear() + rules.clear() // Find out current color theme const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme') @@ -95,21 +95,21 @@ function loadColors(textMateRules: TextMateRule[]): void { for (const rule of textMateRules) { if (typeof rule.scope === 'string') { - const existingRule = colors.get(rule.scope); + const existingRule = rules.get(rule.scope); if (existingRule) { - colors.set(rule.scope, mergeRuleSettings(existingRule, rule.settings)) + rules.set(rule.scope, mergeRuleSettings(existingRule, rule.settings)) } else { - colors.set(rule.scope, rule.settings) + rules.set(rule.scope, rule.settings) } } else if (rule.scope instanceof Array) { for (const scope of rule.scope) { - const existingRule = colors.get(scope); + const existingRule = rules.get(scope); if (existingRule) { - colors.set(scope, mergeRuleSettings(existingRule, rule.settings)) + rules.set(scope, mergeRuleSettings(existingRule, rule.settings)) } else { - colors.set(scope, rule.settings) + rules.set(scope, rule.settings) } } } diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts new file mode 100644 index 000000000..995adae2d --- /dev/null +++ b/editors/code/src/scopes_mapper.ts @@ -0,0 +1,42 @@ +import * as vscode from 'vscode' +import { TextMateRuleSettings } from './scopes' + + + + +let mappings = new Map() + + +const defaultMapping = new Map([ + ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control']], + ['function', ['entity.name.function']], + ['parameter', ['variable.parameter']], + ['type', ['entity.name.type']], + ['builtin', ['variable.language', 'support.type', 'support.type']], + ['text', ['string', 'string.quoted', 'string.regexp']], + ['attribute', ['keyword']], + ['literal', ['string', 'string.quoted', 'string.regexp']], + ['macro', ['support.other']], + ['variable.mut', ['variable']], + ['field', ['variable.object.property']], + ['module', ['entity.name.section']] +] +) +function find(scope: string): string[] { + return mappings.get(scope) || [] +} + +export function toRule(scope: string, intoRule: (scope: string) => TextMateRuleSettings | undefined): TextMateRuleSettings | undefined { + return find(scope).map(intoRule).find(rule => rule !== null) +} + + +export function load() { + const configuration = vscode.workspace + .getConfiguration('rust-analyzer') + .get('scopeMappings') as Map | undefined || new Map() + + mappings = new Map([...Array.from(defaultMapping.entries()), ...Array.from(configuration.entries())]); + + +} \ No newline at end of file -- cgit v1.2.3 From 89993517e97c1bb797b2614110573a1fee4ae071 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sun, 27 Oct 2019 23:11:22 +0100 Subject: Adding all the decorators from RA to map. Useful for more granular control. --- editors/code/src/scopes_mapper.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 995adae2d..5c3cb8f63 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -8,15 +8,21 @@ let mappings = new Map() const defaultMapping = new Map([ + ['comment', ['comment']], + ['string', ['string']], + ['keyword', ['keyword']], + ['keyword.control', ['keyword.control', 'keyword', 'keyword.other']], ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control']], ['function', ['entity.name.function']], ['parameter', ['variable.parameter']], + ['constant', ['constant', 'variable']], ['type', ['entity.name.type']], ['builtin', ['variable.language', 'support.type', 'support.type']], ['text', ['string', 'string.quoted', 'string.regexp']], ['attribute', ['keyword']], ['literal', ['string', 'string.quoted', 'string.regexp']], ['macro', ['support.other']], + ['variable', ['variable']], ['variable.mut', ['variable']], ['field', ['variable.object.property']], ['module', ['entity.name.section']] -- cgit v1.2.3 From 8c2cd28c48ffc1a82528469cde7bf1242e5110f7 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sun, 27 Oct 2019 23:49:41 +0100 Subject: Adding debugging to figure out missing scopes from theme. --- editors/code/src/highlighting.ts | 9 ++++----- editors/code/src/scopes_mapper.ts | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index bc19fae2f..b7dffaff5 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -66,15 +66,14 @@ export class Highlighter { textDecoration?: string ): [string, vscode.TextEditorDecorationType] => { - const foundRule = scopesMapper.toRule(tag, scopes.find) || scopes.find(tag) + const rule = scopesMapper.toRule(tag, scopes.find) - - - if (foundRule) { - const decor = createDecorationFromTextmate(foundRule); + if (rule) { + const decor = createDecorationFromTextmate(rule); return [tag, decor]; } else { + console.log('Missing theme for: ' + tag); const color = new vscode.ThemeColor('ralsp.' + tag); const decor = vscode.window.createTextEditorDecorationType({ color, diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 5c3cb8f63..4534d8a32 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -8,11 +8,11 @@ let mappings = new Map() const defaultMapping = new Map([ - ['comment', ['comment']], + ['comment', ['comment', 'comment.block', 'comment.line', 'comment.block.documentation']], ['string', ['string']], ['keyword', ['keyword']], ['keyword.control', ['keyword.control', 'keyword', 'keyword.other']], - ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control']], + ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword']], ['function', ['entity.name.function']], ['parameter', ['variable.parameter']], ['constant', ['constant', 'variable']], @@ -23,9 +23,9 @@ const defaultMapping = new Map([ ['literal', ['string', 'string.quoted', 'string.regexp']], ['macro', ['support.other']], ['variable', ['variable']], - ['variable.mut', ['variable']], - ['field', ['variable.object.property']], - ['module', ['entity.name.section']] + ['variable.mut', ['variable', 'storage.modifier']], + ['field', ['variable.object.property', 'meta.field.declaration', 'meta.definition.property', 'variable.other',]], + ['module', ['entity.name.section', 'entity.other']] ] ) function find(scope: string): string[] { @@ -33,7 +33,7 @@ function find(scope: string): string[] { } export function toRule(scope: string, intoRule: (scope: string) => TextMateRuleSettings | undefined): TextMateRuleSettings | undefined { - return find(scope).map(intoRule).find(rule => rule !== null) + return find(scope).map(intoRule).filter(rule => rule !== undefined)[0]; } -- cgit v1.2.3 From 49562d36b97ddde34cf7585a8c2e8f232519b657 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sun, 27 Oct 2019 23:58:14 +0100 Subject: Remove `jsonc-parser` since vscode can load the package. Might need it later for loading certain themes, but seems to work without for now. --- editors/code/package-lock.json | 5 ----- editors/code/package.json | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index a632c7395..9c55c257f 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -720,11 +720,6 @@ "esprima": "^4.0.0" } }, - "jsonc-parser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.1.1.tgz", - "integrity": "sha512-VC0CjnWJylKB1iov4u76/W/5Ef0ydDkjtYWxoZ9t3HdWlSnZQwZL5MgFikaB/EtQ4RmMEw3tmQzuYnZA2/Ja1g==" - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index b7ea9fa6f..4b719aada 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -493,4 +493,4 @@ } ] } -} \ No newline at end of file +} -- cgit v1.2.3 From 1f822c8e518132b01d7eda665f6bf7bc254780a7 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 31 Oct 2019 10:36:54 +0100 Subject: Adding better debugging for testing themes missing tags and which scopes didn't map. Since this file is no longer being pushed upstream, double down on monads. --- editors/code/src/highlighting.ts | 5 ++- editors/code/src/scopes.ts | 87 +++++++++++++++++++++------------------ editors/code/src/scopes_mapper.ts | 11 +++-- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index b7dffaff5..dad99254e 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -73,7 +73,10 @@ export class Highlighter { return [tag, decor]; } else { - console.log('Missing theme for: ' + tag); + console.log(' '); + console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:') + console.log(scopesMapper.find(tag)) + console.log(' '); const color = new vscode.ThemeColor('ralsp.' + tag); const decor = vscode.window.createTextEditorDecorationType({ color, diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 470ee716f..76cbbd84e 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -41,61 +41,72 @@ 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) { const themePaths = vscode.extensions.all - .filter(extension => extension.extensionKind === vscode.ExtensionKind.UI) - .filter(extension => extension.packageJSON.contributes) - .filter(extension => extension.packageJSON.contributes.themes) + .filter(filterThemeExtensions) .reduce((list, extension) => { const paths = extension.packageJSON.contributes.themes .filter((element: any) => (element.id || element.label) === themeName) .map((element: any) => path.join(extension.extensionPath, element.path)) return list.concat(paths) - }, Array()); + }, Array()) - themePaths.forEach(loadThemeFile); + themePaths.forEach(loadThemeFile) - const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations'); - if (customization && customization.textMateRules) { - loadColors(customization.textMateRules) - } -} + const tokenColorCustomizations: [any] = [vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations')] -function loadThemeFile(themePath: string) { + tokenColorCustomizations + .filter(custom => custom && custom.textMateRules) + .map(custom => custom.textMateRules) + .forEach(loadColors) - if (checkFileExists(themePath)) { - const themeContentText: string = readFileText(themePath) +} - const themeContent: any = JSON.parse(themeContentText) - if (themeContent && themeContent.tokenColors) { - loadColors(themeContent.tokenColors) - if (themeContent.include) { - // parse included theme file - const includedThemePath: string = path.join(path.dirname(themePath), themeContent.include) - loadThemeFile(includedThemePath) - } - } - } +function loadThemeFile(themePath: string) { + const themeContent = [themePath] + .filter(isFile) + .map(readFileText) + .map(parseJSON) + .filter(theme => theme) + + themeContent + .filter(theme => theme.tokenColors) + .map(theme => theme.tokenColors) + .forEach(loadColors) + + themeContent + .filter(theme => theme.include) + .map(theme => path.join(path.dirname(themePath), theme.include)) + .forEach(loadThemeFile) } + function mergeRuleSettings(defaultSetting: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings { - const mergedRule = defaultSetting; + const mergedRule = defaultSetting mergedRule.background = override.background || defaultSetting.background mergedRule.foreground = override.foreground || defaultSetting.foreground - mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; + mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground - return mergedRule; + return mergedRule } function loadColors(textMateRules: TextMateRule[]): void { for (const rule of textMateRules) { if (typeof rule.scope === 'string') { - const existingRule = rules.get(rule.scope); + const existingRule = rules.get(rule.scope) if (existingRule) { rules.set(rule.scope, mergeRuleSettings(existingRule, rule.settings)) } @@ -104,7 +115,7 @@ function loadColors(textMateRules: TextMateRule[]): void { } } else if (rule.scope instanceof Array) { for (const scope of rule.scope) { - const existingRule = rules.get(scope); + const existingRule = rules.get(scope) if (existingRule) { rules.set(scope, mergeRuleSettings(existingRule, rule.settings)) } @@ -116,19 +127,15 @@ function loadColors(textMateRules: TextMateRule[]): void { } } -function checkFileExists(filePath: string): boolean { - - const stats = fs.statSync(filePath); - if (stats && stats.isFile()) { - return true; - } else { - // console.warn('no such file', filePath) - return false; - } - +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 readFileText(filePath: string, encoding: string = 'utf8'): string { - return fs.readFileSync(filePath, encoding); +// Might need to replace with JSONC if a theme contains comments. +function parseJSON(content: string): any { + return JSON.parse(content) } \ No newline at end of file diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 4534d8a32..19a4213d4 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -28,21 +28,24 @@ const defaultMapping = new Map([ ['module', ['entity.name.section', 'entity.other']] ] ) -function find(scope: string): string[] { + +// Temporary exported for debugging for now. +export function find(scope: string): string[] { return mappings.get(scope) || [] } export function toRule(scope: string, intoRule: (scope: string) => TextMateRuleSettings | undefined): TextMateRuleSettings | undefined { - return find(scope).map(intoRule).filter(rule => rule !== undefined)[0]; + return find(scope).map(intoRule).filter(rule => rule !== undefined)[0] } export function load() { const configuration = vscode.workspace .getConfiguration('rust-analyzer') - .get('scopeMappings') as Map | undefined || new Map() + .get('scopeMappings') as Map | undefined + || new Map() - mappings = new Map([...Array.from(defaultMapping.entries()), ...Array.from(configuration.entries())]); + mappings = new Map([...Array.from(defaultMapping.entries()), ...Array.from(configuration.entries())]) } \ No newline at end of file -- cgit v1.2.3 From a437f0e5849d8ce0a14d40a55f2ac2166f5ec343 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Thu, 31 Oct 2019 11:26:39 +0100 Subject: Making loadColors more readable by monading all the things. --- editors/code/src/scopes.ts | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 76cbbd84e..5d4395930 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -55,10 +55,10 @@ function loadThemeNamed(themeName: string) { const themePaths = vscode.extensions.all .filter(filterThemeExtensions) .reduce((list, extension) => { - const paths = extension.packageJSON.contributes.themes + return extension.packageJSON.contributes.themes .filter((element: any) => (element.id || element.label) === themeName) .map((element: any) => path.join(extension.extensionPath, element.path)) - return list.concat(paths) + .concat(list) }, Array()) @@ -92,7 +92,8 @@ function loadThemeFile(themePath: string) { .forEach(loadThemeFile) } -function mergeRuleSettings(defaultSetting: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings { +function mergeRuleSettings(defaultSetting: TextMateRuleSettings | undefined, override: TextMateRuleSettings): TextMateRuleSettings { + if (defaultSetting === undefined) { return override } const mergedRule = defaultSetting mergedRule.background = override.background || defaultSetting.background @@ -102,29 +103,21 @@ function mergeRuleSettings(defaultSetting: TextMateRuleSettings, override: TextM return mergedRule } -function loadColors(textMateRules: TextMateRule[]): void { - for (const rule of textMateRules) { +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') { - const existingRule = rules.get(rule.scope) - if (existingRule) { - rules.set(rule.scope, mergeRuleSettings(existingRule, rule.settings)) - } - else { - rules.set(rule.scope, rule.settings) - } - } else if (rule.scope instanceof Array) { - for (const scope of rule.scope) { - const existingRule = rules.get(scope) - if (existingRule) { - rules.set(scope, mergeRuleSettings(existingRule, rule.settings)) - } - else { - rules.set(scope, rule.settings) - } - } + updateRules(rule.scope, rule.settings) } - } + else if (rule.scope instanceof Array) { + rule.scope.forEach(scope => updateRules(scope, rule.settings)) + } + }) } function isFile(filePath: string): boolean { -- cgit v1.2.3 From c60f9bf4c6d6ddd341c673b228b6aa1add3da62b Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Mon, 4 Nov 2019 23:59:11 +0100 Subject: * Adding scope mapping configuration manifest in `package.json` * Loading configurable scope mappings from settings. * Updating Readme with `rust-analyzer.scopeMappings`. `rust-analyzer.scopeMappings` -- a scheme backed JSON object to tweak Rust Analyzer scopes to TextMate scopes. ```jsonc { //Will autocomplete keys to available RA scopes. "keyword.unsafe": ["keyword", "keyword.control"], //Values are string | TextMateScope | [string | TextMateScope] "comments": "comment.block" } ``` --- docs/user/README.md | 13 ++++++-- editors/code/package.json | 64 ++++++++++++++++++++++++++++++++++++++- editors/code/src/config.ts | 11 +++---- editors/code/src/highlighting.ts | 32 ++++++++++---------- editors/code/src/scopes.ts | 64 +++++++++++++++++++-------------------- editors/code/src/scopes_mapper.ts | 35 ++++++++++++++------- 6 files changed, 151 insertions(+), 68 deletions(-) diff --git a/docs/user/README.md b/docs/user/README.md index eb1d5ed14..42742c0e6 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -82,7 +82,16 @@ host. ### Settings -* `rust-analyzer.highlightingOn`: enables experimental syntax highlighting +* `rust-analyzer.highlightingOn`: enables experimental syntax highlighting. +* `rust-analyzer.scopeMappings` -- a scheme backed JSON object to tweak Rust Analyzer scopes to TextMate scopes. + ```jsonc + { + //Will autocomplete keys to available RA scopes. + "keyword.unsafe": ["keyword", "keyword.control"], + //Values are string | TextMateScope | [string | TextMateScope] + "comments": "comment.block" + } + ``` * `rust-analyzer.enableEnhancedTyping`: by default, rust-analyzer intercepts `Enter` key to make it easier to continue comments. Note that it may conflict with VIM emulation plugin. * `rust-analyzer.raLspServerPath`: path to `ra_lsp_server` executable @@ -101,7 +110,7 @@ host. * `rust-analyzer.trace.cargo-watch`: enables cargo-watch logging * `RUST_SRC_PATH`: environment variable that overwrites the sysroot * `rust-analyzer.featureFlags` -- a JSON object to tweak fine-grained behavior: - ```js + ```jsonc { // Show diagnostics produced by rust-analyzer itself. "lsp.diagnostics": true, diff --git a/editors/code/package.json b/editors/code/package.json index ee997e58f..35f2f1e62 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -167,6 +167,68 @@ "default": false, "description": "Highlight Rust code (overrides built-in syntax highlighting)" }, + "rust-analyzer.scopeMappings": { + "type": "object", + "definitions": {}, + "properties": { + "comment": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "string": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "keyword": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "keyword.control": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "keyword.unsafe": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "function": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "parameter": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "constant": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "type": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "builtin": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "text": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "attribute": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "literal": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "macro": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "variable": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "variable.mut": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "field": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + }, + "module": { + "$ref": "vscode://schemas/textmate-colors#/items/properties/scope" + } + }, + "additionalProperties": false, + "description": "Mapping Rust Analyzer scopes to TextMateRule scopes list." + }, "rust-analyzer.rainbowHighlightingOn": { "type": "boolean", "default": false, @@ -488,4 +550,4 @@ } ] } -} +} \ No newline at end of file diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 12823f319..234a390ac 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -48,11 +48,13 @@ export class Config { const config = vscode.workspace.getConfiguration('rust-analyzer'); Server.highlighter.removeHighlights(); - scopes.load() - scopesMapper.load() - if (config.has('highlightingOn')) { + if (config.has('highlightingOn')) { this.highlightingOn = config.get('highlightingOn') as boolean; + if (this.highlightingOn) { + scopes.load(); + scopesMapper.load(); + } } if (config.has('rainbowHighlightingOn')) { @@ -61,9 +63,6 @@ export class Config { ) as boolean; } - if (!this.highlightingOn && Server) { - Server.highlighter.removeHighlights(); - } if (config.has('enableEnhancedTyping')) { this.enableEnhancedTyping = config.get( diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index dad99254e..1c67e5dc3 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -1,7 +1,7 @@ import seedrandom = require('seedrandom'); import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; -import * as scopes from './scopes' +import * as scopes from './scopes'; import * as scopesMapper from './scopes_mapper'; import { Server } from './server'; @@ -25,35 +25,35 @@ function fancify(seed: string, shade: 'light' | 'dark') { return `hsl(${h},${s}%,${l}%)`; } + function createDecorationFromTextmate(themeStyle: scopes.TextMateRuleSettings): vscode.TextEditorDecorationType { - const options: vscode.DecorationRenderOptions = {} - options.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen + const options: vscode.DecorationRenderOptions = {}; + options.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; if (themeStyle.foreground) { - options.color = themeStyle.foreground + options.color = themeStyle.foreground; } if (themeStyle.background) { - options.backgroundColor = themeStyle.background + options.backgroundColor = themeStyle.background; } if (themeStyle.fontStyle) { - const parts: string[] = themeStyle.fontStyle.split(' ') + const parts: string[] = themeStyle.fontStyle.split(' '); parts.forEach((part) => { switch (part) { case 'italic': - options.fontStyle = 'italic' - break + options.fontStyle = 'italic'; + break; case 'bold': - options.fontWeight = 'bold' - - break + options.fontWeight = 'bold'; + break; case 'underline': - options.textDecoration = 'underline' - break + options.textDecoration = 'underline'; + break; default: - break + break; } }) } - return vscode.window.createTextEditorDecorationType(options) + return vscode.window.createTextEditorDecorationType(options); } export class Highlighter { @@ -66,7 +66,7 @@ export class Highlighter { textDecoration?: string ): [string, vscode.TextEditorDecorationType] => { - const rule = scopesMapper.toRule(tag, scopes.find) + const rule = scopesMapper.toRule(tag, scopes.find); if (rule) { const decor = createDecorationFromTextmate(rule); diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 5d4395930..a6138fad0 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -1,41 +1,41 @@ -import * as fs from 'fs' -import * as path from 'path' -import * as vscode from 'vscode' +import * as fs from 'fs'; +import * as path from 'path'; +import * as vscode from 'vscode'; export interface TextMateRule { - scope: string | string[] - settings: TextMateRuleSettings + scope: string | string[]; + settings: TextMateRuleSettings; } export interface TextMateRuleSettings { - foreground: string | undefined - background: string | undefined - fontStyle: string | undefined + foreground: string | undefined; + background: string | undefined; + fontStyle: string | undefined; } // Current theme colors -const rules = new Map() +const rules = new Map(); export function find(scope: string): TextMateRuleSettings | undefined { - return rules.get(scope) + return rules.get(scope); } // Load all textmate scopes in the currently active theme export function load() { // Remove any previous theme - rules.clear() + rules.clear(); // Find out current color theme - const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme') + const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme'); if (typeof themeName !== 'string') { // console.warn('workbench.colorTheme is', themeName) - return + return; } // Try to load colors from that theme try { - loadThemeNamed(themeName) + loadThemeNamed(themeName); } catch (e) { // console.warn('failed to load theme', themeName, e) } @@ -44,7 +44,7 @@ export function load() { function filterThemeExtensions(extension: vscode.Extension): boolean { return extension.extensionKind === vscode.ExtensionKind.UI && extension.packageJSON.contributes && - extension.packageJSON.contributes.themes + extension.packageJSON.contributes.themes; } @@ -59,17 +59,17 @@ function loadThemeNamed(themeName: string) { .filter((element: any) => (element.id || element.label) === themeName) .map((element: any) => path.join(extension.extensionPath, element.path)) .concat(list) - }, Array()) + }, Array()); - themePaths.forEach(loadThemeFile) + themePaths.forEach(loadThemeFile); const tokenColorCustomizations: [any] = [vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations')] tokenColorCustomizations .filter(custom => custom && custom.textMateRules) .map(custom => custom.textMateRules) - .forEach(loadColors) + .forEach(loadColors); } @@ -79,26 +79,26 @@ function loadThemeFile(themePath: string) { .filter(isFile) .map(readFileText) .map(parseJSON) - .filter(theme => theme) + .filter(theme => theme); themeContent .filter(theme => theme.tokenColors) .map(theme => theme.tokenColors) - .forEach(loadColors) + .forEach(loadColors); themeContent .filter(theme => theme.include) .map(theme => path.join(path.dirname(themePath), theme.include)) - .forEach(loadThemeFile) + .forEach(loadThemeFile); } function mergeRuleSettings(defaultSetting: TextMateRuleSettings | undefined, override: TextMateRuleSettings): TextMateRuleSettings { - if (defaultSetting === undefined) { return override } - const mergedRule = defaultSetting + if (defaultSetting === undefined) { return override; } + const mergedRule = defaultSetting; - mergedRule.background = override.background || defaultSetting.background - mergedRule.foreground = override.foreground || defaultSetting.foreground - mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground + mergedRule.background = override.background || defaultSetting.background; + mergedRule.foreground = override.foreground || defaultSetting.foreground; + mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; return mergedRule } @@ -106,29 +106,29 @@ function mergeRuleSettings(defaultSetting: TextMateRuleSettings | undefined, ove function updateRules(scope: string, updatedSettings: TextMateRuleSettings): void { [rules.get(scope)] .map(settings => mergeRuleSettings(settings, updatedSettings)) - .forEach(settings => rules.set(scope, settings)) + .forEach(settings => rules.set(scope, settings)); } function loadColors(textMateRules: TextMateRule[]): void { textMateRules.forEach(rule => { if (typeof rule.scope === 'string') { - updateRules(rule.scope, rule.settings) + updateRules(rule.scope, rule.settings); } else if (rule.scope instanceof Array) { - rule.scope.forEach(scope => updateRules(scope, rule.settings)) + rule.scope.forEach(scope => updateRules(scope, rule.settings)); } }) } function isFile(filePath: string): boolean { - return [filePath].map(fs.statSync).every(stat => stat.isFile()) + return [filePath].map(fs.statSync).every(stat => stat.isFile()); } function readFileText(filePath: string): string { - return fs.readFileSync(filePath, 'utf8') + return fs.readFileSync(filePath, 'utf8'); } // Might need to replace with JSONC if a theme contains comments. function parseJSON(content: string): any { - return JSON.parse(content) + return JSON.parse(content); } \ No newline at end of file diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 19a4213d4..7056a8e24 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -1,10 +1,9 @@ -import * as vscode from 'vscode' -import { TextMateRuleSettings } from './scopes' +import * as vscode from 'vscode'; +import { TextMateRuleSettings } from './scopes'; - -let mappings = new Map() +let mappings = new Map(); const defaultMapping = new Map([ @@ -27,25 +26,39 @@ const defaultMapping = new Map([ ['field', ['variable.object.property', 'meta.field.declaration', 'meta.definition.property', 'variable.other',]], ['module', ['entity.name.section', 'entity.other']] ] -) +); // Temporary exported for debugging for now. export function find(scope: string): string[] { - return mappings.get(scope) || [] + return mappings.get(scope) || []; } export function toRule(scope: string, intoRule: (scope: string) => TextMateRuleSettings | undefined): TextMateRuleSettings | undefined { - return find(scope).map(intoRule).filter(rule => rule !== undefined)[0] + return find(scope).map(intoRule).filter(rule => rule !== undefined)[0]; +} + + +function isString(value: any): value is string { + return typeof value === 'string'; +} + +function isArrayOfString(value: any): value is string[] { + return Array.isArray(value) && value.every(item => isString(item)); } export function load() { - const configuration = vscode.workspace + const rawConfig: { [key: string]: any } = vscode.workspace .getConfiguration('rust-analyzer') - .get('scopeMappings') as Map | undefined - || new Map() + .get('scopeMappings') + || {}; - mappings = new Map([...Array.from(defaultMapping.entries()), ...Array.from(configuration.entries())]) + mappings = Object + .entries(rawConfig) + .filter(([_, value]) => isString(value) || isArrayOfString(value)) + .reduce((list, [key, value]: [string, string | string[]]) => { + return list.set(key, isString(value) ? [value] : value); + }, defaultMapping); } \ No newline at end of file -- cgit v1.2.3 From f49781c32d82489374d0924b70b31fa7a225464b Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 5 Nov 2019 00:11:43 +0100 Subject: Logging fallback tag in case scopes are missing. --- editors/code/src/highlighting.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 1c67e5dc3..b184437fc 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -73,11 +73,13 @@ export class Highlighter { 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('Missing theme for: <"' + tag + '"> for following mapped scopes:'); + console.log(scopesMapper.find(tag)); + console.log('Falling back to values defiend in: ' + fallBackTag); console.log(' '); - const color = new vscode.ThemeColor('ralsp.' + tag); + const color = new vscode.ThemeColor(fallBackTag); const decor = vscode.window.createTextEditorDecorationType({ color, textDecoration -- cgit v1.2.3 From 2f1b363b390d41b2db8ebdfa691ff42068e801d0 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 5 Nov 2019 00:16:31 +0100 Subject: Remove new line. --- editors/code/src/scopes_mapper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 7056a8e24..dfb8bf217 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -58,7 +58,6 @@ export function load() { .filter(([_, value]) => isString(value) || isArrayOfString(value)) .reduce((list, [key, value]: [string, string | string[]]) => { return list.set(key, isString(value) ? [value] : value); - }, defaultMapping); } \ No newline at end of file -- cgit v1.2.3 From ec82ca8391603edad974191ec839e2ad8a4234c0 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 5 Nov 2019 00:18:16 +0100 Subject: Clearer docs usage under `rust-analyzer.scopeMappings`. --- docs/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index 42742c0e6..909e574d0 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -89,7 +89,7 @@ host. //Will autocomplete keys to available RA scopes. "keyword.unsafe": ["keyword", "keyword.control"], //Values are string | TextMateScope | [string | TextMateScope] - "comments": "comment.block" + "variable.mut": "variable" } ``` * `rust-analyzer.enableEnhancedTyping`: by default, rust-analyzer intercepts -- cgit v1.2.3 From 6012bbfc514dd086f422afffa23f8713ccc09854 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 5 Nov 2019 00:26:49 +0100 Subject: Fix typo. --- editors/code/src/highlighting.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index b184437fc..3f509e8ee 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -77,7 +77,7 @@ export class Highlighter { console.log(' '); console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); console.log(scopesMapper.find(tag)); - console.log('Falling back to values defiend in: ' + fallBackTag); + console.log('Falling back to values defined in: ' + fallBackTag); console.log(' '); const color = new vscode.ThemeColor(fallBackTag); const decor = vscode.window.createTextEditorDecorationType({ -- cgit v1.2.3 From 45533112c80dd1cda19144b993f609ecee4861a8 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 5 Nov 2019 14:22:09 +0100 Subject: See if this satisfies the CI. --- editors/code/src/highlighting.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 3f509e8ee..ee39ca64c 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -74,11 +74,11 @@ export class Highlighter { } 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(' '); + // 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, -- cgit v1.2.3 From 83a33fbbeae9cbec8bec855e9338b7ccd08bd3a0 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sat, 9 Nov 2019 17:23:30 +0100 Subject: Vscode wasn't running the linter automatically so ran `npm run fix` - wonder if it's related to `tslint` being deprecated. --- editors/code/package.json | 2 +- editors/code/src/config.ts | 5 +-- editors/code/src/extension.ts | 10 ++--- editors/code/src/highlighting.ts | 81 ++++++++++++++------------------------- editors/code/src/scopes.ts | 60 +++++++++++++++++------------ editors/code/src/scopes_mapper.ts | 58 ++++++++++++++++++---------- 6 files changed, 110 insertions(+), 106 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 35f2f1e62..5c5be34db 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -550,4 +550,4 @@ } ] } -} \ No newline at end of file +} diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 234a390ac..4cedbea46 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -46,14 +46,14 @@ export class Config { public userConfigChanged() { const config = vscode.workspace.getConfiguration('rust-analyzer'); - + Server.highlighter.removeHighlights(); if (config.has('highlightingOn')) { this.highlightingOn = config.get('highlightingOn') as boolean; if (this.highlightingOn) { scopes.load(); - scopesMapper.load(); + scopesMapper.load(); } } @@ -63,7 +63,6 @@ export class Config { ) as boolean; } - if (config.has('enableEnhancedTyping')) { this.enableEnhancedTyping = config.get( 'enableEnhancedTyping' diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 07a5c59e8..c06928d12 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -91,11 +91,11 @@ export function activate(context: vscode.ExtensionContext) { const allNotifications: Iterable< [string, lc.GenericNotificationHandler] > = [ - [ - 'rust-analyzer/publishDecorations', - notifications.publishDecorations.handle - ] - ]; + [ + 'rust-analyzer/publishDecorations', + notifications.publishDecorations.handle + ] + ]; const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); // The events below are plain old javascript events, triggered and handled by vscode diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index ee39ca64c..14199dbea 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -25,35 +25,15 @@ function fancify(seed: string, shade: 'light' | 'dark') { return `hsl(${h},${s}%,${l}%)`; } - -function createDecorationFromTextmate(themeStyle: scopes.TextMateRuleSettings): vscode.TextEditorDecorationType { - const options: vscode.DecorationRenderOptions = {}; - options.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; - if (themeStyle.foreground) { - options.color = themeStyle.foreground; - } - if (themeStyle.background) { - options.backgroundColor = themeStyle.background; - } - if (themeStyle.fontStyle) { - const parts: string[] = themeStyle.fontStyle.split(' '); - parts.forEach((part) => { - switch (part) { - case 'italic': - options.fontStyle = 'italic'; - break; - case 'bold': - options.fontWeight = 'bold'; - break; - case 'underline': - options.textDecoration = 'underline'; - break; - default: - break; - } - }) - } - return vscode.window.createTextEditorDecorationType(options); +function createDecorationFromTextmate( + themeStyle: scopes.TextMateRuleSettings +): vscode.TextEditorDecorationType { + const decorationOptions: vscode.DecorationRenderOptions = {}; + decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; + decorationOptions.color = themeStyle.foreground; + decorationOptions.backgroundColor = themeStyle.background; + decorationOptions.fontStyle = themeStyle.fontStyle; + return vscode.window.createTextEditorDecorationType(decorationOptions); } export class Highlighter { @@ -65,14 +45,12 @@ export class Highlighter { tag: string, textDecoration?: string ): [string, vscode.TextEditorDecorationType] => { - const rule = scopesMapper.toRule(tag, scopes.find); if (rule) { const decor = createDecorationFromTextmate(rule); return [tag, decor]; - } - else { + } else { const fallBackTag = 'ralsp.' + tag; // console.log(' '); // console.log('Missing theme for: <"' + tag + '"> for following mapped scopes:'); @@ -91,25 +69,25 @@ export class Highlighter { 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'), - decoration('builtin'), - decoration('text'), - decoration('attribute'), - decoration('literal'), - decoration('macro'), - decoration('variable'), - decoration('variable.mut', 'underline'), - decoration('field'), - decoration('module') - ]; + decoration('comment'), + decoration('string'), + decoration('keyword'), + decoration('keyword.control'), + decoration('keyword.unsafe'), + decoration('function'), + decoration('parameter'), + decoration('constant'), + decoration('type'), + decoration('builtin'), + decoration('text'), + decoration('attribute'), + decoration('literal'), + decoration('macro'), + decoration('variable'), + decoration('variable.mut', 'underline'), + decoration('field'), + decoration('module') + ]; return new Map(decorations); } @@ -138,7 +116,6 @@ export 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(); } diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index a6138fad0..98099872c 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -2,8 +2,6 @@ import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; - - export interface TextMateRule { scope: string | string[]; settings: TextMateRuleSettings; @@ -27,7 +25,9 @@ export function load() { // Remove any previous theme rules.clear(); // Find out current color theme - const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme'); + const themeName = vscode.workspace + .getConfiguration('workbench') + .get('colorTheme'); if (typeof themeName !== 'string') { // console.warn('workbench.colorTheme is', themeName) @@ -42,38 +42,43 @@ export function load() { } function filterThemeExtensions(extension: vscode.Extension): boolean { - return extension.extensionKind === vscode.ExtensionKind.UI && + return ( + extension.extensionKind === vscode.ExtensionKind.UI && extension.packageJSON.contributes && - extension.packageJSON.contributes.themes; + extension.packageJSON.contributes.themes + ); } - - // Find current theme on disk function loadThemeNamed(themeName: string) { - const themePaths = vscode.extensions.all .filter(filterThemeExtensions) .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) + .filter( + (element: any) => + (element.id || element.label) === themeName + ) + .map((element: any) => + path.join(extension.extensionPath, element.path) + ) + .concat(list); }, Array()); - themePaths.forEach(loadThemeFile); - const tokenColorCustomizations: [any] = [vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations')] + const tokenColorCustomizations: [any] = [ + vscode.workspace + .getConfiguration('editor') + .get('tokenColorCustomizations') + ]; tokenColorCustomizations .filter(custom => custom && custom.textMateRules) .map(custom => custom.textMateRules) .forEach(loadColors); - } - function loadThemeFile(themePath: string) { const themeContent = [themePath] .filter(isFile) @@ -92,18 +97,26 @@ function loadThemeFile(themePath: string) { .forEach(loadThemeFile); } -function mergeRuleSettings(defaultSetting: TextMateRuleSettings | undefined, override: TextMateRuleSettings): TextMateRuleSettings { - if (defaultSetting === undefined) { return override; } +function mergeRuleSettings( + defaultSetting: TextMateRuleSettings | undefined, + override: TextMateRuleSettings +): TextMateRuleSettings { + if (defaultSetting === undefined) { + return override; + } const mergedRule = defaultSetting; mergedRule.background = override.background || defaultSetting.background; mergedRule.foreground = override.foreground || defaultSetting.foreground; mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground; - return mergedRule + return mergedRule; } -function updateRules(scope: string, updatedSettings: TextMateRuleSettings): void { +function updateRules( + scope: string, + updatedSettings: TextMateRuleSettings +): void { [rules.get(scope)] .map(settings => mergeRuleSettings(settings, updatedSettings)) .forEach(settings => rules.set(scope, settings)); @@ -113,11 +126,10 @@ function loadColors(textMateRules: TextMateRule[]): void { textMateRules.forEach(rule => { if (typeof rule.scope === 'string') { updateRules(rule.scope, rule.settings); - } - else if (rule.scope instanceof Array) { + } else if (rule.scope instanceof Array) { rule.scope.forEach(scope => updateRules(scope, rule.settings)); } - }) + }); } function isFile(filePath: string): boolean { @@ -128,7 +140,7 @@ function readFileText(filePath: string): string { return fs.readFileSync(filePath, 'utf8'); } -// Might need to replace with JSONC if a theme contains comments. +// Might need to replace with JSONC if a theme contains comments. function parseJSON(content: string): any { return JSON.parse(content); -} \ No newline at end of file +} diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index dfb8bf217..85c791ff5 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -1,17 +1,25 @@ import * as vscode from 'vscode'; import { TextMateRuleSettings } from './scopes'; - - let mappings = new Map(); - const defaultMapping = new Map([ - ['comment', ['comment', 'comment.block', 'comment.line', 'comment.block.documentation']], + [ + 'comment', + [ + 'comment', + 'comment.block', + 'comment.line', + 'comment.block.documentation' + ] + ], ['string', ['string']], ['keyword', ['keyword']], ['keyword.control', ['keyword.control', 'keyword', 'keyword.other']], - ['keyword.unsafe', ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword']], + [ + 'keyword.unsafe', + ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword'] + ], ['function', ['entity.name.function']], ['parameter', ['variable.parameter']], ['constant', ['constant', 'variable']], @@ -23,21 +31,32 @@ const defaultMapping = new Map([ ['macro', ['support.other']], ['variable', ['variable']], ['variable.mut', ['variable', 'storage.modifier']], - ['field', ['variable.object.property', 'meta.field.declaration', 'meta.definition.property', 'variable.other',]], + [ + 'field', + [ + 'variable.object.property', + 'meta.field.declaration', + 'meta.definition.property', + 'variable.other' + ] + ], ['module', ['entity.name.section', 'entity.other']] -] -); +]); -// Temporary exported for debugging for now. +// Temporary exported for debugging for now. export function find(scope: string): string[] { return mappings.get(scope) || []; } -export function toRule(scope: string, intoRule: (scope: string) => TextMateRuleSettings | undefined): TextMateRuleSettings | undefined { - return find(scope).map(intoRule).filter(rule => rule !== undefined)[0]; +export function toRule( + scope: string, + intoRule: (scope: string) => TextMateRuleSettings | undefined +): TextMateRuleSettings | undefined { + return find(scope) + .map(intoRule) + .filter(rule => rule !== undefined)[0]; } - function isString(value: any): value is string { return typeof value === 'string'; } @@ -46,18 +65,15 @@ function isArrayOfString(value: any): value is string[] { return Array.isArray(value) && value.every(item => isString(item)); } - export function load() { - const rawConfig: { [key: string]: any } = vscode.workspace - .getConfiguration('rust-analyzer') - .get('scopeMappings') - || {}; + const rawConfig: { [key: string]: any } = + vscode.workspace + .getConfiguration('rust-analyzer') + .get('scopeMappings') || {}; - mappings = Object - .entries(rawConfig) + mappings = Object.entries(rawConfig) .filter(([_, value]) => isString(value) || isArrayOfString(value)) .reduce((list, [key, value]: [string, string | string[]]) => { return list.set(key, isString(value) ? [value] : value); }, defaultMapping); - -} \ No newline at end of file +} -- cgit v1.2.3 From 3886164bcce734825d20a1af08ce359fbe0710e3 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Sun, 10 Nov 2019 22:30:53 +0100 Subject: Probably a better approach to check for values before assigning lest we replace something. --- editors/code/src/highlighting.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 14199dbea..0a38c9ef6 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -30,9 +30,33 @@ function createDecorationFromTextmate( ): vscode.TextEditorDecorationType { const decorationOptions: vscode.DecorationRenderOptions = {}; decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; - decorationOptions.color = themeStyle.foreground; - decorationOptions.backgroundColor = themeStyle.background; - decorationOptions.fontStyle = themeStyle.fontStyle; + + 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 e5bbb476800c9bf24820701ec9252153ba07cf6a Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Mon, 18 Nov 2019 02:37:18 +0100 Subject: Readding jsonc parser because of https://github.com/rust-analyzer/rust-analyzer/pull/2061\#discussion_r344783715 --- editors/code/package-lock.json | 5 +++++ editors/code/package.json | 3 ++- editors/code/src/scopes.ts | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 9c55c257f..a41497a23 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -720,6 +720,11 @@ "esprima": "^4.0.0" } }, + "jsonc-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.0.tgz", + "integrity": "sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==" + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 5c5be34db..fbf675d46 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -32,7 +32,8 @@ }, "dependencies": { "seedrandom": "^3.0.1", - "vscode-languageclient": "^5.3.0-next.4" + "vscode-languageclient": "^5.3.0-next.4", + "jsonc-parser": "^2.1.0" }, "devDependencies": { "@types/glob": "^7.1.1", diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 98099872c..8f288d761 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -1,4 +1,5 @@ import * as fs from 'fs'; +import * as jsonc from 'jsonc-parser'; import * as path from 'path'; import * as vscode from 'vscode'; @@ -140,7 +141,6 @@ function readFileText(filePath: string): string { return fs.readFileSync(filePath, 'utf8'); } -// Might need to replace with JSONC if a theme contains comments. function parseJSON(content: string): any { - return JSON.parse(content); + return jsonc.parse(content); } -- cgit v1.2.3 From 25537d294cb7a3e01d2329a7d07b469d734fc829 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 24 Dec 2019 00:04:36 +0100 Subject: Fix https://github.com/rust-analyzer/rust-analyzer/pull/2061#discussion_r348716036 Fix https://github.com/rust-analyzer/rust-analyzer/pull/2061/files/68a5ff050faf514e9d122212a66703ca8ce66ab7#r361019340 --- editors/code/package-lock.json | 5 +++++ editors/code/src/highlighting.ts | 4 ++-- editors/code/src/scopes.ts | 10 +++++----- editors/code/src/scopes_mapper.ts | 17 ++++++++--------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 4c5c13646..67081f3fd 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -750,6 +750,11 @@ "esprima": "^4.0.0" } }, + "jsonc-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.0.tgz", + "integrity": "sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==" + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 68eae0941..4e224a54c 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -26,7 +26,7 @@ function fancify(seed: string, shade: 'light' | 'dark') { } function createDecorationFromTextmate( - themeStyle: scopes.TextMateRuleSettings + themeStyle: scopes.TextMateRuleSettings, ): vscode.TextEditorDecorationType { const decorationOptions: vscode.DecorationRenderOptions = {}; decorationOptions.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen; @@ -84,7 +84,7 @@ export class Highlighter { const color = new vscode.ThemeColor(fallBackTag); const decor = vscode.window.createTextEditorDecorationType({ color, - textDecoration + textDecoration, }); return [tag, decor]; } diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts index 8f288d761..cb250b853 100644 --- a/editors/code/src/scopes.ts +++ b/editors/code/src/scopes.ts @@ -58,10 +58,10 @@ function loadThemeNamed(themeName: string) { return extension.packageJSON.contributes.themes .filter( (element: any) => - (element.id || element.label) === themeName + (element.id || element.label) === themeName, ) .map((element: any) => - path.join(extension.extensionPath, element.path) + path.join(extension.extensionPath, element.path), ) .concat(list); }, Array()); @@ -71,7 +71,7 @@ function loadThemeNamed(themeName: string) { const tokenColorCustomizations: [any] = [ vscode.workspace .getConfiguration('editor') - .get('tokenColorCustomizations') + .get('tokenColorCustomizations'), ]; tokenColorCustomizations @@ -100,7 +100,7 @@ function loadThemeFile(themePath: string) { function mergeRuleSettings( defaultSetting: TextMateRuleSettings | undefined, - override: TextMateRuleSettings + override: TextMateRuleSettings, ): TextMateRuleSettings { if (defaultSetting === undefined) { return override; @@ -116,7 +116,7 @@ function mergeRuleSettings( function updateRules( scope: string, - updatedSettings: TextMateRuleSettings + updatedSettings: TextMateRuleSettings, ): void { [rules.get(scope)] .map(settings => mergeRuleSettings(settings, updatedSettings)) diff --git a/editors/code/src/scopes_mapper.ts b/editors/code/src/scopes_mapper.ts index 85c791ff5..e738fa239 100644 --- a/editors/code/src/scopes_mapper.ts +++ b/editors/code/src/scopes_mapper.ts @@ -10,15 +10,15 @@ const defaultMapping = new Map([ 'comment', 'comment.block', 'comment.line', - 'comment.block.documentation' - ] + 'comment.block.documentation', + ], ], ['string', ['string']], ['keyword', ['keyword']], ['keyword.control', ['keyword.control', 'keyword', 'keyword.other']], [ 'keyword.unsafe', - ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword'] + ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword'], ], ['function', ['entity.name.function']], ['parameter', ['variable.parameter']], @@ -28,7 +28,7 @@ const defaultMapping = new Map([ ['text', ['string', 'string.quoted', 'string.regexp']], ['attribute', ['keyword']], ['literal', ['string', 'string.quoted', 'string.regexp']], - ['macro', ['support.other']], + ['macro', ['entity.name.function', 'keyword.other', 'entity.name.macro']], ['variable', ['variable']], ['variable.mut', ['variable', 'storage.modifier']], [ @@ -37,20 +37,19 @@ const defaultMapping = new Map([ 'variable.object.property', 'meta.field.declaration', 'meta.definition.property', - 'variable.other' - ] + 'variable.other', + ], ], - ['module', ['entity.name.section', 'entity.other']] + ['module', ['entity.name.section', 'entity.other']], ]); -// Temporary exported for debugging for now. export function find(scope: string): string[] { return mappings.get(scope) || []; } export function toRule( scope: string, - intoRule: (scope: string) => TextMateRuleSettings | undefined + intoRule: (scope: string) => TextMateRuleSettings | undefined, ): TextMateRuleSettings | undefined { return find(scope) .map(intoRule) -- cgit v1.2.3