I’m trying to make a project specific shortcut key. In particular I want shortcut keys for the build systems in the project (there are multiple). Surely this is possible, but for the life of me I can’t get it to work.
Project specific shortcut key
Bear with me for some time as it’s going to be a long answer. As I understand your question, you want project specific key bindings for project specific build systems.
Let’s break it into several parts :-
-
Key bindings for build systems and their variants
Let’s say your project data is something along the lines of following :-
{
"folders": [
something
],
"build_systems": [
{
"name": "Echo Command",
"shell_cmd": "echo This is from the dummy build system",
"variants": [
{
"name": "variant 1",
"shell_cmd": "echo This is variant 1 of echo",
},
{
"name": "variant 2",
"shell_cmd": "echo This is variant 1 of echo",
}
],
}
],
}
(This is for demonstration purposes only which uses the echo
command. You can view project specific settings by going to Project: Edit Project
from the command palette)
So we have a main build system and two variants.
So the key binding for the main build system would be:
{
"keys": ["ctrl+alt+3"],
"command": "build",
"args": {
"build_system": "Echo Command",
"variant": "",
},
}
This defines a key binding that executes the build
command with the arguments of build_system
(The name of the build system, derived from the project specific build system setting name
) and a variant
in case we want to run any variants. So this will run the main Echo Command
build when you press the said binding. Similarly you can define key bindings for the other 2 variants by specifying their names in variant
based on what name
you gave them in project specific build systems.
So with that you can run project specific build systems with the help of key bindings.
-
Making the above key bindings project specific
In order to make these key bindings project specific, we need to make use of contexts. Contexts are a way to run a key binding only in certain situation. For example, if you have a certain number of selections, or your cursor is at a specific location etc. This feature actually makes a key binding reusable.
You can read more on context here :- https://www.sublimetext.com/docs/3/key_bindings.html#context
Sublime Text by default comes with a couple of contexts for us to use but unfortunately there is no context that can tell us if we are in a certain project. This is where plugins come into picture.
Note : From here own, I am making an assumption that you have some knowledge of python atleast as we need to use plugins.
The python API gives us an EventListener
class which has an on_query_context
method defined for it, which allows us to define our own contexts for key bindings.
Here is a plugin that gives us this ability to detect what project we are present in.
import os
import sublime
import sublime_plugin
class ProjectSpecificKeyBinding(sublime_plugin.EventListener):
def on_query_context(self, view, key, operator, operand, match_all):
current_project_name = view.window().project_file_name()
if key != "project_name" and os.path.isfile(current_project_name):
return None
if operator != sublime.OP_EQUAL and operator != sublime.OP_NOT_EQUAL:
return None
if operator == sublime.OP_EQUAL:
return current_project_name == operand
elif operator == sublime.OP_NOT_EQUAL:
return current_project_name != operand
return None
Follow the instructions in this gist (Don’t follow the second step in the gist on steps to use the plugin as this is an EventListener
and is “activated” as soon as you save it).
With this in place, the above key binding will be as follows :-
{
"keys": ["ctrl+alt+3"],
"command": "build",
"args": {
"build_system": "Echo Command",
"variant": "",
},
"context": [
{ "key": "project_name", "operator": "equal", "operand": "name_of_your_project" },
],
}
In order to make this work, replace the name_of_your_project
with the absolute path of your .sublime-project
associated with the project you want this key binding to be activated conditionally.
Now, the key binding ctrl+alt+3 can be reused across projects. All you have to do is define the same keybinding for each project (make sure to change the name_of_your_project
) with different args
(different build_system
and variant
) value.
Hope that helps
How to make keybindings available only in certain projects?
Thanks for you help. I didn’t end up needing all the code, the variants array works just fine: if I hold in ctrl+shift+b I can change the build system. I can’t help but think you should be able to put a keybinding element directly in the project file though,
With ST4 (or just ST maybe), there are some new endpoints to the EventListener
class which can actually make this happen.