Skip to content
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

[theming] Access theme's colors programmatically #32813

Open
fabiospampinato opened this issue Aug 19, 2017 · 35 comments
Open

[theming] Access theme's colors programmatically #32813

fabiospampinato opened this issue Aug 19, 2017 · 35 comments

Comments

@fabiospampinato
Copy link
Contributor

@fabiospampinato fabiospampinato commented Aug 19, 2017

I think we should add support for accessing theme's colors programmatically.

For instance let's take as an example the popular OneDark Pro theme, I'd like to access colors defined under tokenColors.

My use case: I'm making an extension that decorates some tokens, and I'd like them to have the same color that comments have in my theme, the problem is that the regex I use to find those tokens depends on some configurable value, so I cannot pre-compute it in advance and just put it in a .tmLanguage file.

It's already possible to somehow access colors defined under the colors key, via something like new vscode.ThemeColor ( 'activityBar.background' ), adding support for this sounds like a useful generalization to me.

What do you think?

@vscodebot vscodebot bot added the workbench label Aug 19, 2017
@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Aug 21, 2017

I'd rather avoid API that gives out the actual color, but hope that all can be done with color references. That way extensions don't need to worry about listening to theme changes. Yes, sounds like a useful idea but is not an easy addition as token colors are based on text mate theme rules and the text mate scope hierarchy.
If there are more requests, we can certainly look at it. Until then I recommend you to use one of the regular workbench colors, or - added to 1.16 - define a new color in your extension.

@aeschli aeschli self-assigned this Aug 21, 2017
@aeschli aeschli added this to the Backlog milestone Aug 21, 2017
@aeschli aeschli changed the title Access theme's colors programmatically [themeing] Access theme's colors programmatically Aug 21, 2017
@aeschli aeschli changed the title [themeing] Access theme's colors programmatically [theming] Access theme's colors programmatically Sep 15, 2017
@bpasero bpasero removed the workbench label Nov 16, 2017
@eamodio

This comment has been minimized.

Copy link
Member

@eamodio eamodio commented Mar 1, 2018

@aeschli while I still think an API for this would be valuable (or at the least an API that tells you if the current theme is light or dark), another alternative that might work in certain scenarios would be to expose the set of theme colors as css variables. This would allow the scenario here: #34411 (comment)

In theory I could use an SVG image, with colors pulled from the css variables, allowing me to get theme adaptable icons into the hovers.

Thoughts?

FYI, this is similar to this request #41785, but not just for the webview, for the editor itself.

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Mar 2, 2018

@eamodio Great idea. If using css variables in SVG images works then we should definitely do this. Let's track this in a separate issue!

@DanTup

This comment has been minimized.

Copy link
Contributor

@DanTup DanTup commented Apr 3, 2018

#46940 was closed as a dupe of this, but I'm not sure it's the same request. I have remotely-hosted SVGs I want to include in my markdown tooltips. I need to decide between the black and white versions so need to know whether VS Code considers the current theme light or dark. I don't need access to colours and I cannot modify the SVG.

@eamodio

This comment has been minimized.

Copy link
Member

@eamodio eamodio commented Jun 20, 2018

This issue has come up again. In GitLens, I would like to expose 2 colors (hot and cold versions) for the heatmap that GitLens generates, but I am unable to use theme colors, because I need access to the real color values to generate the full palette of colors required.

@vviikk

This comment has been minimized.

Copy link

@vviikk vviikk commented Jun 26, 2018

A lot of extensions would benefit from this. Bracket colorizer, jumpy, gitlens and a zillion others. Would be good to implement this.

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Jun 26, 2018

@piggyslasher Please explain how/where these extension could profit from this.

There is already a story that extensions can declare a new color (by id) and use it in decorations. Users can redefine these colors in themes.

@fabiospampinato

This comment has been minimized.

Copy link
Contributor Author

@fabiospampinato fabiospampinato commented Jun 26, 2018

My use case: I'm making an extension that decorates some tokens, and I'd like them to have the same color that comments have in my theme, the problem is that the regex I use to find those tokens depends on some configurable value, so I cannot pre-compute it in advance and just put it in a .tmLanguage file

