db2c 0.0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/man/db2c.1.ronn CHANGED
@@ -3,7 +3,7 @@ db2c(1) - A DB2 console with with history and autocomplete support, and few othe
3
3
 
4
4
  ## SYNOPSIS
5
5
 
6
- `db2c` <[options]>
6
+ `db2c` [<options>] [dbname]
7
7
 
8
8
  ## DESCRIPTION && EXAMPLES
9
9
 
@@ -27,32 +27,61 @@ DB2 console mode does not support readline and autocomplete, this is a wrapper f
27
27
  db2(testdb) => select * from xyz.tab[double-tab]
28
28
  </pre>
29
29
 
30
- * **You can pipe**:
31
- <pre>
32
- db2(testdb) => select * from large.table | grep -v something
33
- db2(testdb) => select * from large.table | less
34
- </pre>
35
-
36
30
  * For example, if a command outputs long lines, **less -S** is your friend:
37
31
  <pre>
38
32
  db2(testdb) => select * from table.with.many.columns | less -S
39
33
  (you can scorll horizontally with left/right arrows)
40
34
  </pre>
41
35
 
42
- * You can use _some psql-like_ commands
36
+ * **You can edit last statement or use the editor to write a new multiline statement**:
37
+ <pre>
38
+ db2(testdb) => edit
39
+ db2(testdb) => emacs
40
+ </pre>
41
+
42
+ * **Any !command will be sent to the shell as is**:
43
+ <pre>
44
+ db2(testdb) => !clear
45
+ </pre>
46
+
47
+ * You can use _some_ common shell commands directly:
48
+ <pre>
49
+ db2(testdb) => ls ~
50
+ db2(testdb) => less ~/somefile
51
+ db2(testdb) => top
52
+ db2(testdb) => irb
53
+ </pre>
54
+
55
+ * You can use _some psql-like_ meta commands
43
56
  <pre>
44
- db2(testdb) => **\d schema.table**
45
- == describe table schema.table
46
57
  db2(testdb) => **\h**
47
58
  == To see this help from within the console
59
+ db2(testdb) => **\l**
60
+ == list database directory
61
+ db2(testdb) => **\lt [all|schema]**
62
+ == list tables for all or one schema using db2 list command
63
+ db2(testdb) => **\l[t|v|a|s] [schema]**
64
+ == list tables|views|aliases|summary-tables for all or one schema using syscat.tables
65
+ db2(testdb) => **\d schema.table**
66
+ == describe table schema.table
48
67
  db2(testdb) => **\q**
49
68
  </pre>
50
69
 
70
+ * **You can pipe**:
71
+ <pre>
72
+ db2(testdb) => \dv | grep -v SYS
73
+ db2(testdb) => select * from large.table | less
74
+ </pre>
75
+
76
+
51
77
  ## OPTIONS
52
78
 
53
79
  * `-h`, `--help`, `--man`:
54
80
  Displays this help page.
55
81
 
82
+ * `-t`:
83
+ Commands will be executed when you enter a terminating semicolon (;)
84
+
56
85
  * `--debug`:
57
86
  Displays annoying messages.
58
87
 
