File: EscapePrefix.pm

package info (click to toggle)
libtickit-app-plugin-escapeprefix-perl 0.02-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 116 kB
  • sloc: perl: 157; makefile: 2
file content (134 lines) | stat: -r--r--r-- 3,194 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#
#  (C) Paul Evans, 2020 -- leonerd@leonerd.org.uk

package Tickit::App::Plugin::EscapePrefix;

use strict;
use warnings;

our $VERSION = '0.02';

use Tickit 0.64 qw( MOD_ALT );
use Tickit::Term qw( BIND_FIRST );

=head1 NAME

C<Tickit::App::Plugin::EscapePrefix> - C<Tickit> application plugin for Escape-prefixed shortcut keys

=head1 SYNOPSIS

   use Tickit;
   use Tickit::App::Plugin::EscapePrefix;

   my $tickit = Tickit->new;

   Tickit::App::Plugin::EscapePrefix->apply( $tickit );

   ...

   $tickit->run;

=head1 DESCRIPTION

This package applies code to a L<Tickit> instance to let it handle
C<< <Escape > >>-prefixed shortcut keys, by converting them into the
equivalent C<< <M-...> >> modified keys instead.

Once applied using the L</apply> method, the plugin will consume any plain
C<< <Escape> >> keys typed at the terminal. If another key arrives soon
afterwards, this key will be consumed and instead a new keypress event emitted
that adds the "meta" modifier to it. For example, typing C<< <Escape> <a> >>
will instead emit the modified key C<< <M-a> >> to the application. If no
subsequent key arrives after a timeout of 3 seconds then the modification will
not apply.

While the plugin is still pending anothey keypress to modify, a small
indicator window will appear in the bottom left of the display, showing
C<ESC-> in a reverse-video style, to remind the user the keypress is pending.

=cut

=head1 METHODS

=cut

=head2 apply

   Tickit::App::Plugin::EscapePrefix->apply( $tickit )

Applies the plugin code to the given toplevel L<Tickit> instance.

=cut

sub apply
{
   my $pkg = shift;
   my ( $t ) = @_;

   my $esc_held;
   my $esc_indicator_window = $t->rootwin->make_float( 0, 0, 1, 4 );
   $esc_indicator_window->hide;
   $esc_indicator_window->pen->chattr( rv => 1 );
   $esc_indicator_window->bind_event( expose => sub {
      my ( $win, undef, $info ) = @_;
      $info->rb->text_at( 0, 0, "ESC-" );
   } );

   my $timer_id;

   $t->term->bind_event( key => BIND_FIRST, sub {
      my ( $term, $ev, $info ) = @_;

      if( $esc_held ) {
         $esc_held = 0;
         $esc_indicator_window->hide;
         $t->cancel_timer( $timer_id ) if defined $timer_id;
         undef $timer_id;

         $term->emit_key(
            type => "key",
            str  => "M-" . $info->str,
            mod  => $info->mod | MOD_ALT,
         );

         return 1;
      }

      if( $info->type eq "key" and $info->str eq "Escape" ) {
         $esc_held = 1;
         $esc_indicator_window->reposition( $t->rootwin->lines - 1, 0 );
         $esc_indicator_window->show;

         $t->cancel_timer( $timer_id ) if defined $timer_id;
         $timer_id = $t->timer( after => 3, sub {
            $esc_held = 0;
            $esc_indicator_window->hide;
            undef $timer_id;
         } );

         return 1;
      }

      return 0;
   } );
}

=head1 TODO

=over 4

Much configuration - timeout; style, text and position of indicator window

=back

=cut

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;