Sublime Forum

How to access colour scheme scopes in minihtml?

#1

I have a question about the combination of minihtml and colour schemes. Let’s say I want to create a pop-up, and style elements of it in the same way as parts of the main text. For example, a pop-up that represents some python code with strings in it. I would like to have the strings coloured in the same way as they are in the main view, i.e. the same colour as the scope string gets from the current colour scheme.

Can this be done? I haven’t found a way, here is a quick plugin to showcase the problem. I can use the predefined css variables to get a “yellowish” colour, but that’s only helpful for colour schemes which choose to make strings yellow. I also tried (as a shot in the dark) a couple of tags & attribute combinations that could logically represent the string scope, none of which work.

import sublime_plugin
import sublime

HTML = """
<html>
    <style>
        div.yellow {
            color: var(--yellowish);
        }
    </style>
    <body id="minihtml-test">
        <string>'test'</string>
        <div class="yellow">'test'</div>
        'test'
        <div class="string">'test'</div>
        <scope class="string">'test'</scope>
    </body>
</html>
"""

class MinihtmlTestListener(sublime_plugin.ViewEventListener):
    def on_hover(self, point, hover_zone):
        if hover_zone != sublime.HOVER_TEXT:
            return

        self.view.show_popup(
            HTML,
            flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
            on_navigate=self.on_navigate,
            on_hide=self.on_hide
        )

    def on_navigate(self, href):
        pass

    def on_hide(self):
        pass

I suppose you could get the current colour scheme using the API, and then open and parse the file to try find the right colour. But I’d rather not have to resort that kind of approach, it would feel really natural to be able to “talk” to colour schemes inside minihtml like this.

1 Like

#2

Here’s how mdpopups does it. It can be quite involved!

1 Like

#3

@rwols thanks for the reply. I was not aware of mdpopups, it looks very impressive. Regarding the original question, it would seem that there is no easy way to accomplish this out-of-the-box in Sublime Text? But on the other hand, existing packages such as mdpopups go some way to address this gap. Taking a quick look at the mdpopups code, it seem that this is roughly the function I wanted. Hmm.

0 Likes

#4

So, for reference, here’s what I’ve ended up doing. It works well for what I needed (one-off styling) but a more integrated approach with mdpopups might be a better choice elsewhere.

Anyway, the example becomes something like this (making sure that you have the dependencies for mdpopups all set up).

import sublime_plugin
import sublime
import mdpopups

HTML = """
<html>
    <style>
        {style}
    </style>
    <body id="minihtml-test">
        <div class="string">"test"</div>
    </body>
</html>
"""

CSS = """
html {{
    --string-style: {style};
    --string-color: {color};
    --string-bg-color: {bg_color};
}}

div.string {{
    font-style: var(--string-style);
    color: var(--string-color);
    background-color: var(--string-bg-color);
}}
"""

class MinihtmlTestListener(sublime_plugin.ViewEventListener):
    def on_hover(self, point, hover_zone):
        if hover_zone != sublime.HOVER_TEXT:
            return

        string = mdpopups.scope2style(self.view, "string.quoted.double")
        style = CSS.format(
            style=string.get("style"),
            color=string.get("color"),
            bg_color=string.get("background", "--background"),
        )
        self.view.show_popup(
            HTML.format(style=style),
            flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
            on_navigate=self.on_navigate,
            on_hide=self.on_hide,
        )

    def on_navigate(self, href):
        pass

    def on_hide(self):
        pass
0 Likes