Hi, I am creating a plugin where I want to stop the keypress action. For example, I want to prevent the editor from writing “a” when the key “a” is pressed programatically. Can anyone help?
Block default keypess event programatically
The way you would do this would be to define a key binding in your package that is bound to the key you want to block (in these examples, the unmodified A key), along with a context
that constrains when the key binding is actually active.
For example, you can create a key binding like this:
{
"keys": ["a"],
"command": "noop",
},
Now pressing A by itself will try to execute the noop
command, which doesn’t exist; now it’s impossible to type a lowercase letter a
(although upper case ‘A’ is still possible because that includes a Shift modifier; duplicate the binding with "A"
in place of "a"
to also block upper-case A
).
On the whole this is not a good idea because being able to type is fairly important, so if you do something like this you need a way to still allow an 'a'
to be typed. One way to do that would be to use a context
in the key binding and create an on_query_context
event handler, so that the binding is only active in specific situations where you want to block the key.
{
"keys": ["a"],
"command": "noop",
"context": [
{ "key": "block_a_key", "operator": "equal", "operand": true },
],
},
import sublime
import sublime_plugin
class SampleEventListener(sublime_plugin.EventListener):
def on_query_context(self, view, key, operator, operand, match_all):
if key == "block_a_key":
lhs = view.settings().get("block_a")
rhs = bool(operand)
else:
return None
if operator == sublime.OP_EQUAL:
return lhs == rhs
elif operator == sublime.OP_NOT_EQUAL:
return lhs != rhs
return None
In this example, the key binding is only active when the current view
has a setting that specifically says to block the A key from being pressed; otherwise it operates as per normal. You can put whatever detection logic you need in the context
code so that your binding is only active when you want it to be (i.e. when you want to block the key).
Another option would be to make your key binding unconditional as in the first example, but instead of invoking a command that doesn’t exist you invoke your own command that either does nothing or replicates the default logic.
{
"keys": ["a"],
"command": "example",
},
import sublime
import sublime_plugin
class ExampleCommand(sublime_plugin.TextCommand):
def run(self, edit):
if self.view.settings().get("block_a", False) == False:
self.view.run_command("insert", {"characters": "a"})
In this case, pressing an unmodified A key will always execute the command example
, which can determine if it should be inserting the character or doing nothing (or taking some other action instead, which is generally why you want to do something like this in the first place).
Generally speaking you probably want to use a context
for something like this to stop the binding from being considered except where it should be. For example, if you are writing something for distribution through package control, your package will likely be rejected if it has bindings that override defaults without providing a context
.