-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix problems that can occur when we can't find the theme json #5177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4663793
7406259
99b4f71
d70098e
deb3594
90c4bbe
ad28754
9e6009b
71b7592
4c4ce55
c1938c4
f1d8382
88b8e49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Default colors when theme.json cannot be found. | ||
| Fix python interactive window to update when theme changes. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,16 +9,18 @@ import * as stripJsonComments from 'strip-json-comments'; | |
|
|
||
| import { IWorkspaceService } from '../common/application/types'; | ||
| import { IConfigurationService, ILogger } from '../common/types'; | ||
| import { EXTENSION_ROOT_DIR } from '../constants'; | ||
| import { DefaultTheme, Identifiers } from './constants'; | ||
| import { ICodeCssGenerator, IThemeFinder } from './types'; | ||
|
|
||
| // tslint:disable:no-any | ||
| const DarkTheme = 'dark'; | ||
| const LightTheme = 'light'; | ||
|
|
||
| // These are based on the colors generated by 'Default Light+' and are only set when we | ||
| // are ignoring themes. | ||
| //tslint:disable-next-line:no-multiline-string | ||
| const DefaultStyle = ` | ||
| //tslint:disable:no-multiline-string object-literal-key-quotes | ||
| const DefaultCssVars: { [key: string] : string } = { | ||
| LightTheme : ` | ||
| :root { | ||
| --override-widget-background: #f3f3f3; | ||
| --override-foreground: #000000; | ||
|
|
@@ -28,7 +30,42 @@ const DefaultStyle = ` | |
| --override-tabs-background: #f3f3f3; | ||
| --override-progress-background: #0066bf; | ||
| } | ||
| `; | ||
| `, | ||
| DarkTheme : ` | ||
| :root { | ||
| --override-widget-background: #1e1e1e; | ||
| --override-foreground: #d4d4d4; | ||
| --override-background: #1e1e1e; | ||
| --override-selection-background: #264f78; | ||
| --override-watermark-color: #3f3f46; | ||
| --override-tabs-background: #252526; | ||
| --override-progress-background: #0066bf; | ||
| } | ||
| ` | ||
| }; | ||
|
|
||
| // These colors below should match colors that come from either the Default Light+ theme or the Default Dark+ theme. | ||
| // They are used when we can't find a theme json file. | ||
| const DefaultColors: { [key: string] : string } = { | ||
| 'light.comment' : '#008000', | ||
| 'light.constant.numeric': '#09885a', | ||
| 'light.string' : '#a31515', | ||
| 'light.keyword.control' : '#AF00DB', | ||
| 'light.keyword.operator': '#000000', | ||
| 'light.variable' : '#001080', | ||
| 'light.entity.name.type': '#267f99', | ||
| 'light.support.function': '#795E26', | ||
| 'light.punctuation' : '#000000', | ||
| 'dark.comment' : '#6A9955', | ||
| 'dark.constant.numeric' : '#b5cea8', | ||
| 'dark.string' : '#ce9178', | ||
| 'dark.keyword.control' : '#C586C0', | ||
| 'dark.keyword.operator' : '#d4d4d4', | ||
| 'dark.variable' : '#9CDCFE', | ||
| 'dark.entity.name.type' : '#4EC9B0', | ||
| 'dark.support.function' : '#DCDCAA', | ||
| 'dark.punctuation' : '#1e1e1e' | ||
| }; | ||
|
|
||
| // This class generates css using the current theme in order to colorize code. | ||
| // | ||
|
|
@@ -45,17 +82,17 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| @inject(ILogger) private logger: ILogger) { | ||
| } | ||
|
|
||
| public generateThemeCss = async (): Promise<string> => { | ||
| public async generateThemeCss(isDark: boolean, theme: string): Promise<string> { | ||
| let css : string = ''; | ||
| try { | ||
| // First compute our current theme. | ||
| const workbench = this.workspaceService.getConfiguration('workbench'); | ||
| const ignoreTheme = this.configService.getSettings().datascience.ignoreVscodeTheme ? true : false; | ||
| const theme = ignoreTheme ? DefaultTheme : workbench.get<string>('colorTheme'); | ||
| const terminalCursor = workbench.get<string>('terminal.integrated.cursorStyle', 'block'); | ||
| theme = ignoreTheme ? DefaultTheme : theme; | ||
| const terminalCursor = workbench ? workbench.get<string>('terminal.integrated.cursorStyle', 'block') : 'block'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly part of this checkin, but the default for cursorStyle for VSCode is line, not block. #ByDesign
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you're thinking of editor cursor? Not terminal cursor? In reply to: 274060268 [](ancestors = 274060268,274059636) |
||
| const editor = this.workspaceService.getConfiguration('editor', undefined); | ||
| const font = editor.get<string>('fontFamily'); | ||
| const fontSize = editor.get<number>('fontSize'); | ||
| const font = editor ? editor.get<string>('fontFamily', 'Consolas, \'Courier New\', monospace') : 'Consolas, \'Courier New\', monospace'; | ||
| const fontSize = editor ? editor.get<number>('fontSize', 14) : 14; | ||
|
|
||
| // Then we have to find where the theme resources are loaded from | ||
| if (theme) { | ||
|
|
@@ -65,7 +102,11 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| // The tokens object then contains the necessary data to generate our css | ||
| if (tokenColors && font && fontSize) { | ||
| this.logger.logInformation('Using colors to generate CSS ...'); | ||
| css = this.generateCss(theme, tokenColors, font, fontSize, terminalCursor, ignoreTheme); | ||
| css = this.generateCss(theme, tokenColors, font, fontSize, terminalCursor, ignoreTheme ? LightTheme : undefined); | ||
| } else if (tokenColors === null && font && fontSize) { | ||
| // No colors found. See if we can figure out what type of theme we have | ||
| const style = isDark ? DarkTheme : LightTheme ; | ||
| css = this.generateCss(theme, null, font, fontSize, terminalCursor, style); | ||
| } | ||
| } | ||
| } catch (err) { | ||
|
|
@@ -92,43 +133,48 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| }); | ||
| } | ||
|
|
||
| private getScopeStyle = (tokenColors: JSONArray, scope: string, secondary?: string): { color: string; fontStyle: string } => { | ||
| private getScopeStyle = (tokenColors: JSONArray | null, scope: string, secondary: string, defaultStyle: string | undefined): { color: string; fontStyle: string } => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More of a style issue, but for X | undefined I'd usually just use ? notation, especially as a parameter. #ByDesign
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a difference though. x? notation means the caller doesn't have to send that parameter. X | undefined means they have to be explicit. This change was to force it to be explicit. In reply to: 274062994 [](ancestors = 274062994) |
||
| // Search through the scopes on the json object | ||
| let match = this.matchTokenColor(tokenColors, scope); | ||
| if (match < 0 && secondary) { | ||
| match = this.matchTokenColor(tokenColors, secondary); | ||
| } | ||
| const found = match >= 0 ? tokenColors[match] as any : null; | ||
| if (found !== null) { | ||
| const settings = found.settings; | ||
| if (settings && settings !== null) { | ||
| const fontStyle = settings.fontStyle ? settings.fontStyle : 'normal'; | ||
| const foreground = settings.foreground ? settings.foreground : 'var(--vscode-editor-foreground)'; | ||
|
|
||
| return { fontStyle, color: foreground }; | ||
| if (tokenColors) { | ||
| let match = this.matchTokenColor(tokenColors, scope); | ||
| if (match < 0 && secondary) { | ||
| match = this.matchTokenColor(tokenColors, secondary); | ||
| } | ||
| const found = match >= 0 ? tokenColors[match] as any : null; | ||
| if (found !== null) { | ||
| const settings = found.settings; | ||
| if (settings && settings !== null) { | ||
| const fontStyle = settings.fontStyle ? settings.fontStyle : 'normal'; | ||
| const foreground = settings.foreground ? settings.foreground : 'var(--vscode-editor-foreground)'; | ||
|
|
||
| return { fontStyle, color: foreground }; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Default to editor foreground | ||
| return { color: 'var(--vscode-editor-foreground)', fontStyle: 'normal' }; | ||
| return { color: this.getDefaultColor(defaultStyle, scope), fontStyle: 'normal' }; | ||
| } | ||
|
|
||
| private getDefaultColor(style: string | undefined, scope: string) : string { | ||
| return style ? DefaultColors[`${style}.${scope}`] : 'var(--override-foreground, var(--vscode-editor-foreground))'; | ||
| } | ||
|
|
||
| // tslint:disable-next-line:max-func-body-length | ||
| private generateCss(theme: string, tokenColors: JSONArray, fontFamily: string, fontSize: number, cursorType: string, generateDefaults: boolean): string { | ||
| private generateCss(theme: string, tokenColors: JSONArray | null, fontFamily: string, fontSize: number, cursorType: string, defaultStyle: string | undefined): string { | ||
| const escapedThemeName = Identifiers.GeneratedThemeName; | ||
|
|
||
| // There's a set of values that need to be found | ||
| const commentStyle = this.getScopeStyle(tokenColors, 'comment'); | ||
| const numericStyle = this.getScopeStyle(tokenColors, 'constant.numeric'); | ||
| const stringStyle = this.getScopeStyle(tokenColors, 'string'); | ||
| const keywordStyle = this.getScopeStyle(tokenColors, 'keyword.control', 'keyword'); | ||
| const operatorStyle = this.getScopeStyle(tokenColors, 'keyword.operator', 'keyword'); | ||
| const variableStyle = this.getScopeStyle(tokenColors, 'variable'); | ||
| const entityTypeStyle = this.getScopeStyle(tokenColors, 'entity.name.type'); | ||
| const commentStyle = this.getScopeStyle(tokenColors, 'comment', 'comment', defaultStyle); | ||
| const numericStyle = this.getScopeStyle(tokenColors, 'constant.numeric', 'constant', defaultStyle); | ||
| const stringStyle = this.getScopeStyle(tokenColors, 'string', 'string', defaultStyle); | ||
| const keywordStyle = this.getScopeStyle(tokenColors, 'keyword.control', 'keyword', defaultStyle); | ||
| const operatorStyle = this.getScopeStyle(tokenColors, 'keyword.operator', 'keyword', defaultStyle); | ||
| const variableStyle = this.getScopeStyle(tokenColors, 'variable', 'variable', defaultStyle); | ||
| const entityTypeStyle = this.getScopeStyle(tokenColors, 'entity.name.type', 'entity.name.type', defaultStyle); | ||
| // const atomic = this.getScopeColor(tokenColors, 'atomic'); | ||
| const builtinStyle = this.getScopeStyle(tokenColors, 'support.function'); | ||
| const punctuationStyle = this.getScopeStyle(tokenColors, 'punctuation'); | ||
| const overrides = generateDefaults ? DefaultStyle : ''; | ||
| const builtinStyle = this.getScopeStyle(tokenColors, 'support.function', 'support.function', defaultStyle); | ||
| const punctuationStyle = this.getScopeStyle(tokenColors, 'punctuation', 'punctuation', defaultStyle); | ||
|
|
||
| const def = 'var(--vscode-editor-foreground)'; | ||
|
|
||
|
|
@@ -150,7 +196,7 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| --code-font-size: ${fontSize}px; | ||
| } | ||
|
|
||
| ${overrides} | ||
| ${defaultStyle ? DefaultCssVars[defaultStyle] : undefined } | ||
|
|
||
| .cm-header, .cm-strong {font-weight: bold;} | ||
| .cm-em {font-style: italic;} | ||
|
|
@@ -206,7 +252,7 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| return []; | ||
| } | ||
|
|
||
| private findTokenColors = async (theme: string): Promise<JSONArray> => { | ||
| private findTokenColors = async (theme: string): Promise<JSONArray | null> => { | ||
|
|
||
| try { | ||
| this.logger.logInformation('Attempting search for colors ...'); | ||
|
|
@@ -256,8 +302,7 @@ export class CodeCssGenerator implements ICodeCssGenerator { | |
| this.logger.logError(err); | ||
| } | ||
|
|
||
| // We should return a default. The vscode-light theme | ||
| const defaultThemeFile = path.join(EXTENSION_ROOT_DIR, 'resources', 'defaultTheme.json'); | ||
| return this.readTokenColors(defaultThemeFile); | ||
| // Force the colors to the defaults | ||
| return null; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a good candidate for a manual test case in our CTI test plan file. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Is that in our source somewhere? I can update it here.
In reply to: 274056601 [](ancestors = 274056601)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup. .github/test_plan.md
In reply to: 274056754 [](ancestors = 274056754,274056601)