Sublime Forum

Project specific shortcut key

#1

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.

0 Likes

#2

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 :-

  1. 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.

  1. 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 :slight_smile:

2 Likes

#3

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,

0 Likes

#4

With ST4 (or just ST maybe), there are some new endpoints to the EventListener class which can actually make this happen.

0 Likes