disallow eval { goto &foo }
[p5sagit/p5-mst-13.2.git] / lib / Term / ReadLine.pm
CommitLineData
cb31d310 1=head1 NAME
2
7ef5744c 3Term::ReadLine - Perl interface to various C<readline> packages.
4If no real package is found, substitutes stubs instead of basic functions.
cb31d310 5
6=head1 SYNOPSIS
7
8 use Term::ReadLine;
7824b127 9 my $term = new Term::ReadLine 'Simple Perl calc';
10 my $prompt = "Enter your arithmetic expression: ";
11 my $OUT = $term->OUT || \*STDOUT;
cb31d310 12 while ( defined ($_ = $term->readline($prompt)) ) {
d49f26d4 13 my $res = eval($_);
cb31d310 14 warn $@ if $@;
15 print $OUT $res, "\n" unless $@;
16 $term->addhistory($_) if /\S/;
17 }
18
c07a80fd 19=head1 DESCRIPTION
20
21This package is just a front end to some other packages. At the moment
22this description is written, the only such package is Term-ReadLine,
23available on CPAN near you. The real target of this stub package is to
24set up a common interface to whatever Readline emerges with time.
25
cb31d310 26=head1 Minimal set of supported functions
27
28All the supported functions should be called as methods, i.e., either as
29
30 $term = new Term::ReadLine 'name';
31
32or as
33
34 $term->addhistory('row');
35
d49f26d4 36where $term is a return value of Term::ReadLine-E<gt>new().
cb31d310 37
38=over 12
39
40=item C<ReadLine>
41
42returns the actual package that executes the commands. Among possible
43values are C<Term::ReadLine::Gnu>, C<Term::ReadLine::Perl>,
e15d0a48 44C<Term::ReadLine::Stub>.
cb31d310 45
46=item C<new>
47
48returns the handle for subsequent calls to following
49functions. Argument is the name of the application. Optionally can be
50followed by two arguments for C<IN> and C<OUT> filehandles. These
51arguments should be globs.
52
53=item C<readline>
54
55gets an input line, I<possibly> with actual C<readline>
56support. Trailing newline is removed. Returns C<undef> on C<EOF>.
57
58=item C<addhistory>
59
60adds the line to the history of input, from where it can be used if
61the actual C<readline> is present.
62
d49f26d4 63=item C<IN>, C<OUT>
cb31d310 64
65return the filehandles for input and output or C<undef> if C<readline>
66input and output cannot be used for Perl.
67
68=item C<MinLine>
69
70If argument is specified, it is an advice on minimal size of line to
71be included into history. C<undef> means do not include anything into
72history. Returns the old value.
73
74=item C<findConsole>
75
76returns an array with two strings that give most appropriate names for
1fef88e7 77files for input and output using conventions C<"E<lt>$in">, C<"E<gt>out">.
cb31d310 78
a737e074 79=item Attribs
80
81returns a reference to a hash which describes internal configuration
82of the package. Names of keys in this hash conform to standard
83conventions with the leading C<rl_> stripped.
84
cb31d310 85=item C<Features>
86
87Returns a reference to a hash with keys being features present in
88current implementation. Several optional features are used in the
89minimal interface: C<appname> should be present if the first argument
90to C<new> is recognized, and C<minline> should be present if
91C<MinLine> method is not dummy. C<autohistory> should be present if
92lines are put into history automatically (maybe subject to
93C<MinLine>), and C<addhistory> if C<addhistory> method is not dummy.
94
a737e074 95If C<Features> method reports a feature C<attribs> as present, the
96method C<Attribs> is not dummy.
97
cb31d310 98=back
99
a737e074 100=head1 Additional supported functions
101
cb31d310 102Actually C<Term::ReadLine> can use some other package, that will
103support reacher set of commands.
104
a737e074 105All these commands are callable via method interface and have names
106which conform to standard conventions with the leading C<rl_> stripped.
107
f36776d9 108The stub package included with the perl distribution allows some
109additional methods:
110
111=over 12
112
113=item C<tkRunning>
114
7a2e2cd6 115makes Tk event loop run when waiting for user input (i.e., during
f36776d9 116C<readline> method).
117
118=item C<ornaments>
119
120makes the command line stand out by using termcap data. The argument
121to C<ornaments> should be 0, 1, or a string of a form
122C<"aa,bb,cc,dd">. Four components of this string should be names of
123I<terminal capacities>, first two will be issued to make the prompt
124standout, last two to make the input line standout.
125
126=item C<newTTY>
127
128takes two arguments which are input filehandle and output filehandle.
129Switches to use these filehandles.
130
131=back
132
133One can check whether the currently loaded ReadLine package supports
134these methods by checking for corresponding C<Features>.
7a2e2cd6 135
cb31d310 136=head1 EXPORTS
137
138None
139
a737e074 140=head1 ENVIRONMENT
141
8dcee03e 142The environment variable C<PERL_RL> governs which ReadLine clone is
405ff068 143loaded. If the value is false, a dummy interface is used. If the value
144is true, it should be tail of the name of the package to use, such as
145C<Perl> or C<Gnu>.
a737e074 146
405ff068 147As a special case, if the value of this variable is space-separated,
148the tail might be used to disable the ornaments by setting the tail to
149be C<o=0> or C<ornaments=0>. The head should be as described above, say
150
151If the variable is not set, or if the head of space-separated list is
152empty, the best available package is loaded.
153
154 export "PERL_RL=Perl o=0" # Use Perl ReadLine without ornaments
155 export "PERL_RL= o=0" # Use best available ReadLine without ornaments
156
157(Note that processing of C<PERL_RL> for ornaments is in the discretion of the
158particular used C<Term::ReadLine::*> package).
a737e074 159
4c3ccbe1 160=head1 CAVEATS
161
162It seems that using Term::ReadLine from Emacs minibuffer doesn't work
163quite right and one will get an error message like
164
165 Cannot open /dev/tty for read at ...
166
167One possible workaround for this is to explicitly open /dev/tty like this
168
169 open (FH, "/dev/tty" )
170 or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }';
171 die $@ if $@;
172 close (FH);
173
174or you can try using the 4-argument form of Term::ReadLine->new().
175
cb31d310 176=cut
177
b75c8c73 178use strict;
179
cb31d310 180package Term::ReadLine::Stub;
b75c8c73 181our @ISA = qw'Term::ReadLine::Tk Term::ReadLine::TermCap';
cb31d310 182
183$DB::emacs = $DB::emacs; # To peacify -w
b75c8c73 184our @rl_term_set;
7a2e2cd6 185*rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
cb31d310 186
2499d329 187sub PERL_UNICODE_STDIN () { 0x0001 }
188
cb31d310 189sub ReadLine {'Term::ReadLine::Stub'}
190sub readline {
a737e074 191 my $self = shift;
192 my ($in,$out,$str) = @$self;
6d697788 193 my $prompt = shift;
194 print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
a737e074 195 $self->register_Tk
196 if not $Term::ReadLine::registered and $Term::ReadLine::toloop
197 and defined &Tk::DoOneEvent;
198 #$str = scalar <$in>;
199 $str = $self->get_line;
6d697788 200 $str =~ s/^\s*\Q$prompt\E// if ($^O eq 'MacOS');
2499d329 201 utf8::upgrade($str)
11412ee6 202 if (${^UNICODE} & PERL_UNICODE_STDIN || defined ${^ENCODING}) &&
203 utf8::valid($str);
7a2e2cd6 204 print $out $rl_term_set[3];
cb31d310 205 # bug in 5.000: chomping empty string creats length -1:
206 chomp $str if defined $str;
207 $str;
208}
209sub addhistory {}
210
211sub findConsole {
212 my $console;
213
6d697788 214 if ($^O eq 'MacOS') {
215 $console = "Dev:Console";
216 } elsif (-e "/dev/tty") {
cb31d310 217 $console = "/dev/tty";
8878e869 218 } elsif (-e "con" or $^O eq 'MSWin32') {
cb31d310 219 $console = "con";
220 } else {
221 $console = "sys\$command";
222 }
223
4d2c4e07 224 if (($^O eq 'amigaos') || ($^O eq 'beos') || ($^O eq 'epoc')) {
287f63d2 225 $console = undef;
226 }
227 elsif ($^O eq 'os2') {
cb31d310 228 if ($DB::emacs) {
229 $console = undef;
230 } else {
231 $console = "/dev/con";
232 }
233 }
234
b75c8c73 235 my $consoleOUT = $console;
cb31d310 236 $console = "&STDIN" unless defined $console;
237 if (!defined $consoleOUT) {
238 $consoleOUT = defined fileno(STDERR) ? "&STDERR" : "&STDOUT";
239 }
240 ($console,$consoleOUT);
241}
242
243sub new {
244 die "method new called with wrong number of arguments"
245 unless @_==2 or @_==4;
246 #local (*FIN, *FOUT);
405ff068 247 my ($FIN, $FOUT, $ret);
cb31d310 248 if (@_==2) {
4c3ccbe1 249 my($console, $consoleOUT) = $_[0]->findConsole;
cb31d310 250
251 open(FIN, "<$console");
252 open(FOUT,">$consoleOUT");
253 #OUT->autoflush(1); # Conflicts with debugger?
b75c8c73 254 my $sel = select(FOUT);
cb31d310 255 $| = 1; # for DB::OUT
256 select($sel);
405ff068 257 $ret = bless [\*FIN, \*FOUT];
cb31d310 258 } else { # Filehandles supplied
259 $FIN = $_[2]; $FOUT = $_[3];
260 #OUT->autoflush(1); # Conflicts with debugger?
b75c8c73 261 my $sel = select($FOUT);
cb31d310 262 $| = 1; # for DB::OUT
263 select($sel);
405ff068 264 $ret = bless [$FIN, $FOUT];
cb31d310 265 }
405ff068 266 if ($ret->Features->{ornaments}
267 and not ($ENV{PERL_RL} and $ENV{PERL_RL} =~ /\bo\w*=0/)) {
268 local $Term::ReadLine::termcap_nowarn = 1;
269 $ret->ornaments(1);
270 }
271 return $ret;
cb31d310 272}
f36776d9 273
274sub newTTY {
275 my ($self, $in, $out) = @_;
276 $self->[0] = $in;
277 $self->[1] = $out;
278 my $sel = select($out);
279 $| = 1; # for DB::OUT
280 select($sel);
281}
282
cb31d310 283sub IN { shift->[0] }
284sub OUT { shift->[1] }
285sub MinLine { undef }
a737e074 286sub Attribs { {} }
287
84902520 288my %features = (tkRunning => 1, ornaments => 1, 'newTTY' => 1);
a737e074 289sub Features { \%features }
cb31d310 290
291package Term::ReadLine; # So late to allow the above code be defined?
a737e074 292
11412ee6 293our $VERSION = '1.01';
b75c8c73 294
405ff068 295my ($which) = exists $ENV{PERL_RL} ? split /\s+/, $ENV{PERL_RL} : undef;
a737e074 296if ($which) {
297 if ($which =~ /\bgnu\b/i){
298 eval "use Term::ReadLine::Gnu;";
299 } elsif ($which =~ /\bperl\b/i) {
300 eval "use Term::ReadLine::Perl;";
301 } else {
302 eval "use Term::ReadLine::$which;";
303 }
405ff068 304} elsif (defined $which and $which ne '') { # Defined but false
a737e074 305 # Do nothing fancy
306} else {
307 eval "use Term::ReadLine::Gnu; 1" or eval "use Term::ReadLine::Perl; 1";
308}
cb31d310 309
310#require FileHandle;
311
312# To make possible switch off RL in debugger: (Not needed, work done
313# in debugger).
b75c8c73 314our @ISA;
cb31d310 315if (defined &Term::ReadLine::Gnu::readline) {
316 @ISA = qw(Term::ReadLine::Gnu Term::ReadLine::Stub);
317} elsif (defined &Term::ReadLine::Perl::readline) {
318 @ISA = qw(Term::ReadLine::Perl Term::ReadLine::Stub);
e15d0a48 319} elsif (defined $which && defined &{"Term::ReadLine::$which\::readline"}) {
320 @ISA = "Term::ReadLine::$which";
cb31d310 321} else {
322 @ISA = qw(Term::ReadLine::Stub);
323}
324
7a2e2cd6 325package Term::ReadLine::TermCap;
326
327# Prompt-start, prompt-end, command-line-start, command-line-end
328# -- zero-width beautifies to emit around prompt and the command line.
b75c8c73 329our @rl_term_set = ("","","","");
7a2e2cd6 330# string encoded:
b75c8c73 331our $rl_term_set = ',,,';
7a2e2cd6 332
b75c8c73 333our $terminal;
7a2e2cd6 334sub LoadTermCap {
335 return if defined $terminal;
336
337 require Term::Cap;
338 $terminal = Tgetent Term::Cap ({OSPEED => 9600}); # Avoid warning.
339}
340
341sub ornaments {
342 shift;
343 return $rl_term_set unless @_;
344 $rl_term_set = shift;
345 $rl_term_set ||= ',,,';
7b8d334a 346 $rl_term_set = 'us,ue,md,me' if $rl_term_set eq '1';
7a2e2cd6 347 my @ts = split /,/, $rl_term_set, 4;
348 eval { LoadTermCap };
405ff068 349 unless (defined $terminal) {
350 warn("Cannot find termcap: $@\n") unless $Term::ReadLine::termcap_nowarn;
351 $rl_term_set = ',,,';
352 return;
353 }
7a2e2cd6 354 @rl_term_set = map {$_ ? $terminal->Tputs($_,1) || '' : ''} @ts;
355 return $rl_term_set;
356}
357
358
a737e074 359package Term::ReadLine::Tk;
360
b75c8c73 361our($count_handle, $count_DoOne, $count_loop);
a737e074 362$count_handle = $count_DoOne = $count_loop = 0;
363
b75c8c73 364our($giveup);
a737e074 365sub handle {$giveup = 1; $count_handle++}
366
367sub Tk_loop {
368 # Tk->tkwait('variable',\$giveup); # needs Widget
369 $count_DoOne++, Tk::DoOneEvent(0) until $giveup;
370 $count_loop++;
371 $giveup = 0;
372}
373
374sub register_Tk {
375 my $self = shift;
376 $Term::ReadLine::registered++
377 or Tk->fileevent($self->IN,'readable',\&handle);
378}
379
380sub tkRunning {
381 $Term::ReadLine::toloop = $_[1] if @_ > 1;
382 $Term::ReadLine::toloop;
383}
384
385sub get_c {
386 my $self = shift;
387 $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
388 return getc $self->IN;
389}
390
391sub get_line {
392 my $self = shift;
393 $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
394 my $in = $self->IN;
4e83e451 395 local ($/) = "\n";
a737e074 396 return scalar <$in>;
397}
cb31d310 398
3991;
400