@@ -0,0 +1,816 @@
1
+ package RlwrapFilter;
2
+
3
+ use strict;
4
+ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
5
+
6
+ sub when_defined($@);
7
+ my $previous_tag = -1;
8
+ my $last_cumulative_output = "";
9
+
10
+ require Exporter;
11
+ require AutoLoader;
12
+ @ISA = qw(Exporter AutoLoader);
13
+
14
+ @EXPORT = qw(TAG_INPUT TAG_OUTPUT TAG_HISTORY TAG_COMPLETION TAG_PROMPT);
15
+ $VERSION = '0.01';
16
+
17
+ use Carp;
18
+
19
+ # constants for every tag we know about
20
+ use constant TAG_INPUT => 0;
21
+ use constant TAG_OUTPUT => 1;
22
+ use constant TAG_HISTORY => 2;
23
+ use constant TAG_COMPLETION => 3;
24
+ use constant TAG_PROMPT => 4;
25
+ use constant TAG_IGNORE => 251;
26
+ use constant TAG_ADD_TO_COMPLETION_LIST => 252;
27
+ use constant TAG_REMOVE_FROM_COMPLETION_LIST => 253;
28
+ use constant TAG_OUTPUT_OUT_OF_BAND => 254;
29
+ use constant TAG_ERROR => 255;
30
+
31
+ use constant REJECT_PROMPT => "_THIS_CANNOT_BE_A_PROMPT_";
32
+
33
+ # we want to behave differently when running outside rlwrap
34
+ my $we_are_running_under_rlwrap = defined $ENV{RLWRAP_COMMAND_PID};
35
+
36
+
37
+ # die() and warn() must communicate via rlwrap, not via STDERR
38
+ $SIG{__DIE__} = \&die_with_error_message;
39
+ $SIG{__WARN__} = \&warn_with_info_message;
40
+
41
+ # automagically have a setter/getter for every key of %$self
42
+ sub AUTOLOAD {
43
+ my $self = shift;
44
+ my $type = ref($self)
45
+ or croak "$self is not an object";
46
+
47
+ my $name = $AUTOLOAD;
48
+ $name =~ s/.*://; # strip fully-qualified portion
49
+
50
+ unless (exists $self->{$name} ) {
51
+ croak "There is no `$name' setter/getter in class $type";
52
+ }
53
+
54
+ if (@_) {
55
+ return $self->{$name} = shift;
56
+ } else {
57
+ return $self->{$name};
58
+ }
59
+ }
60
+
61
+ # open communication lines with rlwrap (or with the terminal when not running under rlwrap)
62
+ if ($we_are_running_under_rlwrap) {
63
+
64
+ open CMD_IN, ">&" . $ENV{RLWRAP_MASTER_PTY_FD};
65
+ open CMD_OUT, "<&" . $ENV{RLWRAP_MASTER_PTY_FD};
66
+
67
+ open FILTER_IN, "<&" . $ENV{RLWRAP_INPUT_PIPE_FD};
68
+ open FILTER_OUT, ">&" . $ENV{RLWRAP_OUTPUT_PIPE_FD};
69
+ } else {
70
+ open CMD_IN, ">&STDOUT";
71
+ open CMD_OUT, "<&STDIN";
72
+
73
+ open FILTER_IN, "<&STDIN";
74
+ open FILTER_OUT, ">&STDOUT";
75
+ }
76
+
77
+
78
+ # create filter object
79
+ sub new {
80
+ my ($this, %init) = @_;
81
+ my $class = ref($this) || $this;
82
+ my $self = {};
83
+ my @accessors = qw(initialiser help_text input_handler
84
+ output_handler prompt_handler echo_handler
85
+ message_handler history_handler completion_handler
86
+ echo_handler message_handler cloak_and_dagger_verbose
87
+ cumulative_output prompts_are_never_empty
88
+ minimal_rlwrap_version);
89
+ foreach my $acc (@accessors) {
90
+ $self->{$acc} = "";
91
+ }
92
+ bless $self, $class;
93
+ foreach my $key (keys %init) {
94
+ croak "There is no `$key' attribute in class $class" unless defined $self->{$key};
95
+ $self -> {$key} = $init{$key};
96
+ $self -> minimal_rlwrap_version($self->{$key}) if $key eq "minimal_rlwrap_version";
97
+ }
98
+ return $self;
99
+ }
100
+
101
+
102
+
103
+ # event loop
104
+ sub run {
105
+ my ($self) = @_;
106
+
107
+ if($ENV{RLWRAP_COMMAND_PID} == 0) { # when called as rlwrap -z <filter> (with no command) ..
108
+ write_message(TAG_OUTPUT_OUT_OF_BAND, $self -> help_text . "\n"); # ... send help text
109
+ }
110
+
111
+ while(1) {
112
+ my ($tag, $message) = read_message();
113
+
114
+ $message = when_defined $self -> message_handler, "$message", $tag; # ignore return value
115
+ my $response;
116
+
117
+ if ($tag == TAG_INPUT) {
118
+ $response = when_defined $self -> input_handler, "$message";
119
+ } elsif ($tag == TAG_OUTPUT) {
120
+ $response = $self -> handle_output($message);
121
+ } elsif ($tag == TAG_HISTORY) {
122
+ $response = when_defined $self -> history_handler, "$message";
123
+ } elsif ($tag == TAG_COMPLETION) {
124
+ my ($line, $prefix, $completions, @completions);
125
+ if ($self -> completion_handler) {
126
+ $message =~ s/[ ]+$//; # eat final space
127
+ ($line, $prefix, $completions) = split /\t/, $message;
128
+ @completions = split / /, $completions;
129
+ @completions = &{$self -> completion_handler}($line, $prefix, @completions);
130
+ $response = "$line\t$prefix\t". (join ' ', @completions) . " ";
131
+ } else {
132
+ $response = $message;
133
+ }
134
+ } elsif ($tag == TAG_PROMPT) {
135
+ if ($message eq REJECT_PROMPT or
136
+ ($self -> {prompts_are_never_empty} and $message eq "")) {
137
+ write_message($tag,REJECT_PROMPT);
138
+ # don't update <previous_tag> and don't reset <cumulative_input>
139
+ next;
140
+ }
141
+ $self->{cumulative_output} =~ s/(?<![^\n])[^\n]*$// # s/[^\n]*$// takes way too long on big strings, what is the optimal regex to do this?
142
+ if $ENV{RLWRAP_IMPATIENT}; # chop off prompt from cumulative_output
143
+
144
+ $response = when_defined $self -> prompt_handler, "$message";
145
+ croak "prompts may not contain newlines!" if $response =~ /\n/;
146
+ } else {
147
+ $response = $message; # No error message, compatible with future rlwrap
148
+ # versions that may define new tag types
149
+ }
150
+
151
+ unless (out_of_band($tag) and ($tag == TAG_PROMPT and $response eq REJECT_PROMPT)) {
152
+ $self -> {previous_tag} = $tag;
153
+ $self -> {previous_message} = $message;
154
+ }
155
+ write_message($tag, $response);
156
+
157
+ }
158
+ }
159
+
160
+
161
+ # when_defined \&f, x, y, ... returns f(x, y, ...) if f is defined, x otherwise
162
+ sub when_defined($@) {
163
+ my $maybe_ref_to_sub = shift;
164
+ local $_ = $_[0] ; # convenient when using anonymous subs as handlers: $filter -> blah_handler(sub{$_ if /blah/});
165
+ if ($maybe_ref_to_sub) {
166
+ if ((my $type = ref($maybe_ref_to_sub)) ne 'CODE') {
167
+ croak "improper handler <$maybe_ref_to_sub> of type $type (expected a ref to a sub)";
168
+ }
169
+ return &{$maybe_ref_to_sub}(@_);
170
+ } else {
171
+ return $_;
172
+ }
173
+ }
174
+
175
+ sub out_of_band {
176
+ my($tag) = @_;
177
+ return $tag > 128;
178
+ }
179
+
180
+ # split output in echo and the rest and call the appropriate handlers on them
181
+ sub handle_output {
182
+ my ($self, $message) = @_;
183
+ my ($echo, $handled_echo, $sep);
184
+ if (defined $self -> {previous_tag} and $self -> {previous_tag} == TAG_INPUT) {
185
+ $self->{cumulative_output} = "";
186
+ ($echo, $sep, $message) = ($message =~ /^([^\n\r]*)(\r?\n)?(.*)?/s); #@@@ This doesn't work for multi-line input!
187
+ $handled_echo = when_defined $self -> echo_handler, "$echo";
188
+ }
189
+ $self->{cumulative_output} .= $message;
190
+ return $handled_echo . $sep .(when_defined $self -> output_handler, "$message");
191
+ }
192
+
193
+ sub read_until { # read chunks from pty pointed to by $fh until either inactive for $timeout or
194
+ # $stoptext is seen at end-of-chunk
195
+ my ($fh, $stoptext, $timeout) = @_;
196
+ my ($res);
197
+ while (1){
198
+ my $chunk = read_chunk($fh, $timeout);
199
+ return $res unless $chunk; # got "" back: timeout
200
+ $res .= $chunk;
201
+ return $res if $res =~ /$stoptext$/;
202
+ }
203
+ }
204
+
205
+
206
+ # read chunk from pty pointed to by $fh with timeout $timeout
207
+ sub read_chunk {
208
+ my ($fh, $timeout) = @_;
209
+ my ($rin, $rout, $chunk);
210
+ vec($rin, fileno($fh), 1) = 1;
211
+ my ($nfound, undef) = select($rout=$rin, undef, undef, $timeout);
212
+ if ($nfound > 0) {
213
+ my $nread = sysread($fh, $chunk, 256);
214
+ if ($nread > 0) {
215
+ return $chunk;
216
+ }
217
+ }
218
+ return "";
219
+ }
220
+
221
+
222
+ # keep reading until $count total bytes were read from filehandle $fh
223
+ sub read_patiently {
224
+ my($fh, $count) = @_;
225
+ my $already_read = 0;
226
+ my $result;
227
+ while($already_read < $count) {
228
+ my $nread = sysread($fh, $result, $count-$already_read, $already_read);
229
+ if ($nread == 0) {
230
+ exit 0;
231
+ } elsif ($nread < 0) {
232
+ die_with_errormessage("error reading: $!");
233
+ }
234
+ $already_read += $nread;
235
+ }
236
+ return $result;
237
+ }
238
+
239
+ # keep writing until all bytes from $buffer were written to $fh
240
+ sub write_patiently {
241
+ my($fh, $buffer) = @_;
242
+ my $already_written = 0;
243
+ my $count = length($buffer);
244
+ while($already_written < $count) {
245
+ my $nwritten = syswrite($fh, $buffer, $count-$already_written, $already_written);
246
+ if ($nwritten <= 0) {
247
+ die_with_errormessage("error writing: $!");
248
+ }
249
+ $already_written += $nwritten;
250
+ }
251
+ }
252
+
253
+
254
+ # read message (tag, length word and contents) from FILTER_IN
255
+ sub read_message {
256
+ return read_from_stdin() unless $we_are_running_under_rlwrap;
257
+
258
+ my $tag = unpack("C", read_patiently(*FILTER_IN,1));
259
+ my $length = unpack("L",read_patiently(*FILTER_IN,4));
260
+ my $message = read_patiently(*FILTER_IN, $length);
261
+ $message =~ s/\n$//;
262
+ return ($tag, $message);
263
+ }
264
+
265
+
266
+ sub write_message {
267
+ my($tag, $message) = @_;
268
+ return write_to_stdout($tag, $message) unless $we_are_running_under_rlwrap;
269
+
270
+ $message ||= ""; # allow undefined messages
271
+
272
+ write_patiently(*FILTER_OUT, pack("C", $tag));
273
+ write_patiently(*FILTER_OUT, pack("L", (length $message) + 1));
274
+ write_patiently(*FILTER_OUT, "$message\n");
275
+ }
276
+
277
+ sub read_from_stdin {
278
+ my ($tag, $prompt, $tagname, $message);
279
+ while (not defined $tag) {
280
+ print $prompt;
281
+ ($tagname, $message) = (<STDIN> =~ /(\S+) (.*?)\r?\n/);
282
+ exit unless $tagname;
283
+ $tag = name2tag(undef, $tagname); # call as function, not method
284
+ $prompt = "again > ";
285
+ }
286
+ return ($tag, $message)
287
+ }
288
+
289
+ sub write_to_stdout {
290
+ my($tag, $message) = @_;
291
+ print tag2name(undef, $tag) . " $message\n";
292
+ }
293
+
294
+
295
+ sub add_to_completion_list {
296
+ my ($self, @words) = @_;
297
+ write_message(TAG_ADD_TO_COMPLETION_LIST, join(' ', @words));
298
+ }
299
+
300
+ sub remove_from_completion_list {
301
+ my ($self, @words) = @_;
302
+ write_message(TAG_REMOVE_FROM_COMPLETION_LIST, join(' ', @words));
303
+ }
304
+
305
+
306
+ sub cwd {
307
+ my ($self) = @_;
308
+ my $command_pid = $ENV{RLWRAP_COMMAND_PID};
309
+ my $pwd = "/proc/$command_pid/cwd";
310
+ croak "cannot read commands working directory as $pwd doesn't exist" unless -e $pwd;
311
+ return (-l $pwd ? readlink ($pwd) : $pwd);
312
+ }
313
+
314
+
315
+
316
+ # have a private chat with the rlwrapped command. This relies very much om the assumption that command stops
317
+ # talking, and only listens, when it has displayed the $prompt
318
+ sub cloak_and_dagger {
319
+ my ($self, $question, $prompt, $timeout) = @_;
320
+ $prompt ||= $self -> last('prompt');
321
+ write_patiently(*CMD_IN, "$question\n");
322
+ $self -> send_output_oob("cloak_and_dagger question: $question\n") if $self -> {cloak_and_dagger_verbose};
323
+ my $response = read_until(*CMD_OUT, $prompt, $timeout);
324
+ $response =~ s/.*?\n//; # chop off echoed question;
325
+ $response =~ s/$prompt$//; # chop off prompt;
326
+ $self -> send_output_oob("cloak_and_dagger response: $response\n") if $self -> {cloak_and_dagger_verbose};
327
+ return $response;
328
+ }
329
+
330
+
331
+
332
+ sub tag2name {
333
+ my ($self, $tag) = @_;
334
+ for my $name (qw(TAG_REMOVE_FROM_COMPLETION_LIST TAG_ADD_TO_COMPLETION_LIST TAG_INPUT TAG_PROMPT TAG_COMPLETION
335
+ TAG_HISTORY TAG_OUTPUT_OUT_OF_BAND TAG_ERROR TAG_IGNORE TAG_OUTPUT)) {
336
+ return $name if (eval "$tag == $name");
337
+ }
338
+ croak "unknown tag $tag";
339
+ }
340
+
341
+ sub name2tag {
342
+ my ($self, $name ) = @_;
343
+ my $tag = eval uc $name;
344
+ #croak "unknown tagname $name " if $@;
345
+ return $tag;
346
+ }
347
+
348
+ sub send_output_oob {
349
+ my ($self, $text) = @_;
350
+ write_message(TAG_OUTPUT_OUT_OF_BAND, $text);
351
+ }
352
+
353
+
354
+
355
+ sub send_ignore_oob {
356
+ my ($self, $text) = @_;
357
+ write_message(TAG_IGNORE, $text);
358
+ }
359
+
360
+ sub die_with_error_message {
361
+ die $@ if $^S; # make die() within eval do the right thing
362
+ my ($error_message) = @_;
363
+ my $myself = $0;
364
+ $myself =~ s#^.*/([^.]+)$#$1#;
365
+ write_message(TAG_ERROR, "$myself: $error_message");
366
+ sleep 2;
367
+ exit 1;
368
+ }
369
+
370
+
371
+ sub warn_with_info_message {
372
+ my ($warning) = @_;
373
+ my $myself = $0;
374
+ $myself =~ s#^.*/([^.]+)$#$1#;
375
+ write_message(TAG_OUTPUT_OUT_OF_BAND, "$myself: $warning");
376
+
377
+ }
378
+
379
+ sub minimal_rlwrap_version {
380
+ my ($self, $wanted) = @_;
381
+ my $found = $ENV{RLWRAP_VERSION} || "0.34";
382
+ die "This filter requires rlwrap version $wanted or newer!\n"
383
+ unless !$we_are_running_under_rlwrap or $wanted le $found;
384
+ }
385
+
386
+
387
+ sub command_line {
388
+ my $commandline = $ENV{RLWRAP_COMMAND_LINE};
389
+ return (wantarray ? split /\s+/, $commandline : $commandline);
390
+ }
391
+
392
+ sub running_under_rlwrap {
393
+ return $we_are_running_under_rlwrap;
394
+ }
395
+
396
+ sub prompt_rejected {
397
+ my ($self) = @_;
398
+ $self->minimal_rlwrap_version("0.35");
399
+ return REJECT_PROMPT;
400
+ }
401
+
402
+ sub name {
403
+ my ($name) = ($0 =~ m#([^/]+)$#);
404
+ $name ||= $0;
405
+ return $name;
406
+ }
407
+
408
+
409
+ 1
410
+
411
+ __END__
412
+
413
+
414
+ =head1 NAME
415
+
416
+ RlwrapFilter - Perl class for B<rlwrap> filters
417
+
418
+ =head1 SYNOPSIS
419
+
420
+ use lib $ENV{RLWRAP_FILTERDIR};
421
+ use RlwrapFilter;
422
+
423
+ $filter = new RlwrapFilter;
424
+
425
+ $filter -> output_handler(sub {s/apple/orange/; $_}); # re-write output
426
+ $filter -> prompt_handler(\&pimp_the_prompt); # change prompt
427
+ $filter -> history_handler(sub {s/with password \w+/with password ****/; $_}); # keep passwords out of history
428
+
429
+ $filter -> run;
430
+
431
+ =head1 DESCRIPTION
432
+
433
+ B<rlwrap> (1) (L<http://utopia.knoware.nl/~hlub/uck/rlwrap>) is a tiny
434
+ utility that sits between the user and any console command, in order
435
+ to bestow readline capabilities (line editing, history recall) to
436
+ commands that don't have them.
437
+
438
+ Since version 0.32, rlwrap can use filters to script almost every
439
+ aspect of rlwrap's interaction with the user: changing the history,
440
+ re-writing output and input, calling a pager or computing completion
441
+ word lists from the current input.
442
+
443
+ B<RlwrapFilter> makes it very simple to write rlwrap
444
+ filters in perl. A filter only needs to instantiate a RlwrapFilter
445
+ object, change a few of its default handlers and then call its 'run'
446
+ method.
447
+
448
+ =head1 PUBLIC METHODS
449
+
450
+ =head2 CONSTRUCTOR
451
+
452
+ =over 4
453
+
454
+ =item $f = new RlwrapFilter
455
+
456
+ =item $f = RlwrapFilter -> new(prompt_handler => sub {"Hi! > "}, minimal_rlwrap_version => "0.35", ...)
457
+
458
+ Return a new RlwrapFilter object.
459
+
460
+ =back
461
+
462
+ =head2 SETTING/GETTING HANDLERS
463
+
464
+ Handlers are user-defined callbacks that get called from the
465
+ 'run' method with a message (i.e. the un-filtered input,
466
+ output, prompt) as their first argument. For convenience, $_ is set to the same
467
+ value. They should return the re-written message text. They get called
468
+ in a fixed cyclic order: prompt, completion, history, input, echo,
469
+ output, prompt, ... etc ad infinitum. Rlwrap may always skip a handler when in direct mode,
470
+ on the other hand, completion and output handlers may get called more
471
+ than once in succession. If a handler is left undefined, the result is
472
+ as if the message text were returned unaltered.
473
+
474
+ It is important to note that the filter, and hence all its handlers,
475
+ are bypassed when I<command> is in direct mode, i.e. when it asks for
476
+ single keystrokes (and also, for security reasons, when it doesn't
477
+ echo, e.g. when asking for a password). If you don't want this to happen, use
478
+ B<rlwrap -a> to force B<rlwrap> to remain in readline mode and to
479
+ apply the filter to I<all> of I<command>'s in- and output. This will
480
+ make editors and pagers (which respond to single keystrokes) unusable,
481
+ unless you use rlwrap's B<-N> option (linux only)
482
+
483
+
484
+ The getters/setters for the respective handlers are listed below:
485
+
486
+ =over 4
487
+
488
+
489
+
490
+ =item $handler = $f -> prompt_handler, $f -> prompt_handler(\&handler)
491
+
492
+ The prompt handler re-writes prompts and gets called when rlwrap
493
+ decides it is time to "cook" the prompt, by default some 40 ms after
494
+ the last output has arrived. Of course, B<rlwrap> cannot read the mind
495
+ of I<command>, so what looks like a prompt to B<rlwrap> may actually
496
+ be the beginning of an output line that took I<command> a little
497
+ longer to formulate. If this is a problem, specify a longer "cooking"
498
+ time with rlwrap's B<-w> option, use the B<prompts_are_never_empty>
499
+ method or "reject" the prompt (cf. the B<prompt_rejected> method)
500
+
501
+
502
+ =item $handler = $f -> completion_handler, $f -> completion_handler(\&handler)
503
+
504
+ The completion handler gets called with the the entire input line, the
505
+ prefix (partial word to complete), and rlwrap's own completion list as
506
+ arguments. It should return a (possibly revised) list of completions. As
507
+ an example, suppose the user has typed "She played for
508
+ AE<lt>TABE<gt>". The handler will be called like this:
509
+
510
+ myhandler("She played for A", "A", "Arsenal", "Arendal", "Anderlecht")
511
+
512
+ it could then return a list of stronger clubs: ("Ajax", "AZ67", "Arnhem")
513
+
514
+ =item $handler = $f -> history_handler, $f -> history_handler(\&handler)
515
+
516
+ Every input line is submitted to this handler, the return value is put
517
+ in rlwrap's history. Returning an empty or undefined value will keep
518
+ the input line out of the history.
519
+
520
+ =item $handler = $f -> input_handler, $f -> input_handler(\&handler)
521
+
522
+ Every input line is submitted to this handler, The handler's return
523
+ value is written to I<command>'s pty (pseudo-terminal).
524
+
525
+ =item $handler = $f -> echo_handler, $f -> echo_handler(\&handler)
526
+
527
+ The first line of output that is read back from I<command>'s pty is
528
+ the echo'ed input line. If your input handler alters the input line,
529
+ it is the altered input that will be echo'ed back. If you don't want
530
+ to confuse the user, use an echo handler that returns your original
531
+ input.
532
+
533
+ If you use rlwrap in --multi-line mode, additional echo lines will
534
+ have to be handled by the output handler
535
+
536
+
537
+ =item $handler = $f -> output_handler, $f -> output_handler(\&handler)
538
+
539
+ All I<command> output after the echo line is submitted to the output
540
+ handler (including newlines). This handler may get called many times in succession,
541
+ dependent on the size of I<command>'s write() calls, and the whims of
542
+ your system's scheduler. Therefore your handler should be prepared to
543
+ rewrite your output in "chunks", where you even don't have the
544
+ guarantee that the chunks contain entire unbroken lines.
545
+
546
+ If you want to handle I<command>'s entire output in one go, you can
547
+ specify an output handler that returns an empty string, and then use
548
+ $filter -> cumulative_output in your prompt handler to send the
549
+ re-written output "out-of-band" just before the prompt:
550
+
551
+ $filter -> output_handler(sub {""});
552
+
553
+ $filter -> prompt_handler(
554
+ sub{ $filter -> send_output_oob(mysub($filter -> cumulative_output));
555
+ "Hi there > "
556
+ });
557
+
558
+
559
+ Note that when rlwrap is run in --multi-line mode the echo handler will still
560
+ only handle the first echo line. The remainder will generally
561
+ be echoed back preceded by a continuation prompt; it is up to the
562
+ output handler what to do with it.
563
+
564
+
565
+ =item $handler = $f -> message_handler, $f -> message_handler(\&handler)
566
+
567
+ This handler gets called (as handler($message, $tag)) for every
568
+ incoming message, and every tag (including out-of-band tags), before
569
+ all other handlers. Its return value is ignored, but it may be useful
570
+ for logging and debugging purposes. The $tag is an integer that can be
571
+ converted to a tag name by the 'tag2name' method
572
+
573
+ =back
574
+
575
+ =head2 OTHER METHODS
576
+
577
+ =over 4
578
+
579
+ =item $f -> help_text("Usage...")
580
+
581
+ Set the help text for this filter. It will be displayed by rlwrap -z
582
+ <filter>. The second line of the help text is used by C<rlwrap -z listing>;
583
+ it should be a short description of what the filter does.
584
+
585
+ =item $f -> minimal_rlwrap_version("x.yy")
586
+
587
+ Die unless rlwrap is version x.yy or newer
588
+
589
+ =item $dir = $f -> cwd
590
+
591
+ return the name of I<command>'s current working directory. This uses
592
+ the /proc filesystem, and may only work on newer linux systems (on
593
+ older linux and on Solaris, it will return something like
594
+ "/proc/12345/cwd", useful to find the contents of I<command>'s working
595
+ directory, but not its name)
596
+
597
+
598
+ =item $text = $f -> cumulative_output
599
+
600
+ return the current cumulative output. All (untreated) output gets
601
+ appended to the cumulative output after the output_handler has been
602
+ called. The cumulative output starts with a fresh slate with every
603
+ OUTPUT message that directly follows an INPUT message (ignoring out-of-band
604
+ messages and rejected prompts)
605
+
606
+ When necessary (i.e. when B<rlwrap> is in "impatient mode") the prompt
607
+ is removed from $filter->cumulative_output by the time the prompt
608
+ handler is called.
609
+
610
+ =item $tag = $f -> previous_tag
611
+
612
+ The tag of the last preceding in-band message. A tag is an integer between 0 and
613
+ 255, its name can be found with the following method:
614
+
615
+ =item $name = $f -> tag2name($tag)
616
+
617
+ Convert the tag (an integer) to its name (e.g. "TAG_PROMPT")
618
+
619
+ =item $name = $f -> name2tag($tag)
620
+
621
+ Convert a valid tag name like "TAG_PROMPT" to a tag (an integer)
622
+
623
+ =item $f -> send_output_oob($text)
624
+
625
+ Make rlwrap display C<$text>. C<$text> is sent "out-of-band":
626
+ B<rlwrap> will not see it until just after it has sent the next
627
+ message to the filter
628
+
629
+ =item $f -> send_ignore_oob($text)
630
+
631
+ Send an out-of-band TAG_IGNORE message to rlwrap. B<rlwrap> will silently
632
+ discard it, but it can be useful when debugging filters
633
+
634
+ =item $f -> add_to_completion_list(@words)
635
+
636
+ =item $f -> remove_from_completion_list(@words)
637
+
638
+ Permanently add or remove the words in C<@words> to/from rlwrap's completion list.
639
+
640
+ =item $f -> cloak_and_dagger($question, $prompt, $timeout);
641
+
642
+ Send C<$question> to I<command>'s input and read back everything that
643
+ comes back until C<$prompt> is seen at "end-of-chunk", or no new
644
+ chunks arrive for $timeout seconds, whichever comes first. Return the
645
+ response (without the final C<$prompt>). B<rlwrap> remains completely
646
+ unaware of this conversation.
647
+
648
+ =item $f -> cloak_and_dagger_verbose($verbosity)
649
+
650
+ If $verbosity evaluates to a true value, make rlwrap print all
651
+ questions sent to I<command> by the C<cloak_and_dagger> method, and
652
+ I<command>'s responses. By default, $verbosity = 0; setting it to
653
+ 1 will mess up the screen but greatly facilitate the (otherwise rather tricky) use of
654
+ C<cloak_and_dagger>
655
+
656
+ =item $self -> prompt_rejected
657
+
658
+ A special text ("_THIS_CANNOT_BE_A_PROMPT_") to be returned by a
659
+ prompt handler to "reject" the prompt. This will make rlwrap skip
660
+ cooking the prompt. $self->previous_tag and $self->cumulative_output
661
+ will not be touched.
662
+
663
+ =item $text = $f -> prompts_are_never_empty($val)
664
+
665
+ If $val evaluates to a true value, automatically reject empty prompts.
666
+
667
+ =item $f -> command_line
668
+
669
+ In scalar context: the rlwrapped command and its arguments as a string ("command -v blah")
670
+ in list context: the same as a list ("command", "-v", "blah")
671
+
672
+ =item $f -> running_under_rlwrap
673
+
674
+ Whether the filter is run by B<rlwrap>, or directly from the command line
675
+
676
+ =item $f -> run
677
+
678
+ Start an event loop that reads rlwrap's messages from the input pipe,
679
+ calls the appropriate handlers and writes the result to the output
680
+ pipe. This method never returns.
681
+
682
+ =back
683
+
684
+
685
+
686
+ =head1 LOW LEVEL PROTOCOL
687
+
688
+ B<rlwrap> communicates with a filter through messages consisting of a tag
689
+ byte (TAG_OUTPUT, TAG_PROMPT etc. - to inform the filter of what is
690
+ being sent), an unsigned 32-bit integer containing the length of the
691
+ message, the message text and an extra newline. For every message
692
+ sent, rlwrap expects, and waits for an answer message with the same
693
+ tag. Sending back a different (in-band) tag is an error and instantly
694
+ kills rlwrap, though filters may precede their answer message with
695
+ "out-of-band" messages to output text (TAG_OUTPUT_OUT_OF_BAND), report
696
+ errors (TAG_ERROR), and to manipulate the completion word list
697
+ (TAG_ADD_TO_COMPLETION_LIST and TAG_REMOVE_FROM_COMPLETION_LIST)
698
+ Out-of-band messages are not serviced by B<rlwrap> until right after
699
+ it has sent the next in-band message - the communication with the
700
+ filter is synchronous and driven by rlwrap.
701
+
702
+ Messages are received and sent via two pipes. STDIN, STDOUT and STDERR
703
+ are still connected to the user's terminal, and you can read and write
704
+ them directly, though this may mess up the screen and confuse the user
705
+ unless you are careful. A filter can even communicate with the
706
+ rlwrapped command behind rlwrap's back (cf the cloak_and_dagger()
707
+ method)
708
+
709
+ The protocol uses the following tags (tags E<gt> 128 are out-of-band)
710
+
711
+ TAG_INPUT 0
712
+ TAG_OUTPUT 1
713
+ TAG_HISTORY 2
714
+ TAG_COMPLETION 3
715
+ TAG_PROMPT 4
716
+
717
+ TAG_IGNORE 251
718
+ TAG_ADD_TO_COMPLETION_LIST 252
719
+ TAG_REMOVE_FROM_COMPLETION_LIST 253
720
+ TAG_OUTPUT_OUT_OF_BAND 254
721
+ TAG_ERROR 255
722
+
723
+
724
+ To see how this works, you can eavesdrop on the protocol
725
+ using the 'logger' filter.
726
+
727
+ The constants TAG_INPUT, ... are exported by the RlwrapFilter.pm module.
728
+
729
+ =head1 SIGNALS
730
+
731
+ As STDIN is still connected to the users teminal, one might expect the filter
732
+ to receive SIGINT, SIGTERM, SIGTSTP directly from the terminal driver if
733
+ the user presses CTRL-C, CTRL-Z etc Normally, we don't want this - it
734
+ would confuse rlwrap, and the user (who thinks she is talking straight
735
+ to the rlwapped command) probably meant those signals to be sent to
736
+ the command itself. For this reason the filter starts with all signals blocked.
737
+
738
+ Filters that interact with the users terminal (e.g. to run a pager)
739
+ should unblock signals like SIGTERM, SIGWINCH.
740
+
741
+ =head1 FILTER LIFETIME
742
+
743
+ The filter is started by B<rlwrap> after I<command>, and stays alive
744
+ as long as B<rlwrap> runs. Filter methods are immediately usable. When
745
+ I<command> exits, the filter stays around for a little longer in order
746
+ to process I<command>'s last words. As calling the cwd and
747
+ cloak_and_dagger methods at that time will make the filter die with an
748
+ error, it may be advisable to wrap those calls in eval{}
749
+
750
+ If a filter calls die() it will send an (out-of-band) TAG_ERROR
751
+ message to rlwrap before exiting. rlwrap will then report the message
752
+ and exit (just after its next in-band message - out-of-band messages
753
+ are not always processed immediately)
754
+
755
+ die() within an eval() sets $@ as usual.
756
+
757
+ =head1 ENVIRONMENT
758
+
759
+ Before calling a filter, B<rlwrap> sets the following environment variables:
760
+
761
+ RLWRAP_FILTERDIR directory where RlwrapFilter.pm and most filters live (set by B<rlwrap>, can be
762
+ overridden by the user before calling rlwrap)
763
+
764
+ PATH rlwrap automatically adds $RLWRAP_FILTERDIR to the front of filter's PATH
765
+
766
+ RLWRAP_VERSION rlwrap version (e.g. "0.35")
767
+
768
+ RLWRAP_COMMAND_PID process ID of the rlwrapped command
769
+
770
+ RLWRAP_COMMAND_LINE command line of the rlwrapped command
771
+
772
+ RLWRAP_IMPATIENT whether rlwrap is in "impatient mode" (cf B<rlwrap (1)>). In impatient mode,
773
+ the candidate prompt is filtered through the output handler (and displayed before
774
+ being overwritten by the cooked prompt).
775
+
776
+ RLWRAP_INPUT_PIPE_FD File descriptor of input pipe. For internal use only
777
+
778
+ RLWRAP_OUTPUT_PIPE_FD File descriptor of output pipe. For internal use only
779
+
780
+ RLWRAP_MASTER_PTY_FD File descriptor of I<command>'s pty.
781
+
782
+
783
+ =head1 DEBUGGING FILTERS
784
+
785
+ While RlwrapFilter.pm makes it easy to write simple filters, debugging
786
+ them can be a problem. A couple of useful tricks:
787
+
788
+ =head2 LOGGING
789
+
790
+ When running a filter, the in- and outgoing messages can be logged by
791
+ the B<logger> filter, using a pipeline:
792
+
793
+ rlwrap -z 'pipeline logger incoming : my_filter : logger outgoing' command
794
+
795
+
796
+ =head2 RUNNING WITHOUT B<rlwrap>
797
+
798
+ When called by rlwrap, filters get their input from
799
+ $RLWRAP_INPUT_PIPE_FD and write their output to
800
+ $RLWRAP_OUTPUT_PIPE_FD, and expect and write messages consisting of a
801
+ tag byte, a 32-bit length and the message proper. This is not terribly
802
+ useful when running a filter directly from the command line (outside
803
+ rlwrap), even if we set the RLWRAP_*_FD ourselves.
804
+
805
+ Therfore, when run directly from the command line, a filter expects
806
+ input messages on its standard input of the form
807
+
808
+ TAG_PROMPT >
809
+
810
+ (i.a. a tag name, one space and a message) and it will respond in the
811
+ same way on its standard output
812
+
813
+
814
+ =head1 SEE ALSO
815
+
816
+ B<rlwrap> (1), B<readline> (3)