The [binding] command.

Introduction

The binding command lets you create and manipulate key bindings (aka keyboard shortcuts) in Alpha.
Bindings are associated with Tcl procs (or Tcl scripts): this is a characteristic they share with menu items which can also be associated with Tcl procs (see the [menuItem] reference file).
A key binding is defined by the following attributes:
A key binding is uniquely determined by these parameters. The code and the modifiers are required parameters. The other parameters are optional. By default, a code is interpreted as a character code. If the tag is empty or unspecified, the binding is global, otherwise it is mode-specific.
The [binding] command establishes a link between a key combo and an action to execute, represented by a Tcl proc.

Synopsis

The formal syntax of the [binding] command is:
binding subcommand ?options?
The possible subcommands are described below. Depending on the subcommand, various options can be additionally specified. Specifying a key combo

The [allowed] subcommand

This subcommand lets you filter the bindings, that is to say allow only certain kinds of bindings to be executed. The filtering is based on the modifier keys. The command lets you specify, based on the modifiers, which bindings should be accepted by the application: only bindings involving these modifiers will be executed. The syntax can take three forms:
    binding allowed
    binding allowed modifiers
    binding allowed all
In the first form, the command returns the modifiers which are currently accepted. The other forms are used to specify the set of modifiers which are allowed. By convention, the returned string can be: The letters c, o, s, z have the same meaning as described in the Specifying a key combo section. The letter e is used to designate bindings which do not have a modifier key (for instance bindings defined for the carriage return).
An empty string means that all the bindings are disabled.
Under normal circumstances, the command returns "szoce" which means that all the bindings are allowed. But, if a modal dialog is displayed, the core suspends all the bindings and the returned value, in that case, would be an empty string.
The third form is a convenience to reenable all the bindings. This command can be useful if all the bindings have been accidentally suspended and the application seems unresponsive. To restore them, just invoke the command binding allowed all.
Note that another technique to restrict some bindings is to specify a context with the -context option of the [binding create] command.

The [create] subcommand

This subcommand creates a new binding or redefines an already existing one. It accepts a few options. The complete syntax is:
    binding create ?option value...? {modifiers key} proc
The command has two required arguments:
Here are the currently supported options: The possible values for the -context option are:
NameValueDescription
None0no context is required
Exists Doc Window1there must exist at least one document window
Active Doc Window2the frontmost window must be a document window
Exists Root Window3there must exist at least one view root window
Active Root Window4the frontmost window must be a view root window
If there is already a binding corresponding to the same key combination, it is overwritten by the new one.
Note also that the [binding allowed] command has precedence over the -context option: the context condition is tested only if the binding's modifiers are allowed.

The [delete] subcommand

This subcommand is used to delete a key binding. The syntax is:
    binding delete ?option value...? {modifiers key}
The possible options are -tag and -prefix: they have the same meaning as the -tag and -prefix options in the [binding create] command.
If the binding does not exist, the command is just ignored.
See the Specifying a key combo section for the format of the {modifiers key} argument.

The [info] subcommand

This subcommand returns information about an existing key binding. The syntax is:
   binding info (command|context|help) ?option value...? {modifiers key}
The third argument indicates which kind of info is desired. It can be one of the following keywords: The possible options are -tag and -prefix: they have the same meaning as the -tag and -prefix options in the [binding create] command.
If the binding does not exist, the command raises an error.
See the Specifying a key combo section for the format of the {modifiers key} argument.

The [list] subcommand

This subcommand returns a list of the currently existing key bindings. The syntax is:
    binding list ?option value...?
One can specify some options to restrict the returned list to bindings satisfying these options. The available options are:
-command, -creator, -key, -modifiers, -prefix, -tag, -virtual.
If the command is invoked without any argument, it returns a list of all the currently defined bindings. This list may be augmented each time a new mode is loaded.
This allows you to specify key codes or modifiers separately. The value of the -key option can be either a numeric value or a character enclosed between single quotes. The value of the -modifiers option is a string made of the c, o, s, z, f, v letters. See the Specifying a key combo section. The -virtual option can be used to list only character code bindings (if the value is 0) or only virtual keycode bindings (if the value is 1).
Each element of the list returned by the [binding list] command is a sublist describing a particular key binding. This sublist contains 6 or 8 elements:
  1. the modifier string (an empty string if there are no modifier specifications)
  2. the key code (decimal value or letter)
  3. the tag (an empty string if the binding is global)
  4. the creator (an empty string if no creator was specified)
  5. the Tcl script attached to the binding
  6. the help string attached to the binding
  7. the modifier string of the prefix (empty if there are no modifier specifications)
  8. the key code of the prefix (decimal value)
