The problem
Usually, in Conkeror, when you want to bind a keystroke to a command or function
in a key map, you would use the define_key
function (see more at
Conkeror Key Bindings). However, when you
have too many key bindings, it will lead to the problem of repetition in your
config code. For example
define_key(default_global_keymap, "A-z", previous_buffer);
define_key(default_global_keymap, "C-j", previous_buffer);
define_key(default_global_keymap, "A-x", next_buffer);
define_key(default_global_keymap, "C-l", next_buffer);
This is extremely annoying since I have to rebind too many keys in Conkeror (the Emacs style keys is inefficient). Luckily, the flexibility of Javascript allows us dynamically define the number of arguments that passed to the function. By using that, you can define your own function for binding the keys to avoid repetition in your init code.
Defining keys function
The idea is to create a function that receive a key map followed by pairs of keystroke and the command/function that bound to it. The function looks like this
function my_define_keys(){
// check if arguments if larger than 1
if(arguments.length > 1){
var args = Array.prototype.slice.call(arguments);
// get the keymap
var keymap = args[0];
// remove the first item (keymap)
args.splice(0, 1);
// the length
var length = 0;
// check the number of elements in arguments
if(args.length % 2 == 0){
length = args.length;
} else {
length = args.length + 1;
// add one more null item to the array
args[length] = null;
}
// loop through the arguments
for(var i = 0; i < length; i+=2){
define_key(keymap, args[i], args[i+1]);
}
}
}
Now, if you want to batch define keys, just pass the keymap as the first
argument, and the rest will be the pairs of keystroke and the command. The
following example demonstrates how to batch define keys for default_global_keymap
.
my_define_keys(default_global_keymap,
"A-z", previous_buffer,
"C-j", previous_buffer,
"A-x", next_buffer,
"C-l", next_buffer,
"O", "find-url-new-buffer",
"C-x C-d", "find-alternate-url",
"A-q", "quit",
"C-tab", "switch-to-recent-buffer",
"C-S-tab", "switch-to-last-buffer",
"C-A-x", switch_to_last_tab,
"0", switch_to_last_tab,
"A-n", "colors-toggle",
"C-R", "show-tab-temporarily",
"w", "tmtxt-close-and-save-current-buffer",
"A-w", "tmtxt-close-and-save-current-buffer",
"A-k", "tmtxt-close-and-save-current-buffer",
"A-W", "tmtxt-open-closed-buffer",
"A-T", "tmtxt-open-closed-buffer",
"A-h", "stop-loading-all-buffers",
"A-r", "reload-all-buffers"
);
You can pass as many key bindings as you want. The argument that follow right after the keystroke is the string representing the interactive command name (which can be activated via M-x) or the name of the interactive function that you want to bind.
This function is very helpful. It eliminates the repetition in my code and makes my code a lot easier to read.
Undefining keys function
Similarly, the function for undefining keys receives the key map as the first argument and followed by a series of keystroke that you wish to unbind from that key map. This is how the function looks like
function my_undefine_keys(){
var args = Array.prototype.slice.call(arguments);
// check if the arguments number is bigger than 1
if(args.length > 1){
var keymap = args[0];
args.splice(0,1);
// loop through the args
for(var i = 0; i < args.length; i++){
undefine_key(keymap, args[i]);
}
}
}
Usage example
my_undefine_keys(content_buffer_normal_keymap, "F", "C-f", "C-b", "C-p", "C-n", "M-v");
Function for defining key aliases
This function behaves much in the same way with the defining keys function.
function my_define_keys_aliases(){
var args = Array.prototype.slice.call(arguments);
// check if the number of arguments is even
var length;
if(args.length % 2 == 0){
length = args.length;
} else {
length = args.length + 1;
args[length] = null;
}
// loop through the args
for(var i = 0; i < length; i+=2){
define_key_alias(args[i], args[i+1]);
}
}
In the following example, C-o
is aliased to escape
, A-v
is aliased to
C-y
and so on.
my_define_keys_aliases("C-o", "escape",
"A-v", "C-y",
"A-c", "M-w",
"C-m", "return",
"M-L", "C-e",
"M-J", "C-a",
"C-J", "C-A-z",
"C-L", "C-A-x",
"C-i", "tab");