I am using multiple keymaps. I copy the
default 'emacs' keymap, rename it 'nama',
select keymap 'nama' and apply custom bindings.
git:master ~/build/nama/src $ perl test-readline-keymap2
emacs keymap address: Keymap=SCALAR(0x555bc647a150)
keymap name: emacs
nama keymap address: Keymap=SCALAR(0x555bc6440258)
keymap name: nama
rebinding arrow keys
prompt>Special key: Left, escape sequence: \e[D, decimal: 27 91 68 , hex: 1B 5B 44
Special key: Right, escape sequence: \e[C, decimal: 27 91 67 , hex: 1B 5B 43
got:
prompt>emacs
got: emacs
setting keymap: emacs
name: emacs, address: Keymap=SCALAR(0x555bc6340908)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# I expect the same memory address as emacs above
should be normal arrow keys
prompt>Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
^^^^^^^^^^^^^^^
# I expect emacs keybindings
emacs
Special key: Down, escape sequence: \e[B, decimal: 27 91 66 , hex: 1B 5B 42
emacs
Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
emacs
Special key: Down, escape sequence: \e[B, decimal: 27 91 66 , hex: 1B 5B 42
emacs
got:
prompt>nama
got: nama
setting keymap: nama
name: nama, address: Keymap=SCALAR(0x555bc6498b28)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# I expect same address as nama above.
should be magic arrow keys
prompt>Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
nama
Special key: Down, escape sequence: \e[B, decimal: 27 91 66 , hex: 1B 5B 42
nama
Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
nama
Special key: Down, escape sequence: \e[B, decimal: 27 91 66 , hex: 1B 5B 42
nama
got:
prompt>emacs
got: emacs
setting keymap: emacs
name: emacs, address: Keymap=SCALAR(0x555bc6340908)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# different address again
# try setting emacs keymap by eval:
should be normal arrow keys
prompt>eval $term->set_keymap($term->get_keymap_by_name('emacs'))
got: eval $term->set_keymap($term->get_keymap_by_name('emacs'))
eval'ing
prompt>Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
^^^^^^^^^^^^^^^
# still getting custom bindings
eval $term->set_keymap($term->get_keymap_by_name('emacs'))
Special key: Down, escape sequence: \e[B, decimal: 27 91 66 , hex: 1B 5B 42
eval $term->set_keymap($term->get_keymap_by_name('emacs'))
Special key: Up, escape sequence: \e[A, decimal: 27 91 65 , hex: 1B 5B 41
eval $term->set_keymap($term->get_keymap_by_name('emacs'))
Code:
use v5.30;
use Term::ReadLine;
my $term = Term::ReadLine->new('keyboard code and custom dispatch test');
my $emacs = $term->get_keymap;
say "emacs keymap address: $emacs";
my $name = $term->get_keymap_name($emacs);
say "keymap name: $name";
my $nama = $term->copy_keymap($emacs);
$term->set_keymap_name('nama',$nama);
$term->set_keymap($nama);
$name = $term->get_keymap_name($term->get_keymap);
say "nama keymap address: $nama";
say "keymap name: $name";
say "rebinding arrow keys";
my %escape_code; # Insert -> \e[2~
my %keyname; # \e[2~ -> Insert
read_esc_codes();
my $func_name = 'hotkey_dispatch';
my $coderef = \&hotkey_dispatch;
$term->add_defun($func_name, $coderef);
while ( my ($keyname,$seq) = each %escape_code) {
$term->bind_keyseq($seq, $func_name);
}
sub hotkey_dispatch {
my ($seq, $decimal, $hex) = string_to_escape_code($term->Attribs->{executing_keyseq});
my $name = $keyname{$seq};
say "Special key: $name, escape sequence: $seq, decimal: $decimal, hex: $hex";
say
}
sub string_to_escape_code {
my ($string) = @_;
my $esc = '';
my $decimal = '';
my $hex = '';
for my $char (split //, $string) {
my $ord = ord($char);
# It seems that readline intercepts control characters
# so don't try to convert them.
$char = '\e' if $ord == 27;
$decimal .= "$ord ";
$esc .= $char;
$hex .= sprintf("%02X ", $ord);
}
$esc, $decimal, $hex;
}
sub read_esc_codes {
%escape_code = qw(
Escape \\e
Insert \\e[2~
Delete \\e[3~
Home \\e[1~
End \\e[4~
PageUp \\e[5~
PageDown \\e[6~
Up \\e[A
Left \\e[D
Down \\e[B
Right \\e[C
F1 \\eOP
F2 \\eOQ
F3 \\eOR
F4 \\eOS
F5 \\e[15~
F6 \\e[17~
F7 \\e[18~
F8 \\e[19~
F9 \\e[20~
F10 \\e[21~
F11 \\e[23~
F12 \\e[24~
Keypad/ \\eOo
Keypad* \\eOj
Keypad- \\eOm
Keypad+ \\eOk
Keypad7 \\eOw
Keypad8 \\eOx
Keypad9 \\eOy
Keypad4 \\eOt
Keypad5 \\eOu
Keypad6 \\eOv
Keypad1 \\eOq
Keypad2 \\eOr
Keypad3 \\eOs
Keypad0 \\eOp
Keypad. \\eOn
KeypadEnter \\eOM
);
%keyname = ( reverse %escape_code );
}
while ( defined ($_ = $term->readline('prompt>')) ) {
say "got: $_";
if (/^eval/) {
say "eval'ing";
say eval($_);
next
}
if (/nama|emacs/){
say "setting keymap: $_" ;
set_keymap($_);
}
}
sub set_keymap {
my $name = shift;
my $keymap = $term->get_keymap_by_name($name);
$term->set_keymap($keymap);
$keymap = $term->get_keymap;
$name = $term->get_keymap_name($keymap);
say "name: $name, address: $keymap";
say "should be normal arrow keys" if $name =~ /emacs/;
say "should be magic arrow keys" if $name =~ /nama/;
}
__END__