The last two elements are present only if the binding is composite, that is to say if it has been defined with a -prefix option.
For instance, if a binding is created like this:
    binding create -creator "abcd" -tag Tcl {cv 112} Tcl::doSomethingProc
the returned sublist will be
    cv 112 Tcl abcd Tcl::doSomethingProc ""
This command can be used to find if there exists a key binding bound to a particular Tcl proc. For instance:
    binding list -command Tcl::doSomethingProc
The [binding info] command with the -creator option can also be useful to identify a collection of bindings. It is useful for packages in order to keep track of the bindings they define. If a collection of bindings have been declared with a -creator option like this
    binding create -creator "ABCD" {modifiers key} proc
it is possible to get the list of all these bindings with the following command:
    binding list -creator "ABCD"
See examples in the Examples section below.
Note that character code bindings corresponding to a character are case insensitive: they are stored internally using the code of the uppercase character even if the definition was invoked using a lowercase character. On output, all the character code bindings corresponding to a printable character are written with this character (uppercase form between single quotes); the other bindings (including virtual key bindings) are represented by the decimal value of the key. So, if a binding has been defined for 'a', the character returned in [binding list] will be 'A'. This is consistent with the way bindings are displayed in menus.

Specifying a key combo

Many subcommands of the [binding] command take a keyboard shortcut argument of the form
{modifiers key}
This argument describes a key combination. It is a two-elements Tcl list: The next paragraphs explain how to specify both of them.
The modifiers are specified as a string made of some of the following letters:
LetterDescription
ccorresponds to the Command key ()
scorresponds to the Shift key ()
ocorresponds to the Option key ()
zcorresponds to the Control key ()
vspecifies whether the main key is a character code or as a virtual key code.
The modifier string must be specified as an empty string if no modifiers are associated with the key combo. For more information about the modifier v, see the Character codes vs. virtual keycodes section below.
There are three ways of specifying the main key: Note that character code bindings are case insensitive. So Command-a and Command-A are identical. If you really want the Shift key to be part of the binding, you must specify the letter s in the modifier string. For instance, the string {cs 65} corresponds to the ⇧⌘A combination, but {c 'A'} is synonym of {c 'a'} and corresponds to the ⌘A combination.

Character codes vs. virtual keycodes

A keyboard equivalent may be either a character code or a virtual keycode. Only one is used by the application at any given time: a virtual keycode binding always has precedence over a character code binding. Note that zero is a valid virtual keycode.

Symbolic key names

Here is the list of the predefined symbolic names which can be used to specify a virtual key binding. These values are case insensitive, so one can use HOME, home, Home indifferently. The following table gives the numeric key codes corresponding to the symbolic names:
NameKeycode
Clear0x75
Delete0x33
Down0x7d
End0x77
Enter0x4c
Esc0x35
F10x7a
F20x78
F30x63
F40x76
F50x60
F60x61
F70x62
F80x64
F90x65
F100x6d
F110x67
F120x6f
F130x69
F140x6b
F150x71
Help0x72
Home0x73
Kpad=0x51
Kpad*0x43
Kpad/0x4b
Kpad+0x45
Kpad-0x4e
Kpad.0x41
Kpad00x52
Kpad10x53
Kpad20x54
Kpad30x55
Kpad40x56
Kpad50x57
Kpad60x58
Kpad70x59
Kpad80x5b
Kpad90x5c
Left0x7b
NumLock0x47
PageDown0x79
PageUp0x74
Return0x24
Right0x7c
Space0x31
Tab0x30
Up0x7e

Composite bindings