@aeschli that's my use case. Sure, I'm already exporting these colors via the settings and users can override them already. But I can't just pick the colors for them automatically depending on what theme they are currently using. Also if someone uses one of those extensions for rotating themes I can't just expect them to update their settings every time.

@vviikk

This comment has been minimized.

Copy link

@vviikk vviikk commented Aug 17, 2018

@aeschli A use case in my scenario is I use the extension called "Bracket pair colorizer" with adds colors to matching brackets, like so:
image
Now, in order for the extension to render the brackets to match my theme, I have to hard code the colors into my settings:

image

Without this, I would end up with something that looks like this out of the box:
image

Notice the color of the brackets. They're from the extension's default preferences because the developer can't access the colors. I hope I'm on the right track.

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Aug 20, 2018

@piggyslasher Did you see that you can define new colors in the extension's package.json?

"contributes": {
  "colors": [{
      "id": "bracketPairColorizer.bracket1",
      "description": "Color for the outermost bracket",
      "defaults": {
          "dark": "#112233",
          "light": "#ddeeff",
          "highContrast": "foreground"
      }
  }]
}

Users can then customize the color in the workspace.colorCustomization setting and even themes can add a default color.

Color default values can be defined for light, dark and high contrast theme and can either be a reference to an existing color or a color hex value.

@tamuratak

This comment has been minimized.

Copy link
Contributor

@tamuratak tamuratak commented Oct 13, 2018

Hi,
I am working on a PR for LaTeX-Workshop, a VSCode extension for LaTeX editing. In the PR, I make a latex preview in hover available rendering math equations in SVG format with MathJax and embedding the dataurl of generated SVG into a markdown text as an image source.

When rendering math equations, I have to tell MathJax which color to use for each rendering. Otherwise rendered equations are invisible on a certain theme. To work around the lack of color API in VSCode, I have to render equations in a WebView process, not in an extension process because we can know colors form css variables in the WebView process, as suggested by @eamodio. So when LaTeX-Workshop users close a WebView pane, my PR does not work. For LaTeX-Workshop users, opening a WebView pane as a pdf viewer is a usual thing. So the lack of color api seems to be a minor thing.

However, the same can be said for other documents having TeX-like equations. Docstring in python, for example. Let's think about API documents with math equations written in docstring. Python libraries should have tons of such API documents. If we want to render equations in them with MathJax, and to display them with API documents in hover, the same problem happens. And, for python programmers while coding, opening a WebView pane is an unusual thing.

Please notice that, for this purpose, extensions don't have to listen to theme changes. Equations are dynamically rendered each time. MathJax is enough fast to do that.

Regards,

On a light theme.

oct-13-2018 10-46-17

On a dark theme.

oct-13-2018 10-48-16

@DanTup

This comment has been minimized.

Copy link
Contributor

@DanTup DanTup commented Jul 15, 2019

Here's another annoyance with not knowing if the theme is light or dark... Terminal ansi colours...

I had some code that used Grey and White in stack traces so that users own code frames was more visible (white) than framework code (grey). I tested it with both light and dark themes and found that the White ansi color codes produce a dark color in the themes (great!).

Well, until a user with a third party theme found that I was showing white text on a light background 😞

I figured I could raise this as a bug against their theme, however I failed to find any guidance on how themes should handle these, though I did found that in the VS Code code, ansiWhite is inverted for light/dark theme but ansiBlack is not which leaves me more confused.

@anaisbetts

This comment has been minimized.

Copy link

@anaisbetts anaisbetts commented Aug 23, 2019

Came here via @DanTup - I'm trying to write a VS Extension to sync your color theme to Windows Terminal, but this bug blocks it. This information is available internally (via "Generate Color Theme from Current Settings"), but I have no sane access to it

@paulyoung

This comment has been minimized.

Copy link

@paulyoung paulyoung commented Aug 23, 2019

@anaisbetts I’ve done this before. It’s not exactly sane but it worked for me at the time.

