My aim is to:
- Copy emacs-standard and emacs-meta keymaps,
- Activate the copies
- Make changes to the copies
- Restore the emacs-standard and emacs-meta keymaps
I have read that emacs-meta is assigned to the Esc key, \e.
My (failing) attempt is in perl, but working code in any language is welcome.
use v5.30;
use Term::ReadLine;
BEGIN {
import Term::ReadLine::Gnu qw(:keymap_type);
}
my (%seq, %seq_meta, %func, %func_meta);
my $term = Term::ReadLine->new('keymap and custom dispatch test');
# add my own dispatch routine
my $func_name = 'hotkey_dispatch';
my $coderef = sub {};
$term->add_defun($func_name, $coderef);
my $emacs = $term->get_keymap;
say "initial state:";
dump_keyseq("\e"); # Esc
dump_keyseq("\e[A"); # Up arrow
$term->bind_keyseq("\e", $func_name);
$term->bind_keyseq("\e[A", $func_name);
my $emacs_meta = $term->get_keymap_by_name('emacs-meta');
my $nama = $term->copy_keymap($emacs);
my $nama_meta = $term->copy_keymap($emacs_meta);
$term->set_keymap_name('nama-meta', $nama_meta);
$term->set_keymap_name('nama',$nama);
$term->set_keymap($nama);
$term->generic_bind(ISKMAP,"\e",$nama_meta, $nama);
$term->bind_keyseq("\e", $func_name);
$term->bind_keyseq("\e[A", $func_name);
say "after copying, activating and binding:";
dump_keyseq("\e");
say "this should be 'nama-meta'";
dump_keyseq("\e[A");
say "this should be 'hotkey_dispatch'";
$term->set_keymap($emacs_meta);
$term->set_keymap($emacs);
$term->generic_bind(ISKMAP,"\e",$emacs_meta, $emacs);
say "after attempting restore:";
dump_keyseq("\e");
say "this should be emacs-meta, but only after nama-meta";
dump_keyseq("\e[A");
say "this should be previous-history";
sub dump_keyseq {
my $seq = shift;
my ($data, $type) = $term->function_of_keyseq($seq);
if ($type == ISFUNC) {
say "function: ", $term->get_function_name($data);
} elsif ($type == ISKMAP) {
say "keymap: ", $term->get_keymap_name($data);
} elsif ($type == ISMACR) {
say "macro: $data";
} else {
say "unknown type: $type";
}
}
initial state:
keymap: emacs-meta
function: previous-history
after copying, activating and binding:
keymap: emacs-meta
this should be 'nama-meta'
function: hotkey_dispatch
this should be 'hotkey_dispatch'
after attempting restore:
keymap: emacs-meta
this should be emacs-meta, but only after nama-meta
function: hotkey_dispatch
this should be previous-history
So as you can see, I attempted to copy, activate, modify and restore the default keymaps, however failed being able to correctly activate or restore keymaps. I will appreciate any advice.
It seems like it is not possible to change the keymap for the escape key (or any other key that is already of type ISKMAP, see source code https://git.savannah.gnu.org/cgit/readline.git/tree/bind.c#n472). Also it seems
bind_keyseq()does not have effect ifgeneric_bind()has been called first on the same key in the same keymap. So for these two lines:the second will not have any effect since both happens in the keymap
$nama. But the first line also does not have an effect since the key is escape which cannot be modifed. If you change it to another key like CTRL+M it works fine:Now the first line has an effect, and the second line does not have any effect.