The -prefix option can be used in the [binding create] command to define composite bindings. Its value is a two-elements Tcl list of the form {modifiers key} with the same meaning as with the main key argument of the [binding create] command.
For instance, in order to define the binding ⌃⌥B Z (which means, first press ⌃⌥B , then press Z), the instruction is:
    binding create -prefix {oz 'B'} {"" 'Z'} someProc
The binding ⌃⌥B Z will trigger the Tcl proc designated by someProc.
For this mechanism to work, the simple ⌃⌥B binding must also be defined and must be bound to the [prefixBinding] core command like this:
    binding create {oz 'B'} prefixBinding
The [prefixBinding] core command takes care of waiting for the second part of the binding to be entered (here the letter Z) and then to execute the code designated by someProc.

Bindings with an infix

There is an even more elaborate kind of composite bindings which involves an infix, like for instance ⌃A 5 ⌥B: here the infix is 5 and means that the action which is bound to the combo ⌃A ⌥B will receive the value 5 as an additional argument which it can interpret in different ways.
The embrace package, for instance, makes use of this technique: the ⌃B S combo encloses the word under the insertion cursor in square brackets. If you type for example ⌃B 3 S, then the group of three preceding words will be enclosed in square brackets.
To create a binding accepting an infix, one must specify the -infix option in the [prefixBinding] command. The value of the -infix option is a regular expression which describes which values are considered an infix: for instance [1-5r] means that the infix could be a digit between 1 and 5 or the letter r. Similarly the regular expression (\d+|[a-c]) allows any number (made of one or more digits) or one of the letters a, b, c.
Here is an example:
    binding create {z 'A'} { prefixBinding -infix {(\d+|r)} }
    binding create -prefix {z 'A'} {"" 'B'} someProc
If the user executes the binding ⌃A, the [prefixBinding] command will be expecting an infix (something matched by the regular expression) hopefully followed later by the letter B. If finally the entered combo is ⌃A 15 B, the proc someProc will be invoked with an additional argument 15. This proc should know how to handle this argument. The infix is not compulsory though: if the user enters something that is not matched by the regular expression, it is assumed that there is no infix, so the user could type ⌃A B as well (in that case, the additional argument will be an empty string).
Important: it is up to the user (and to the developer of packages!) to avoid ambiguities. With the example above, a new binding for the combo ⌃A R would never work because the letter r would be interpreted as an infix and would expect another keydown event to complete the binding.

Examples

Here are a few basic examples which can be executed one by one in the Tcl Shell (⌘Y) in Alpha:
proc bindingActionProc {idx}  {
	alertnote "Command $idx triggered"
}
# Define a few commands
for {set i 1} {$i < 12} {incr i} {
	set cmd$i "test::bindingActionProc $i"
}

# Bindings to letter A (resp opt-cmd-A, ctrl-cmd-A, and ctrl-opt-cmd-A)
binding create -help "do something" {co 65} $cmd1
binding create -help "perform something" {cz 65} $cmd2
binding create -help "something else" {coz 65} $cmd3

# Bindings to letter L
binding create {co 76} $cmd4
binding create -tag Tcl {co 76} $cmd5
binding create -tag Python {co 76} $cmd6
binding create -tag Ruby {co 76} $cmd7

# A virtual keycode binding attached to opt-F5.
# Note that the v modifier could be omitted here.
binding create {ov F5} $cmd8
binding create -tag Tcl {ov F5} $cmd9
binding create -tag Ruby {ov F5} $cmd10

# The Help key
binding create {v Help} $cmd11

# Get a list of all the bindings
binding list

# Get a list of all the bindings associated with letter L
binding list -key 76
# Get a list of all the bindings using opt-cmd
binding list -modifiers "co"
# Get a list of all the bindings defined in Ruby mode
binding list -tag Ruby
# Get a list of all the opt-cmd bindings in Ruby mode
binding list -modifiers "co" -tag Ruby
# Get a list of all the bindings attached to the action contained in 
# the cmd1 variable
binding list -command $cmd1

# Find the command associated with the opt-cmd-L combo in Ruby mode
binding info command -tag Ruby {co 'L'}

# Get the help string associated with a binding
binding info help {co 65}

   # Delete the previous binding
binding delete -tag Ruby {co 76}


Last updated 2021-05-21 14:43:34