const getTokenColorsForTheme = (themeName: string): TokenColors => {
  const tokenColors = new Map();
  let currentThemePath;
  for (const extension of extensions.all) {
    const themes = extension.packageJSON.contributes && extension.packageJSON.contributes.themes;
    const currentTheme = themes && themes.find((theme) => theme.id === themeName);
    if (currentTheme) {
      currentThemePath = path.join(extension.extensionPath, currentTheme.path);
      break;
    }
  }
  const themePaths = [];
  if (currentThemePath) { themePaths.push(currentThemePath); }
  while (themePaths.length > 0) {
    const themePath = themePaths.pop();
    const theme = require(themePath);
    if (theme) {
      if (theme.include) {
        themePaths.push(path.join(path.dirname(themePath), theme.include));
      }
      if (theme.tokenColors) {
        theme.tokenColors.forEach((rule) => {
          if (typeof rule.scope === "string" && !tokenColors.has(rule.scope)) {
            tokenColors.set(rule.scope, rule.settings);
          } else if (rule.scope instanceof Array) {
            rule.scope.forEach((scope) => {
              if (!tokenColors.has(rule.scope)) {
                tokenColors.set(scope, rule.settings);
              }
            });
          }
        });
      }
    }
  }
  return tokenColors;
}

where

type TokenColors = Map<string, TokenColorSettings>

interface TokenColorSettings {
  background?: string
  fontStyle?: string
  foreground?: string
}
@paulyoung

This comment has been minimized.

Copy link

@paulyoung paulyoung commented Aug 23, 2019

Usage:

const themeName: string | undefined = workspace.getConfiguration("workbench").get("colorTheme");
const tokenColors = getTokenColorsForTheme(themeName);
@kufii

This comment has been minimized.

Copy link

@kufii kufii commented Sep 25, 2019

@paulyoung Thanks for the solution! pretty hacky but it worked for me

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Nov 25, 2019

This is a proposal for accessing the current workbench colors

	/**
	 * Represents a color theme kind.
	 */
	export enum ColorThemeKind {
		Light = 1,
		Dark = 2,
		HighContrast = 3
	}

	/**
	 * Represents a color theme.
	 */
	export interface ColorTheme {

		/**
		 * The kind of this color theme: light, dark or high contrast.
		 */
		readonly kind: ColorThemeKind;

		/**
		 * The id of the color theme. This corresponds to the value used in the `workbench.colorTheme` setting.
		 */
		readonly id: string;

		/**
		 * Get the color value for a color identifier.
		 *
		 * @param colorIdentifier A color identifier as defined in https://code.visualstudio.com/docs/getstarted/theme-color-reference
		 * or contributed by an extension.
		 * @return The color as defined by the theme or in the color defaults. If the color identifier is
		 * unknown, `undefined` is returned.
		 */
		getColor(colorIdentifier: ThemeColor): Color | undefined;
	}

	export namespace window {
		/**
		 * The currently active color theme as configured in the settings. The active
		 * theme can be changed via the `workbench.colorTheme` setting.
		 */
		export let activeColorTheme: ColorTheme;

		/**
		 * An [event](#Event) which fires when the active theme changes.
		 */
		export const onDidChangeActiveColorTheme: Event<ColorTheme>;
	}
@rchiodo

This comment has been minimized.

Copy link

@rchiodo rchiodo commented Nov 25, 2019

I'm not sure why that API is needed? All of those colors are available in the root CSS for a webview?

What we really want is the token colors, not the CSS colors.

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Nov 25, 2019

Token colors are coming too. I've just added the first implementation for #77133 and once that has settled I'll propose something like

function getTokenStyle(type: string, modifiers: string[]): TokenStyle;

interface TokenStyle {
   foreground: Color:
   bold: boolean:
   italics: boolean:
   underline: boolean;
} 
@Colengms

This comment has been minimized.

Copy link

@Colengms Colengms commented Nov 25, 2019

Would onDidChangeActiveColorTheme() fire when colors are changed by settings that override theme colors? (i.e. editor.tokenColorCustomizations).

@aeschli

This comment has been minimized.

Copy link
Contributor

@aeschli aeschli commented Nov 26, 2019

@Colengms Yes

@PEZ

This comment has been minimized.

Copy link

@PEZ PEZ commented Dec 2, 2019

@APerricone for Webviews you can use the vscode css vars in your css. Like I do here: https://github.com/BetterThanTomorrow/calva/tree/master/assets/styles

@APerricone

This comment has been minimized.

Copy link

@APerricone APerricone commented Dec 2, 2019

@PEZ sorry, i saw the documentation 5 minutes after the comment, so I removed the comment...
Thank you anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.