aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/scopes.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/scopes.ts')
-rw-r--r--editors/code/src/scopes.ts134
1 files changed, 134 insertions, 0 deletions
diff --git a/editors/code/src/scopes.ts b/editors/code/src/scopes.ts
new file mode 100644
index 000000000..470ee716f
--- /dev/null
+++ b/editors/code/src/scopes.ts
@@ -0,0 +1,134 @@
1import * as fs from 'fs'
2import * as path from 'path'
3import * as vscode from 'vscode'
4
5
6
7export interface TextMateRule {
8 scope: string | string[]
9 settings: TextMateRuleSettings
10}
11
12export interface TextMateRuleSettings {
13 foreground: string | undefined
14 background: string | undefined
15 fontStyle: string | undefined
16}
17
18// Current theme colors
19const rules = new Map<string, TextMateRuleSettings>()
20
21export function find(scope: string): TextMateRuleSettings | undefined {
22 return rules.get(scope)
23}
24
25// Load all textmate scopes in the currently active theme
26export function load() {
27 // Remove any previous theme
28 rules.clear()
29 // Find out current color theme
30 const themeName = vscode.workspace.getConfiguration('workbench').get('colorTheme')
31
32 if (typeof themeName !== 'string') {
33 // console.warn('workbench.colorTheme is', themeName)
34 return
35 }
36 // Try to load colors from that theme
37 try {
38 loadThemeNamed(themeName)
39 } catch (e) {
40 // console.warn('failed to load theme', themeName, e)
41 }
42}
43
44// Find current theme on disk
45function loadThemeNamed(themeName: string) {
46
47 const themePaths = vscode.extensions.all
48 .filter(extension => extension.extensionKind === vscode.ExtensionKind.UI)
49 .filter(extension => extension.packageJSON.contributes)
50 .filter(extension => extension.packageJSON.contributes.themes)
51 .reduce((list, extension) => {
52 const paths = extension.packageJSON.contributes.themes
53 .filter((element: any) => (element.id || element.label) === themeName)
54 .map((element: any) => path.join(extension.extensionPath, element.path))
55 return list.concat(paths)
56 }, Array<string>());
57
58
59 themePaths.forEach(loadThemeFile);
60
61 const customization: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations');
62 if (customization && customization.textMateRules) {
63 loadColors(customization.textMateRules)
64 }
65}
66
67function loadThemeFile(themePath: string) {
68
69 if (checkFileExists(themePath)) {
70 const themeContentText: string = readFileText(themePath)
71
72 const themeContent: any = JSON.parse(themeContentText)
73
74 if (themeContent && themeContent.tokenColors) {
75 loadColors(themeContent.tokenColors)
76 if (themeContent.include) {
77 // parse included theme file
78 const includedThemePath: string = path.join(path.dirname(themePath), themeContent.include)
79 loadThemeFile(includedThemePath)
80 }
81 }
82 }
83}
84function mergeRuleSettings(defaultSetting: TextMateRuleSettings, override: TextMateRuleSettings): TextMateRuleSettings {
85 const mergedRule = defaultSetting;
86
87 mergedRule.background = override.background || defaultSetting.background
88 mergedRule.foreground = override.foreground || defaultSetting.foreground
89 mergedRule.fontStyle = override.fontStyle || defaultSetting.foreground;
90
91 return mergedRule;
92}
93
94function loadColors(textMateRules: TextMateRule[]): void {
95 for (const rule of textMateRules) {
96
97 if (typeof rule.scope === 'string') {
98 const existingRule = rules.get(rule.scope);
99 if (existingRule) {
100 rules.set(rule.scope, mergeRuleSettings(existingRule, rule.settings))
101 }
102 else {
103 rules.set(rule.scope, rule.settings)
104 }
105 } else if (rule.scope instanceof Array) {
106 for (const scope of rule.scope) {
107 const existingRule = rules.get(scope);
108 if (existingRule) {
109 rules.set(scope, mergeRuleSettings(existingRule, rule.settings))
110 }
111 else {
112 rules.set(scope, rule.settings)
113 }
114 }
115 }
116 }
117}
118
119function checkFileExists(filePath: string): boolean {
120
121 const stats = fs.statSync(filePath);
122 if (stats && stats.isFile()) {
123 return true;
124 } else {
125 // console.warn('no such file', filePath)
126 return false;
127 }
128
129
130}
131
132function readFileText(filePath: string, encoding: string = 'utf8'): string {
133 return fs.readFileSync(filePath, encoding);
134} \ No newline at end of file