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