Sublime Forum

Plugin which shows a popup with all keybindings

#1

I’m posting this here in case some people may find it useful.

I implemented my own Git implementation on top of ST. In some Git views I use a lot of key-bndings (e.g. for Git Diff I can press c to commit, z to revert a hunk, etc.). Since I have a lot of these key bindings, I often forget them. As such I wanted to be able to press h and see all the key bindings associated to a given Git view.

The helper is dynamically generated by Default.sublime-keymap.

"""
On 'h' keypress, show a popup re. the key bindings available for a
given view. Used mostly for Git views.

The help is dinamically generated by Default.sublime-keymap file like this.
Enable helper for a given context:

    { "keys": ["h"],
      "command": "show_helper",
      "args": {"marker": [{ "key": "setting.git_diff_view" }] },
      "context": [{ "key": "setting.git_diff_view" }] },

Add an entry:

    { "keys": ["c"],
      "command": "git_diff_view_commit",
      "context": [{ "key": "setting.git_diff_view" }],
      "help": "commit" },
"""

import os

import sublime
import sublime_plugin
from sublime_plugin import WindowCommand

SUBLIME_ROOT_DIR = os.path.realpath(os.path.dirname(sublime.packages_path()))
SUBLIME_USER_DIR = os.path.join(SUBLIME_ROOT_DIR, "Packages", "User")


HTML = """
<html>
<style>
html {
    border: 1px solid white;
}
h2 {
    margin-top: 0;
    color: #fce566;
    font-size: 1.2em;
}
ul {
    border: 0px solid white;
    padding-left: 13px;
}
.header-wrapper {
    border: 0px solid white;
}
.shortcut-key {
    font-weight: bold;
    color: #fce566;
}
</style>
<body>
    <h2>Keyboard Shortcuts</h2>
    <ul>
    %s
    </ul>
</body>
</html>
"""


def show_helper(keys):
    popup_max_width = 800
    popup_max_height = 800
    view = sublime.active_window().active_view()
    items = []
    for key, help in keys:
        key = ", ".join(key).replace("+", " + ")
        key += "&nbsp;" * (22 - len(key))
        items.append(
            f'<li><code><span class="shortcut-key">{key}</span><span class="helper"></span>{help}</code></li>'  # noqa
        )
    html = HTML % "\n".join(items)
    view.show_popup(html, 0, -1, popup_max_width, popup_max_height)


# key: ?
class ShowHelperCommand(WindowCommand):
    def run(self, marker):
        file = os.path.join(SUBLIME_USER_DIR, "Default (Linux).sublime-keymap")
        with open(file) as f:
            js = sublime.decode_value(f.read())  # json without comments
        keys = []
        for item in js:
            if item.get("context") == marker and "help" in item:
                keys.append((item["keys"], item["help"]))
        show_helper(keys)
3 Likes

#2

Hi @giampaolo,
Thanks for that! I like it very much. Maybe you could make repository out of it? There is possibly room for a few additions.

0 Likes

#3

Yep, I’d like to release it. What I lack right now is time. :slight_smile:

There is possibly room for a few additions.

I’m curious: do you have some ideas?

0 Likes

#4

The main thing I see would be the possibility to change on the fly the package whose sublime-keymap is scanned (this could be done from a link in the popup or in the command palette for instance).
Perhaps also the possibility to apply a filter to the results if there are many keybindings at play.
Thanks again for this plugin, I use it daily!

0 Likes

#5

the possibility to change on the fly the package whose sublime-keymap is scanned

I’m not sure I understand what you mean. The only “dictator” here is the main keymap file (e.g. Default (Linux).sublime-keymap on Linux), nothing else. From there you specify for which views to show the helper based on context.

0 Likes

#6

What I meant is that I can sometimes be interested in the popup based on the DATA/Packages/User/Default (Linux).sublime-keymap file, and some other times in the one based on the DATA/Packages/LaTeXTools/Default (Linux).sublime-keymap for instance. But maybe am I missing something?

0 Likes

#7

Packages/User/Default (Linux).sublime-keymap is the last file being loaded and has precedence. It will overwrite the keys which are in common with Packages/LaTeXTools/Default (Linux).sublime-keymap.

You only need to care about Packages/User/Default (Linux).sublime-keymap, and define your helpers in there.

0 Likes

#8

Yes, but that would mean one has to copy the keys defined in various sublime-keymap files inside package folder into the main /User/Default (Linux).sublime-keymap one? That is definitely a solution, though I would consider more natural to keep these keys in their “own” sublime-keymap and ask for them separately. Anyway, this is only my opinion!

0 Likes

#9

Ah, I get what you mean now. Yes you would have to do that. I’m not sure how else you could override other packages’ keymaps other than doing it in the default keymap file.

But I get your point, it would be nice to avoid re-defining third-party keys as a whole. But I see no way to do that other than via override. You have to define helpers somewhere.

0 Likes

#10

I understand now where I was not clear! I override each package sublime-keymap file by using OdatNurd’s excellent OverrideAudit. This creates an override at DATA/Packages/User/LaTeXTools/Default (Linux).sublime-keymap for instance (sorry for not putting the User in the previous path). There I can put my "help": "command" entries.

0 Likes

#11

Just to throw this out there, you know that Packages/SomeRandomPackage/Default (Linux).sublime-keymap keymap files are actually loaded and contribute to the bindings that are in use, and you only need to add bindings to the version in your User package if you want to alter what the package provides by default, right?

(or, when the file in the package has the bindings commented out as an example, in which case you need to copy them in order to uncomment them).

0 Likes

#12

… and your OverrideAudit package is very handy to manage that. Thanks a lot for it!

0 Likes

#13

You don’t need to override to do that (in fact, overriding key bindings in a package like that is probably Not Good :tm: in the general case).

However, that said:

That’s not an override; that is you putting extra key bindings into the User package. An Override would be if you created file at DATA/Packages/LaTeXTools/Default (Linux).sublime-keymap (note the lack of User in there).

However, don’t do that; the appropriate way to alter the bindings is as mentioned in the post above.

0 Likes

#14

OK, I see. Thanks a lot for the advice!

0 Likes