1package RlwrapFilter;
2
3require 5.006;
4
5use strict;
6use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
7
8sub when_defined($@);
9my $previous_tag = -1;
10my $echo_has_been_handled = 0;
11my $saved_output = "";
12
13
14require Exporter;
15require AutoLoader;
16@ISA = qw(Exporter AutoLoader);
17
18@EXPORT = qw(TAG_INPUT TAG_OUTPUT TAG_HISTORY TAG_COMPLETION TAG_PROMPT TAG_HOTKEY TAG_SIGNAL DEBUG_FILTERING DEBUG_RANDOM_DELAY);
19$VERSION = '0.01';
20
21use Carp;
22
23# constants for every tag we know about
24use constant MAX_TAG                           => 255;
25use constant TAG_INPUT                         => 0;
26use constant TAG_OUTPUT                        => 1;
27use constant TAG_HISTORY                       => 2;
28use constant TAG_COMPLETION                    => 3;
29use constant TAG_PROMPT                        => 4;
30use constant TAG_HOTKEY                        => 5;
31use constant TAG_SIGNAL                        => 6;
32use constant TAG_WHAT_ARE_YOUR_INTERESTS       => 127;
33use constant TAG_IGNORE                        => 251;
34use constant TAG_ADD_TO_COMPLETION_LIST        => 252;
35use constant TAG_REMOVE_FROM_COMPLETION_LIST   => 253;
36use constant TAG_OUTPUT_OUT_OF_BAND            => 254;
37use constant TAG_ERROR                         => 255;
38
39# to bitwise AND with $ENV{RLWRAP_DEBUG}, the value of the rlwrap --debug option:
40use constant DEBUG_FILTERING                   => 16;
41use constant DEBUG_RANDOM_DELAY                => 1024;
42
43use constant REJECT_PROMPT                    => "_THIS_CANNOT_BE_A_PROMPT_";
44
45
46
47# we want to behave differently when running outside rlwrap
48my $we_are_running_under_rlwrap = defined $ENV{RLWRAP_COMMAND_PID};
49
50
51# die() and warn() must communicate via rlwrap, not via STDERR (unless we're running under perl -c)
52unless ($^C){
53  $SIG{__DIE__}  = \&die_with_error_message;
54  $SIG{__WARN__} = \&warn_with_info_message;
55}
56
57# automagically have a setter/getter for every key of %$self
58sub AUTOLOAD {
59  my $self = shift;
60  my $type = ref($self)
61    or croak "$self is not an object";
62
63  my $name = $AUTOLOAD;
64  $name =~ s/.*://;             # strip fully-qualified portion
65
66  unless (exists $self->{$name} ) {
67    croak "There is no `$name' setter/getter in class $type";
68  }
69
70  if (@_) {
71    return $self->{$name} = shift;
72  } else {
73    return $self->{$name};
74  }
75}
76
77# open communication lines with rlwrap (or with the terminal when not running under rlwrap)
78if ($we_are_running_under_rlwrap) {
79
80  open CMD_IN,     ">&" . $ENV{RLWRAP_MASTER_PTY_FD};
81  open CMD_OUT,    "<&" . $ENV{RLWRAP_MASTER_PTY_FD};
82
83  open FILTER_IN,  "<&" . $ENV{RLWRAP_INPUT_PIPE_FD};
84  open FILTER_OUT, ">&" . $ENV{RLWRAP_OUTPUT_PIPE_FD};
85} else {
86  open CMD_IN,     ">&STDOUT";
87  open CMD_OUT,    "<&STDIN";
88
89  open FILTER_IN,  "<&STDIN";
90  open FILTER_OUT,  ">&STDOUT";
91}
92
93
94# create filter object
95sub new {
96  my ($this, %init) = @_;
97  my $class = ref($this) || $this;
98  my $self = {};
99  my @accessors = qw(initialiser help_text input_handler
100		   output_handler prompt_handler echo_handler
101		   message_handler history_handler hotkey_handler completion_handler signal_handler
102		   echo_handler message_handler cloak_and_dagger_verbose
103		   cumulative_output prompts_are_never_empty
104		   minimal_rlwrap_version);
105  foreach my $acc (@accessors) {
106    $self->{$acc} = "";
107  }
108  bless $self, $class;
109  foreach my $key (keys %init) {
110    croak "There is no `$key' attribute in class $class" unless defined $self->{$key};
111    $self -> {$key} = $init{$key};
112    $self -> minimal_rlwrap_version($self->{$key}) if $key eq "minimal_rlwrap_version";
113  }
114  return $self;
115}
116
117# event loop
118sub run {
119    my ($self) = @_;
120
121    if($ENV{RLWRAP_COMMAND_PID} == 0) { # when called as rlwrap -z <filter> (with no command) ..
122      write_message(TAG_OUTPUT_OUT_OF_BAND, $self -> help_text . "\n"); # ... send help text
123    }
124
125    while(1) {
126	my ($tag, $message) = read_message();
127        $message = when_defined $self -> message_handler, "$message", $tag; # ignore return value
128	my $response = $message; # a response that is identical to the message signals: don't do anything
129
130	if ($tag == TAG_INPUT) {
131	  $response = when_defined $self -> input_handler, "$message";
132	} elsif ($tag == TAG_OUTPUT) {
133	  $response = $self -> handle_output($message);
134	} elsif ($tag == TAG_HISTORY) {
135	  $response = when_defined $self -> history_handler, "$message";
136        } elsif ($tag == TAG_HOTKEY and $self -> hotkey_handler) {
137            my @params = split_rlwrap_message($message);
138            my @result = &{$self -> hotkey_handler}(@params);
139            $response = merge_fields(@result);
140	} elsif ($tag == TAG_COMPLETION and $self -> completion_handler) {
141          my ($line, $prefix, @completions) = split_rlwrap_message($message);
142          @completions = &{$self -> completion_handler}($line, $prefix, @completions);
143	  $response = merge_fields($line, $prefix, @completions); # The handler only returns a (revised) list of completions. We add the (original) $line and $prefix
144	} elsif ($tag == TAG_PROMPT) {
145	  if ($message eq REJECT_PROMPT or
146	      ($self -> {prompts_are_never_empty} and $message eq "")) {
147			write_message($tag, REJECT_PROMPT);
148			# don't update <previous_tag> and don't reset <cumulative_input>
149			next;
150                      }
151
152          if ($ENV{RLWRAP_IMPATIENT} and  $self->{cumulative_output} !~ /\n$/) { # cumulative output contains prompt: chop it off!
153            $self->{cumulative_output} =~ s/(?<![^\n])[^\n]*$//                  # s/[^\n]*$// takes way too long on big strings,
154                                                                                 # what is the optimal regex to do this?
155          }
156
157	  $response = when_defined $self -> prompt_handler, "$message";
158	  croak "prompts may not contain newlines!" if $response =~ /\n/;
159        } elsif ($tag == TAG_SIGNAL) {
160	  $response = when_defined($self -> signal_handler, $message);
161        } elsif ($tag == TAG_WHAT_ARE_YOUR_INTERESTS) {
162          $response = $self -> add_interests($message);
163        }
164
165
166        # shouldn't the next "and" be an  "or"? @@@
167	unless (out_of_band($tag) and ($tag == TAG_PROMPT and $response eq REJECT_PROMPT)) {
168          $self -> {previous_tag} = $tag;
169          $self -> {previous_message} = $message;
170        }
171	write_message($tag, $response);
172
173    }
174}
175
176
177# when_defined \&f, x, y, ... returns f(x, y, ...) if f is defined, x otherwise
178sub when_defined($@) {
179  my $maybe_ref_to_sub = shift;
180  local $_ =  $_[0] ; # convenient when using anonymous subs as handlers: $filter -> blah_handler(sub{$_ if /blah/});
181  if ($maybe_ref_to_sub) {
182    if ((my $type  = ref($maybe_ref_to_sub))  ne 'CODE') {
183      croak "improper handler <$maybe_ref_to_sub> of type $type (expected a ref to a sub)";
184    }
185    return &{$maybe_ref_to_sub}(@_);
186  } else {
187    return $_;
188  }
189}
190
191# When the filter starts, it tells rlwrap its interests as a string 'yyny..' (1 + TAG_MAX chars, 1 for each tag)
192# when receiving a message 'nnynn...' the follwoing function changes 'n' to 'y' for those message types that the
193# filter handles,so that at the end of the pipeline the message reflects the interests of all filters in the
194# pipeline
195sub add_interests {
196  my ($self, $message) = @_;
197  my @interested = split //, $message;
198  for (my $tag = 0; $tag < @interested; $tag++) {
199    next if $interested[$tag] eq 'y'; # a preceding filter in the pipeline has already shown interest
200    $interested[$tag] = 'y'
201      if ($tag == TAG_INPUT      and $self -> input_handler)
202      or ($tag == TAG_OUTPUT     and ($self -> output_handler or $self -> echo_handler)) # echo is the first OUTPUT after INPUT
203      or ($tag == TAG_HISTORY    and ($self -> history_handler or $self -> echo_handler)) # to determine which OUTPUT is echo, we need to see INPUT
204      or ($tag == TAG_COMPLETION and $self -> completion_handler)
205      or ($tag == TAG_PROMPT     and $self -> prompt_handler)
206      or ($tag == TAG_HOTKEY     and $self -> hotkey_handler)
207      or ($tag == TAG_SIGNAL     and $self -> signal_handler);
208  }
209  return join '', @interested;
210}
211
212
213sub out_of_band {
214  my($tag) = @_;
215  return $tag > 128;
216}
217
218
219
220
221
222
223# split output in echo and the rest and call the appropriate handlers on them
224sub handle_output {
225  my ($self, $message) = @_;
226  my ($echo, $handled_echo, $nl);
227  if (defined $self -> {previous_tag} and $self -> {previous_tag} == TAG_INPUT) {
228    $self->{cumulative_output} = "";
229    $echo_has_been_handled = 0;
230  }
231
232  if (not $echo_has_been_handled) {
233    if ($message !~ /\n/) {
234      $saved_output .= $message; # save all output until we have one *whole* echo line
235      return "";
236    } else {                    # ... then process it
237      $message = $saved_output . $message;
238      $echo_has_been_handled = 1;
239      $saved_output = "";
240      ($echo, $nl, $message) = ($message =~ /^([^\n\r]*)(\r?\n)?(.*)?/s); #@@@ This doesn't work for multi-line input!
241      $handled_echo = when_defined $self -> echo_handler, "$echo";
242    }
243  }
244  $self->{cumulative_output} .= $message;
245  return $handled_echo . $nl . (when_defined $self -> output_handler, "$message");
246}
247
248
249sub read_until { # read chunks from pty pointed to by $fh until either inactive for $timeout or
250                 # $stoptext is seen at end-of-chunk
251  my ($fh, $stoptext, $timeout) = @_;
252  my ($res);
253  while (1){
254    my $chunk = read_chunk($fh, $timeout);
255    return $res unless $chunk; # got "" back: timeout
256    $res .= $chunk;
257    return $res if $res =~ /$stoptext$/;
258  }
259}
260
261
262# read chunk from pty pointed to by $fh with timeout $timeout
263sub read_chunk {
264  my ($fh, $timeout) = @_;
265  my ($rin, $rout, $chunk);
266  vec($rin, fileno($fh), 1) = 1;
267  my ($nfound, undef) = select($rout=$rin, undef, undef, $timeout);
268  if ($nfound > 0) {
269    my $nread = sysread($fh, $chunk, 256);
270    if ($nread > 0) {
271      return $chunk;
272    }
273  }
274  return "";
275}
276
277
278# keep reading until $count total bytes were read from filehandle $fh
279sub read_patiently {
280  my($fh, $count) = @_;
281  my $already_read = 0;
282  my $result;
283  while($already_read < $count) {
284    my $nread = sysread($fh, $result, $count-$already_read, $already_read);
285    if ($nread == 0) { # rlwrap (or the rlwrapped command) has put down the
286                       # telephone - we're going to die anyway. Don't complain.
287      exit(0);
288    } elsif ($nread < 0) {
289      die_with_errormessage("error reading: $!");
290    }
291    $already_read += $nread;
292  }
293  return $result;
294}
295
296# keep writing until all bytes from $buffer were written to $fh
297sub write_patiently {
298  my($fh, $buffer) = @_;
299  my $already_written = 0;
300  my $count = length($buffer);
301  while($already_written < $count) {
302    my $nwritten = syswrite($fh, $buffer, $count-$already_written, $already_written);
303    if ($nwritten <= 0) {
304      die_with_errormessage("error writing: $!\n");
305    }
306    $already_written += $nwritten;
307  }
308}
309
310
311# read message (tag, length word and contents) from FILTER_IN
312sub read_message {
313  return read_from_stdin() unless $we_are_running_under_rlwrap;
314  my $tag = unpack("C", read_patiently(*FILTER_IN,1));
315  my $length = unpack("L",read_patiently(*FILTER_IN,4));
316  my $message = read_patiently(*FILTER_IN, $length);
317  $message =~ s/\n$//;
318  return ($tag, $message);
319}
320
321
322sub write_message {
323  my($tag, $message) = @_;
324  return write_to_stdout($tag, $message) unless $we_are_running_under_rlwrap;
325
326  $message ||= ""; # allow undefined messages
327
328  write_patiently(*FILTER_OUT, pack("C", $tag));
329  write_patiently(*FILTER_OUT, pack("L", (length $message) + 1));
330  write_patiently(*FILTER_OUT, "$message\n");
331}
332
333sub read_from_stdin {
334  my ($tag, $prompt, $tagname, $message);
335  while (not defined $tag) {
336    print $prompt;
337    ($tagname, $message) = (<STDIN> =~ /(\S+) (.*?)\r?\n/);
338    exit unless $tagname;
339    $message =~ s/\\t/\t/g; # allow TABs to be input as '\t'
340    $message =~ s/\\n/\n/g; # the same for newlines
341    $tag = name2tag(undef, $tagname); # call as function, not method
342    $prompt = "again > ";
343  }
344  return ($tag, $message)
345}
346
347sub write_to_stdout {
348  my($tag, $message) = @_;
349  print tag2name(undef, $tag) . " $message\n";
350}
351
352
353sub add_to_completion_list {
354  my ($self, @words) = @_;
355  write_message(TAG_ADD_TO_COMPLETION_LIST, join(' ', @words));
356}
357
358sub remove_from_completion_list {
359  my ($self, @words) = @_;
360  write_message(TAG_REMOVE_FROM_COMPLETION_LIST, join(' ', @words));
361}
362
363
364sub cwd {
365  my ($self) = @_;
366  my $command_pid = $ENV{RLWRAP_COMMAND_PID};
367  my $pwd = "/proc/$command_pid/cwd";
368  croak  "cannot read commands working directory as $pwd doesn't exist" unless -e $pwd;
369  return (-l $pwd ? readlink ($pwd) : $pwd);
370}
371
372
373
374# have a private chat with the rlwrapped command. This relies very much om the assumption that command stops
375# talking, and only listens, when it has displayed the $prompt
376sub cloak_and_dagger {
377  my ($self, $question, $prompt, $timeout) = @_;
378  $prompt ||= $self -> last('prompt');
379  write_patiently(*CMD_IN, "$question\n");
380  $self -> send_output_oob("cloak_and_dagger question: $question\n") if $self -> {cloak_and_dagger_verbose};
381  my $response = read_until(*CMD_OUT, $prompt, $timeout);
382  $response =~ s/.*?\n//; # chop off echoed question;
383  $response =~ s/$prompt$//; # chop off prompt;
384  $self -> send_output_oob("cloak_and_dagger response: $response\n") if $self -> {cloak_and_dagger_verbose};
385  return $response;
386}
387
388
389# Commands return messages asynchronously and may time out
390# when invoked by multiple `cloak_and_dagger`. You may want to
391# drop their unused output at some later time:
392
393# rlwrap_filter.cloak_and_dagger($command1, $prompt, $timeout)
394# rlwrap_filter.cloak_and_dagger($command2, $prompt, $timeout) ...
395# sleep(1)
396# rlwrap_filter.vacuum_stale_message($prompt,  $timeout)
397
398sub vacuum_stale_message {
399  my ($self, $prompt, $timeout) = @_;
400  return read_until(*CMD_OUT, $prompt, $timeout);
401}
402
403
404
405sub tag2name {
406  my ($self, $tag) = @_;
407  for my $name (qw(TAG_REMOVE_FROM_COMPLETION_LIST TAG_ADD_TO_COMPLETION_LIST TAG_INPUT TAG_PROMPT TAG_COMPLETION
408		   TAG_HOTKEY TAG_SIGNAL TAG_HISTORY TAG_WHAT_ARE_YOUR_INTERESTS  TAG_OUTPUT_OUT_OF_BAND TAG_ERROR  TAG_IGNORE TAG_OUTPUT)) {
409    return $name if (eval "$tag == $name");
410  }
411  croak "unknown tag $tag";
412}
413
414sub name2tag {
415  my ($self, $name ) = @_;
416  my $tag = eval uc $name;
417  #croak "unknown tagname $name " if $@;
418  return $tag;
419}
420
421sub send_output_oob {
422  my ($self, $text) = @_;
423  write_message(TAG_OUTPUT_OUT_OF_BAND, $text);
424}
425
426
427sub  send_ignore_oob {
428  my ($self, $text) = @_;
429  write_message(TAG_IGNORE, $text);
430}
431
432sub tweak_readline_oob {
433  my ($self, $rl_tweak, @args) = @_;
434  my %nargs = (rl_variable_bind => 2,
435               rl_completer_word_break_characters => 1,
436               rl_completer_quote_characters => 1,
437               rl_filename_completion_desired => 1);
438               # the list can be extended in future versions
439
440  die "tweak_readline_oob() called with unknown readline function or variable '$rl_tweak'\n" unless  $nargs{$rl_tweak};
441  die "tweak_readline_oob($rl_tweak,...) should be called with $nargs{$rl_tweak} more args\n" if @args != $nargs{$rl_tweak};
442  $self -> send_ignore_oob("@" . join("::", ($rl_tweak, @args, "\n")));
443}
444
445
446sub die_with_error_message {
447  my ($error_message) = @_;
448  die $error_message if $^S; # make die() within eval do the right thing
449  my $myself = $0;
450  $myself =~ s#^.*/([^.]+)$#$1#;
451  write_message(TAG_ERROR, "$myself: $error_message");
452  sleep 2;
453  exit 1;
454}
455
456
457sub warn_with_info_message {
458  my ($warning) = @_;
459  my $myself = $0;
460  $myself =~ s#^.*/([^.]+)$#$1#;
461  write_message(TAG_OUTPUT_OUT_OF_BAND, "$myself: $warning");
462
463}
464
465sub minimal_rlwrap_version {
466  my ($self, $wanted) = @_;
467  my $found = $ENV{RLWRAP_VERSION} || "0.34";
468  die "This filter requires rlwrap version $wanted or newer!\n"
469    unless !$we_are_running_under_rlwrap or $wanted le $found;
470}
471
472
473sub command_line {
474  my $commandline = $ENV{RLWRAP_COMMAND_LINE};
475  return (wantarray ? split /\s+/, $commandline : $commandline);
476}
477
478sub running_under_rlwrap {
479  return $we_are_running_under_rlwrap;
480}
481
482sub prompt_rejected {
483  my ($self) = @_;
484  $self->minimal_rlwrap_version("0.35");
485  return REJECT_PROMPT;
486}
487
488sub name {
489  my ($name) = ($0 =~ m#([^/]+)$#);
490  $name ||= $0;
491  return $name;
492}
493
494use constant DIGIT_NUMBER => 8; # This has to be the same number as DIGITS_NUMBER  in src/string_utils.c:914
495
496
497sub split_rlwrap_message {
498  my ($message) = @_;
499  my @fields = ();
500
501  while(length($message) != 0){
502    my $lenstr = substr($message, 0, DIGIT_NUMBER, "");
503    my $len = hex($lenstr);
504    my $field = substr($message, 0, $len, "");
505    push(@fields, $field);
506  }
507  return @fields;
508}
509
510sub merge_fields {
511  my (@fields) = @_;
512  my $message = "";
513
514  foreach my $field (@fields) {
515    my $lenstr = sprintf("%0" . DIGIT_NUMBER . "x", length($field));
516    $message = $message . $lenstr . $field;
517  }
518  return $message;
519}
520
521
5221
523
524__END__
525
526
527=head1 NAME
528
529RlwrapFilter - Perl class for B<rlwrap> filters
530
531=head1 SYNOPSIS
532
533  use lib $ENV{RLWRAP_FILTERDIR};
534  use RlwrapFilter;
535
536  $filter = new RlwrapFilter;
537
538  $filter -> output_handler(sub {s/apple/orange/; $_}); # re-write output
539  $filter -> prompt_handler(\&pimp_the_prompt); # change prompt
540  $filter -> history_handler(sub {s/with password \w+/with password ****/; $_}); # keep passwords out of history
541
542  $filter -> run;
543
544=head1 DESCRIPTION
545
546B<rlwrap> (1) (L<https://github.com/hanslub42/rlwrap>) is a tiny
547utility that sits between the user and any console command, in order
548to bestow readline capabilities (line editing, history recall) to
549commands that don't have them.
550
551Since version 0.32, rlwrap can use filters to script almost every
552aspect of rlwrap's interaction with the user: changing the history,
553re-writing output and input, calling a pager or computing completion
554word lists from the current input.
555
556Filters can be combined in a pipeline using the special B<pipeline> filter.
557
558B<RlwrapFilter> makes it very simple to write rlwrap
559filters in perl. A filter only needs to instantiate a RlwrapFilter
560object, change a few of its default handlers and then call its 'run'
561method.
562
563There is also a Python 3 module B<rlwrapfilter.py>, distributed
564together with B<rlwrap>, that provides  more or less the same API as
565its B<perl> counterpart.
566
567=head1 PUBLIC METHODS
568
569=head2 CONSTRUCTOR
570
571=over 4
572
573=item $f = new RlwrapFilter
574
575=item $f = RlwrapFilter -> new(prompt_handler => sub {"Hi! > "}, minimal_rlwrap_version => "0.35", ...)
576
577Return a new RlwrapFilter object.
578
579=back
580
581=head2 SETTING/GETTING HANDLERS
582
583Handlers are user-defined callbacks that specify one or more of an
584RlwrapFilter object's handler methods (handle_input, handle_prompt)
585They get called from the 'run' method in response to a message sent
586from B<rlwrap>.  Messages consist of a tag indicating which handler
587should be called (e.g. TAG_INPUT, TAG_HISTORY) and the message
588text. Usually, a filter overrides only one or at most two methods.
589
590=head2 CALLING CONVENTIONS
591
592In many cases (e.g. TAG_INPUT, TAG_OUTPUT, TAG_PROMPT) the message
593text is a simple string. Their handlers are called with the message
594text (i.e. the un-filtered input, output, prompt) as their only
595argument. For convenience, $_ is set to the same value. They should
596return the re-written message text.
597
598Some handlers (those for TAG_COMPLETION and TAG_HOTKEY) are a little
599more complex: their message text (accessible via $_) is a
600tab-separated list of fields; they get called with multiple arguments
601and are evaluated in list context.
602
603
604The message handlers are called in a fixed cyclic order: prompt,
605completion, history, input, echo, output, prompt, ... etc ad
606infinitum. Rlwrap may always skip a handler when in direct mode; on
607the other hand, completion and output handlers may get called more
608than once in succession. If a handler is left undefined, the result is
609as if the message text were returned unaltered (in fact, B<rlwrap> knows
610when this is the case and won't even bother to send the message)
611
612It is important to note that the filter, and hence all its handlers,
613are bypassed when I<command> is in direct mode, i.e. when it asks for
614single keystrokes (and also, for security reasons, when it doesn't
615echo, e.g. when asking for a password). If you don't want this to happen, use
616B<rlwrap -a> to force B<rlwrap> to remain in readline mode and to
617apply the filter to I<all> of I<command>'s in- and output. This will
618make editors and pagers (which respond to single keystrokes) unusable,
619unless you use rlwrap's B<-N> option (linux only)
620
621
622The getters/setters for the respective handlers are listed below:
623
624=over 4
625
626
627
628=item $handler = $f -> prompt_handler, $f -> prompt_handler(\&handler)
629
630The prompt handler re-writes prompts and gets called when rlwrap
631decides it is time to "cook" the prompt, by default some 40 ms after
632the last output has arrived. Of course, B<rlwrap> cannot read the mind
633of I<command>, so what looks like a prompt to B<rlwrap> may actually
634be the beginning of an output line that took I<command> a little
635longer to formulate. If this is a problem, specify a longer "cooking"
636time with rlwrap's B<-w> option, use the B<prompts_are_never_empty>
637method or "reject" the prompt (cf. the B<prompt_rejected> method)
638
639
640=item $handler = $f -> completion_handler, $f -> completion_handler(\&handler)
641
642The completion handler gets called with three arguments: the entire input
643line, the prefix (partial word to complete), and rlwrap's own completion list.
644It should return a (possibly revised) list of completions.
645As an example, suppose the user has typed "She played for
646AE<lt>TABE<gt>". The handler will be called like this:
647
648     myhandler("She played for A", "A", "Arsenal", "Arendal", "Anderlecht")
649
650it could then return a list of stronger clubs: ("Ajax", "AZ67",  "Arnhem")
651
652=item $handler = $f -> history_handler, $f -> history_handler(\&handler)
653
654Every input line is submitted to this handler, the return value is put
655in rlwrap's history. Returning an empty or undefined value will keep
656the input line out of the history.
657
658=item $handler = $f -> hotkey_handler, $f -> hotkey_handler(\&handler)
659
660If, while editing an input line, the user presses a key that is bound
661to "rlwrap_hotkey" in B<.inputrc>, the handler is called with five
662arguments: the hotkey, the prefix (i.e.  the part of the current input
663line before the cursor), the remaining part of the input line
664(postfix), the history as one string ("line 1\nline 2\n...line N", and
665the history position. It has to return a similar list, except that the
666first element will be printed in the "echo area" if it is changed from
667its original value.
668
669
670B<Example:> if the current input line is  "pea soup" (with the cursor on the
671space), and the user presses CTRL+P, which happens to be bound to "rlwrap-hotkey"
672in B<.inputrc>, the handler is called like this:
673
674    my_handler("\0x10", "pea", " soup", "tomato soup\nasparagus..", 12) # 16 = CTRL-P
675
676If you prefer peanut soup, the handler should return
677
678    ("Mmmm!", "peanut", " soup", "asparagus..", 11)
679
680after which the input line will be "peanut soup" (with the cursor
681again on the space), the echo area will display "Mmmm!", and any reference
682to inferior soups will have been purged from the history.
683
684If the returned input line ends with a newline B<rlwrap> will immediately
685accept the result.
686
687
688
689=item $handler = $f -> input_handler, $f -> input_handler(\&handler)
690
691Every input line (which may consist of multiple \n-separated lines,
692when using bracketed paste) is submitted to this handler, The
693handler's return value is written to I<command>'s pty
694(pseudo-terminal).
695
696=item $handler = $f -> echo_handler, $f -> echo_handler(\&handler)
697
698The first line of output that is read back from I<command>'s pty is
699the echo'ed input line. If your input handler alters the input line,
700it is the altered input that will be echo'ed back. If you don't want
701to confuse the user, use an echo handler that returns your original
702input.
703
704If you use rlwrap in --multi-line mode, additional echo lines will
705have to be handled by the output handler
706
707
708=item $handler = $f -> output_handler, $f -> output_handler(\&handler)
709
710All I<command> output after the echo line is submitted to the output
711handler (including newlines). This handler may get called many times in succession,
712dependent on the size of I<command>'s write() calls, and the whims of
713your system's scheduler. Therefore your handler should be prepared to
714rewrite your output in "chunks", where you even don't have the
715guarantee that the chunks contain entire unbroken lines.
716
717If you want to handle I<command>'s entire output in one go, you can
718specify an output handler that returns an empty string, and then use
719$filter -> cumulative_output in your prompt handler to send the
720re-written output "out-of-band" just before the prompt:
721
722    $filter -> output_handler(sub {""});
723
724    $filter -> prompt_handler(
725                  sub{ $filter -> send_output_oob(mysub($filter -> cumulative_output));
726                       "Hi there > "
727                     });
728
729
730Note that when rlwrap is run in --multi-line mode the echo handler will still
731only handle the first echo line.  The remainder will generally
732be echoed back preceded by a continuation prompt; it is up to the
733output handler what to do with it.
734
735
736=item $handler = $f -> signal_handler, $f -> signal_handler(\&handler)
737
738As B<rlwrap> is transparent to signals, signals get passed on to I<command>.
739This handler gets called (as handler($signo)) for signals SIGHUP, SIGINT,
740SIGQUIT, SIGTERM, SIGCONT, SIGUSR1, SIGUSR2, and SIGWINCH, before the signal is delivered.
741It receives (and should return) $signo as a string. The returned signal is delivered to
742I<command>; return "0" to ignore the signal altogether. Output can be written out-of-band (to B<rlwrap>) or
743cloak_and_dagger (to I<command>, see below)
744
745
746=item $handler = $f -> message_handler, $f -> message_handler(\&handler)
747
748This handler gets called (as handler($message, $tag)) for every
749incoming message, and every tag (including out-of-band tags), before
750all other handlers. Its return value is ignored, but it may be useful
751for logging and debugging purposes. The $tag is an integer that can be
752converted to a tag name by the 'tag2name' method
753
754
755=back
756
757
758
759=head2 OTHER METHODS
760
761=over 4
762
763=item $f -> help_text("Usage...")
764
765Set the help text for this filter. It will be displayed by rlwrap -z
766<filter>. The second line of the help text is used by C<rlwrap -z listing>;
767it should be a short description of what the filter does.
768
769=item $f -> minimal_rlwrap_version("x.yy")
770
771Die unless rlwrap is version x.yy or newer
772
773=item $dir = $f -> cwd
774
775return the name of I<command>'s current working directory. This uses
776the /proc filesystem, and may only work on newer linux systems (on
777older linux and on Solaris, it will return something like
778"/proc/12345/cwd", useful to find the contents of I<command>'s working
779directory, but not its name)
780
781
782=item $text = $f -> cumulative_output
783
784return the current cumulative output. All (untreated) output gets
785appended to the cumulative output after the output_handler has been
786called. The cumulative output starts with a fresh slate with every
787OUTPUT message that directly follows an INPUT message (ignoring out-of-band
788messages and rejected prompts)
789
790When necessary (i.e. when B<rlwrap> is in "impatient mode") the prompt
791is removed from $filter->cumulative_output by the time the prompt
792handler is called.
793
794=item $tag = $f -> previous_tag
795
796The tag of the last preceding in-band message. A tag is an integer between 0 and
797255, its name can be found with the following method:
798
799=item  $name = $f -> tag2name($tag)
800
801Convert the tag (an integer) to its name (e.g. "TAG_PROMPT")
802
803=item  $name = $f -> name2tag($tag)
804
805Convert a valid tag name like "TAG_PROMPT" to a tag (an integer)
806
807=item $f -> send_output_oob($text)
808
809Make rlwrap display C<$text>. C<$text> is sent "out-of-band" :
810B<rlwrap> will not see it until just  after it has sent the next
811message to the filter
812
813=item $f -> send_ignore_oob($text)
814
815Send an out-of-band TAG_IGNORE message to rlwrap. B<rlwrap> will silently
816discard it, but it can be useful when debugging filters
817
818
819=item $f -> tweak_readline_oob($readline_function, @parameters)
820
821Send a specially formatted out-of-band message in order to tweak
822readline (i.e. to make B<rlwrap> call a B<readline> function or set a
823B<readline> variable). See the GNU B<Readline> documentation for details.
824
825At this moment, the following tweaks are recognised:
826
827    $filter -> tweak_readline_oob("rl_variable_bind", $rl_variable_name, $value);
828    # ... only for bindable readline variables like those in .inputrc
829    $filter -> tweak_readline_oob("rl_completer_word_break_characters", $chars);
830    $filter -> tweak_readline_oob("rl_completer_quote_characters", $chars);
831    $filter -> tweak_readline_oob("rl_filename_completion_desired", "0" or "1");
832
833The parameters should not contain "::" (two consecutive colons). This method can be called at any
834moment, even before $filter -> run
835
836=item $f -> add_to_completion_list(@words)
837
838=item $f -> remove_from_completion_list(@words)
839
840Permanently add or remove the words in C<@words> to/from rlwrap's completion list.
841
842=item $f -> cloak_and_dagger($question, $prompt, $timeout);
843
844Send C<$question> to I<command>'s input and read back everything that
845comes back until C<$prompt> is seen at "end-of-chunk", or no new
846chunks arrive for $timeout seconds, whichever comes first.  Return the
847response (without the final C<$prompt>).  B<rlwrap> remains completely
848unaware of this conversation.
849
850=item $f -> cloak_and_dagger_verbose($verbosity)
851
852If $verbosity evaluates to a true value, make rlwrap print all
853questions sent to I<command> by the C<cloak_and_dagger> method, and
854I<command>'s responses. By default, $verbosity = 0; setting it to
8551 will mess up the screen but greatly facilitate the (otherwise rather tricky) use of
856C<cloak_and_dagger>
857
858=item $self -> prompt_rejected
859
860A special text ("_THIS_CANNOT_BE_A_PROMPT_") to be returned by a
861prompt handler to "reject" the prompt. This will make rlwrap skip
862cooking the prompt.  $self->previous_tag and $self->cumulative_output
863will not be touched.
864
865=item $text = $f -> prompts_are_never_empty($val)
866
867If $val evaluates to a true value, automatically reject empty prompts.
868
869=item $f -> command_line
870
871In scalar context: the rlwrapped command and its arguments as a string ("command -v blah")
872in list context: the same as a list ("command", "-v", "blah")
873
874=item $f -> running_under_rlwrap
875
876Whether the filter is run by B<rlwrap>, or directly from the command line
877
878=item $f -> run
879
880Start an event loop that reads rlwrap's messages from the input pipe,
881calls the appropriate handlers and writes the result to the output
882pipe.  This method never returns.
883
884=back
885
886
887
888=head1 LOW LEVEL PROTOCOL
889
890B<rlwrap> communicates with a filter through messages consisting of a tag
891byte (TAG_OUTPUT, TAG_PROMPT etc. - to inform the filter of what is
892being sent), an unsigned 32-bit integer containing the length of the
893message, the message text and an extra newline. For every message
894sent, rlwrap expects, and waits for an answer message with the same
895tag. Sending back a different (in-band) tag is an error and instantly
896kills rlwrap, though filters may precede their answer message with
897"out-of-band" messages to output text (TAG_OUTPUT_OUT_OF_BAND), report
898errors (TAG_ERROR), and to manipulate the completion word list
899(TAG_ADD_TO_COMPLETION_LIST and TAG_REMOVE_FROM_COMPLETION_LIST)
900Out-of-band messages are not serviced by B<rlwrap> until right after
901it has sent the next in-band message - the communication with the
902filter is synchronous and driven by rlwrap.
903
904Messages are received and sent via two pipes. STDIN, STDOUT and STDERR
905are still connected to the user's terminal, and you can read and write
906them directly, though this may mess up the screen and confuse the user
907unless you are careful. A filter can even communicate with the
908rlwrapped command behind rlwrap's back (cf the cloak_and_dagger()
909method)
910
911The protocol uses the following tags (tags E<gt> 128 are out-of-band)
912
913 TAG_INPUT       0
914 TAG_OUTPUT      1
915 TAG_HISTORY     2
916 TAG_COMPLETION  3
917 TAG_PROMPT      4
918 TAG_HOTKEY      5
919 TAG_SIGNAL      6
920
921 TAG_WHAT_ARE_YOUR_INTERESTS     127
922
923 TAG_IGNORE                      251
924 TAG_ADD_TO_COMPLETION_LIST      252
925 TAG_REMOVE_FROM_COMPLETION_LIST 253
926 TAG_OUTPUT_OUT_OF_BAND          254
927 TAG_ERROR                       255
928
929
930To see how this works, you can eavesdrop on the protocol
931using the B<logger> filter.
932
933The constants TAG_INPUT, ... are exported by the RlwrapFilter.pm module.
934
935TAG_WHAT_ARE_YOUR_INTERESTS is only ever used internally, to prevent the exchange of messages that
936won't be handled by the filter anyway. It will be seen by the general message handler, and therefore show
937up (exactly once, at program start) in the output of e.g. the B<logger> filter.
938
939=head1 SIGNALS
940
941As STDIN is still connected to the users teminal, one might expect the filter
942to receive SIGINT, SIGTERM, SIGTSTP directly from the terminal driver if
943the user presses CTRL-C, CTRL-Z etc Normally, we don't want this - it
944would confuse rlwrap, and the user (who thinks she is talking straight
945to the rlwapped command) probably meant those signals to be sent to
946the command itself. For this reason the filter starts with all signals blocked.
947
948Filters that interact with the users terminal (e.g. to run a pager)
949should unblock signals like SIGTERM, SIGWINCH.
950
951=head1 FILTER LIFETIME
952
953The filter is started by B<rlwrap> after I<command>, and stays alive
954as long as B<rlwrap> runs. Filter methods are immediately usable. When
955I<command> exits, the filter stays around for a little longer in order
956to process I<command>'s last words. As calling the cwd and
957cloak_and_dagger methods at that time will make the filter die with an
958error, it may be advisable to wrap those calls in eval{}
959
960If a filter calls die() it will send an (out-of-band) TAG_ERROR
961message to rlwrap before exiting. rlwrap will then report the message
962and exit (just after its next in-band message - out-of-band messages
963are not always processed immediately)
964
965die() within an eval() sets $@ as usual.
966
967=head1 ENVIRONMENT
968
969Before calling a filter, B<rlwrap> sets the following environment variables:
970
971    RLWRAP_FILTERDIR      directory where RlwrapFilter.pm and most filters live (set by rlwrap, can be
972                          overridden by the user before calling rlwrap)
973
974    PATH	          rlwrap automatically adds $RLWRAP_FILTERDIR to the front of filter's PATH
975
976    RLWRAP_VERSION        rlwrap version (e.g. "0.35")
977
978    RLWRAP_COMMAND_PID    process ID of the rlwrapped command
979
980    RLWRAP_COMMAND_LINE   command line of the rlwrapped command
981
982    RLWRAP_IMPATIENT      whether rlwrap is in "impatient mode" (cf rlwrap (1)). In impatient mode,
983                          the candidate prompt is filtered through the output handler (and displayed before
984                          being overwritten by the cooked prompt).
985
986    RLWRAP_INPUT_PIPE_FD  File descriptor of input pipe. For internal use only
987
988    RLWRAP_OUTPUT_PIPE_FD File descriptor of output pipe. For internal use only
989
990    RLWRAP_MASTER_PTY_FD  File descriptor of command's pty.
991
992    RLWRAP_BREAK_CHARS    The characters rlwrap considers word-breaking (cf. the --break-chars option in rlwrap (1))
993
994    RLWRAP_DEBUG          The value of the --debug (-d) option given to rlwrap
995
996=head1 DEBUGGING FILTERS
997
998While RlwrapFilter.pm makes it easy to write simple filters, debugging
999them can be a problem. A couple of useful tricks:
1000
1001=head2 LOGGING
1002
1003When running a filter, the in- and outgoing messages can be logged by
1004the B<logger> filter, using a pipeline:
1005
1006  rlwrap -z 'pipeline logger incoming : my_filter : logger outgoing' command
1007
1008
1009=head2 RUNNING WITHOUT B<rlwrap>
1010
1011When called by rlwrap, filters get their input from
1012$RLWRAP_INPUT_PIPE_FD and write their output to
1013$RLWRAP_OUTPUT_PIPE_FD, and expect and write messages consisting of a
1014tag byte, a 32-bit length and the message proper. This is not terribly
1015useful when running a filter directly from the command line (outside
1016rlwrap), even if we set the RLWRAP_*_FD ourselves.
1017
1018Therefore, when run directly from the command line, a filter expects
1019input messages on its standard input of the form
1020
1021  TAG_PROMPT myprompt >
1022
1023(i.a. a tag name, one space and a message followed by a newline. The
1024message will not contain the final newline) and it will respond in the
1025same way on its standard output. Of course, B<rlwrap> can help with the
1026tedious typing of tag names:
1027
1028  rlwrap -f tagnames filter_to_be_debugged
1029
1030Because B<rlwrap> cannot put TABs and newlines in input lines, filters will
1031convert '\t' and '\n' into TAB and newline when run directly from the command line.
1032
1033=head1 SEE ALSO
1034
1035B<rlwrap> (1), B<readline> (3)
1036