FILE * in XS code for PerlIO world:
[p5sagit/p5-mst-13.2.git] / lib / Term / ReadLine.pm
CommitLineData
cb31d310 1=head1 NAME
2
c07a80fd 3Term::ReadLine - Perl interface to various C<readline> packages. If
cb31d310 4no real package is found, substitutes stubs instead of basic functions.
5
6=head1 SYNOPSIS
7
8 use Term::ReadLine;
9 $term = new Term::ReadLine 'Simple Perl calc';
10 $prompt = "Enter your arithmetic expression: ";
11 $OUT = $term->OUT || STDOUT;
12 while ( defined ($_ = $term->readline($prompt)) ) {
13 $res = eval($_), "\n";
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
1fef88e7 36where $term is a return value of Term::ReadLine-E<gt>Init.
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>,
44C<Term::ReadLine::Stub Exporter>.
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
63=item C<IN>, $C<OUT>
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
cb31d310 160=cut
161
b75c8c73 162use strict;
163
cb31d310 164package Term::ReadLine::Stub;
b75c8c73 165our @ISA = qw'Term::ReadLine::Tk Term::ReadLine::TermCap';
cb31d310 166
167$DB::emacs = $DB::emacs; # To peacify -w
b75c8c73 168our @rl_term_set;
7a2e2cd6 169*rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
cb31d310 170
171sub ReadLine {'Term::ReadLine::Stub'}
172sub readline {
a737e074 173 my $self = shift;
174 my ($in,$out,$str) = @$self;
6d697788 175 my $prompt = shift;
176 print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
a737e074 177 $self->register_Tk
178 if not $Term::ReadLine::registered and $Term::ReadLine::toloop
179 and defined &Tk::DoOneEvent;
180 #$str = scalar <$in>;
181 $str = $self->get_line;
6d697788 182 $str =~ s/^\s*\Q$prompt\E// if ($^O eq 'MacOS');
7a2e2cd6 183 print $out $rl_term_set[3];
cb31d310 184 # bug in 5.000: chomping empty string creats length -1:
185 chomp $str if defined $str;
186 $str;
187}
188sub addhistory {}
189
190sub findConsole {
191 my $console;
192
6d697788 193 if ($^O eq 'MacOS') {
194 $console = "Dev:Console";
195 } elsif (-e "/dev/tty") {
cb31d310 196 $console = "/dev/tty";
8878e869 197 } elsif (-e "con" or $^O eq 'MSWin32') {
cb31d310 198 $console = "con";
199 } else {
200 $console = "sys\$command";
201 }
202
4d2c4e07 203 if (($^O eq 'amigaos') || ($^O eq 'beos') || ($^O eq 'epoc')) {
287f63d2 204 $console = undef;
205 }
206 elsif ($^O eq 'os2') {
cb31d310 207 if ($DB::emacs) {
208 $console = undef;
209 } else {
210 $console = "/dev/con";
211 }
212 }
213
b75c8c73 214 my $consoleOUT = $console;
cb31d310 215 $console = "&STDIN" unless defined $console;
216 if (!defined $consoleOUT) {
217 $consoleOUT = defined fileno(STDERR) ? "&STDERR" : "&STDOUT";
218 }
219 ($console,$consoleOUT);
220}
221
222sub new {
223 die "method new called with wrong number of arguments"
224 unless @_==2 or @_==4;
225 #local (*FIN, *FOUT);
405ff068 226 my ($FIN, $FOUT, $ret);
cb31d310 227 if (@_==2) {
b75c8c73 228 my($console, $consoleOUT) = findConsole;
cb31d310 229
230 open(FIN, "<$console");
231 open(FOUT,">$consoleOUT");
232 #OUT->autoflush(1); # Conflicts with debugger?
b75c8c73 233 my $sel = select(FOUT);
cb31d310 234 $| = 1; # for DB::OUT
235 select($sel);
405ff068 236 $ret = bless [\*FIN, \*FOUT];
cb31d310 237 } else { # Filehandles supplied
238 $FIN = $_[2]; $FOUT = $_[3];
239 #OUT->autoflush(1); # Conflicts with debugger?
b75c8c73 240 my $sel = select($FOUT);
cb31d310 241 $| = 1; # for DB::OUT
242 select($sel);
405ff068 243 $ret = bless [$FIN, $FOUT];
cb31d310 244 }
405ff068 245 if ($ret->Features->{ornaments}
246 and not ($ENV{PERL_RL} and $ENV{PERL_RL} =~ /\bo\w*=0/)) {
247 local $Term::ReadLine::termcap_nowarn = 1;
248 $ret->ornaments(1);
249 }
250 return $ret;
cb31d310 251}
f36776d9 252
253sub newTTY {
254 my ($self, $in, $out) = @_;
255 $self->[0] = $in;
256 $self->[1] = $out;
257 my $sel = select($out);
258 $| = 1; # for DB::OUT
259 select($sel);
260}
261
cb31d310 262sub IN { shift->[0] }
263sub OUT { shift->[1] }
264sub MinLine { undef }
a737e074 265sub Attribs { {} }
266
84902520 267my %features = (tkRunning => 1, ornaments => 1, 'newTTY' => 1);
a737e074 268sub Features { \%features }
cb31d310 269
270package Term::ReadLine; # So late to allow the above code be defined?
a737e074 271
b75c8c73 272our $VERSION = '1.00';
273
405ff068 274my ($which) = exists $ENV{PERL_RL} ? split /\s+/, $ENV{PERL_RL} : undef;
a737e074 275if ($which) {
276 if ($which =~ /\bgnu\b/i){
277 eval "use Term::ReadLine::Gnu;";
278 } elsif ($which =~ /\bperl\b/i) {
279 eval "use Term::ReadLine::Perl;";
280 } else {
281 eval "use Term::ReadLine::$which;";
282 }
405ff068 283} elsif (defined $which and $which ne '') { # Defined but false
a737e074 284 # Do nothing fancy
285} else {
286 eval "use Term::ReadLine::Gnu; 1" or eval "use Term::ReadLine::Perl; 1";
287}
cb31d310 288
289#require FileHandle;
290
291# To make possible switch off RL in debugger: (Not needed, work done
292# in debugger).
b75c8c73 293our @ISA;
cb31d310 294if (defined &Term::ReadLine::Gnu::readline) {
295 @ISA = qw(Term::ReadLine::Gnu Term::ReadLine::Stub);
296} elsif (defined &Term::ReadLine::Perl::readline) {
297 @ISA = qw(Term::ReadLine::Perl Term::ReadLine::Stub);
298} else {
299 @ISA = qw(Term::ReadLine::Stub);
300}
301
7a2e2cd6 302package Term::ReadLine::TermCap;
303
304# Prompt-start, prompt-end, command-line-start, command-line-end
305# -- zero-width beautifies to emit around prompt and the command line.
b75c8c73 306our @rl_term_set = ("","","","");
7a2e2cd6 307# string encoded:
b75c8c73 308our $rl_term_set = ',,,';
7a2e2cd6 309
b75c8c73 310our $terminal;
7a2e2cd6 311sub LoadTermCap {
312 return if defined $terminal;
313
314 require Term::Cap;
315 $terminal = Tgetent Term::Cap ({OSPEED => 9600}); # Avoid warning.
316}
317
318sub ornaments {
319 shift;
320 return $rl_term_set unless @_;
321 $rl_term_set = shift;
322 $rl_term_set ||= ',,,';
7b8d334a 323 $rl_term_set = 'us,ue,md,me' if $rl_term_set eq '1';
7a2e2cd6 324 my @ts = split /,/, $rl_term_set, 4;
325 eval { LoadTermCap };
405ff068 326 unless (defined $terminal) {
327 warn("Cannot find termcap: $@\n") unless $Term::ReadLine::termcap_nowarn;
328 $rl_term_set = ',,,';
329 return;
330 }
7a2e2cd6 331 @rl_term_set = map {$_ ? $terminal->Tputs($_,1) || '' : ''} @ts;
332 return $rl_term_set;
333}
334
335
a737e074 336package Term::ReadLine::Tk;
337
b75c8c73 338our($count_handle, $count_DoOne, $count_loop);
a737e074 339$count_handle = $count_DoOne = $count_loop = 0;
340
b75c8c73 341our($giveup);
a737e074 342sub handle {$giveup = 1; $count_handle++}
343
344sub Tk_loop {
345 # Tk->tkwait('variable',\$giveup); # needs Widget
346 $count_DoOne++, Tk::DoOneEvent(0) until $giveup;
347 $count_loop++;
348 $giveup = 0;
349}
350
351sub register_Tk {
352 my $self = shift;
353 $Term::ReadLine::registered++
354 or Tk->fileevent($self->IN,'readable',\&handle);
355}
356
357sub tkRunning {
358 $Term::ReadLine::toloop = $_[1] if @_ > 1;
359 $Term::ReadLine::toloop;
360}
361
362sub get_c {
363 my $self = shift;
364 $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
365 return getc $self->IN;
366}
367
368sub get_line {
369 my $self = shift;
370 $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
371 my $in = $self->IN;
4e83e451 372 local ($/) = "\n";
a737e074 373 return scalar <$in>;
374}
cb31d310 375
3761;
377