Sublime Forum

Generate keymaps using Python!

#1

Hello!

I’ve been using the hyper terminal (a web based terminal), and it’s way of configuring it kind of inspired me.

If you don’t use it, all you need to know is that the configuration file isn’t a JSON file, it’s a JavaScript one that exports an object which contains the config.

At first, I didn’t see the point, but it revealed to be quite useful. For example, in a terminal, you need base colors (black, white, red, blue, etc), but you also need a “light” version of it. Well, I just had to make a function that would lighten the base colors to get the light ones, without having to do it manually.

The current solution for making keybindings in Sublime Text doesn’t suit me very well. JSON isn’t the best markup langage in my opinion, and not being able to reuse contexts makes it a pain when you want to create unregular keybindings.

So, in this case, we’re not using JavaScript, but Python!

Hum… Mate, I don’t have Python installed on my machine, and I ain’t gonna do that just for this plugin…

You don’t need to install Python at all! It comes out of the box with Sublime Text!

Yeah… Fair enough… But I’m not sure I want to learn Python…

You definitely should. It’s an awesome langage, properly designed (unlike PHP or JavaScript), easy to type, and used everywhere (you can build games with pygame, servers with django/flask, etc…) But the best thing is that Sublime Text plugins are written in Python. So, if you ever want to make one to improve even more your workflow, you’ll be good to go!

So, here’s the package: kpymap. Just read the readme to learn how to use it, it’s pretty straight forward.

Here’s a quick example.

from kpymap import *
reset()

with context('selector', 'source.python'):
    add('.', '.', 'insert', {'characters': 'self.'})
    add('alt+f', 'fold_python_function')

add('ctrl+u', 'upper_case')
generate()

As soon as you save this, you’ll get:

[
    {
        "keys": [".", "."],
        "command": "insert",
        "args": {
            "characters": "self."
        },
        "context": [
            {"key": "selector", "operand": "source.python"}
        ]
    },
    {
        "keys": ["alt+f"],
        "command": "fold_python_function",
        "args": {
            "characters": "self."
        },
        "context": [
            {"key": "selector", "operand": "source.python"}
        ]
    }
    {
        "keys": ["ctrl+u"],
        "command": "upper_case"
    }
]

Note: the default value of operator in a context is equal. That’s why it is automatically removed in this case.

Using the with statement allows you to add a context to every keybinding in added in it. So, you don’t have to repeat yourself.

This is just one quick example, I’ll add more in the repo’s README soon.

Then, remember: it’s python. It’s a programming language. You can do whatever you want! For example, you could do this (by the way, I’m planning on adding these kind of helper functions by default)

So, in my case, I like to have all the shortcut that concern the appearance of ST (like toggling the side bar, the tabs, the minimap, etc) prefixed by ctrl+k. So what you can do is using some cool feature provided by Python out of the box: functools.

from kpymap import *
import functools
reset()

# 'vadd' now calls the function 'add' with the first argument being `ctrl+k`
vadd = functools.partial(add, 'ctrl+k')
vadd('ctrl+m', 'toggle_minimap')
vadd('ctrl+t', 'toggle_tabs')

generate()

Would give you:

[
    {
        "keys": ["ctrl+k", "ctrl+m"],
        "command": "toggle_minimap"
    },
    {
        "keys": ["ctrl+k", "ctrl+t"],
        "command": "toggle_tabs"
    }
]

So, it’s not much, but it might save you a bit of typing :smile:

That’s it. I need to write a bit more tests and some documention, but it should be usable by now.

Let me know what you think!

8 Likes

#2

Very interesting. Also I never considered that I could use keybindings to do character insertion. Gives my stutter typing for my own package some possibilities.

1 Like

#3

Configuration via a programming language is quite neat for certain tools and I do feel like st could profit from it like you are showing here.

The only thing I don’t like about these intermediate configuration formats (for example yaml macros for syntaxes, sane snippets, csscheme or just plainly using yaml->json conversion for some files) is that you now have two files that you have to ship in your package (and that one file shouldn’t be modified).
This happens a lot in the web development area with task runners like gulp and it’s not exactly ideal but your only real option if you don’t want to type everything raw.

1 Like