ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-ReadLine-Gnu/Gnu.pm
Revision: 1.3
Committed: Thu May 10 22:59:21 2012 UTC (12 years ago) by root
Branch: MAIN
Changes since 1.2: +27 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     AnyEvent::ReadLine::Gnu - event-based interface to Term::ReadLine::Gnu
4    
5     =head1 SYNOPSIS
6    
7     use AnyEvent::ReadLine::Gnu;
8    
9     # works always, prints message to stdout
10     AnyEvent::ReadLine::Gnu->print ("message\n");
11    
12     # now initialise readline
13 root 1.2 my $rl = new AnyEvent::ReadLine::Gnu prompt => "hi> ", on_line => sub {
14 root 1.1 # called for each line entered by the user
15     AnyEvent::ReadLine::Gnu->print ("you entered: $_[0]\n");
16     };
17    
18     # asynchronously print something
19     my $t = AE::timer 1, 1, sub {
20     $rl->hide;
21     print "async message 1\n"; # mind the \n
22     $rl->show;
23    
24     # the same, but shorter:
25     $rl->print ("async message 2\n");
26     };
27    
28     # do other eventy stuff...
29     AE::cv->recv;
30    
31     =head1 DESCRIPTION
32    
33     The L<Term::ReadLine> module family is bizarre (and you are encouraged not
34     to look at its sources unless you want to go blind). It does support
35     event-based operations, somehow, but it's hard to figure out.
36    
37     It also has some utility functions for printing messages asynchronously,
38     something that, again, isn't obvious how to do.
39    
40     This module has figured it all out for you, once and for all.
41    
42     =over 4
43    
44     =cut
45    
46     package AnyEvent::ReadLine::Gnu;
47    
48     use common::sense;
49     use AnyEvent;
50    
51     BEGIN {
52     # we try our best
53     local $ENV{PERL_RL} = "Gnu";
54    
55     require Term::ReadLine;
56     require Term::ReadLine::Gnu;
57     }
58    
59     use base Term::ReadLine::;
60    
61 root 1.2 our $VERSION = '0.2';
62 root 1.1
63     =item $rl = new AnyEvent::ReadLine::Gnu key => value...
64    
65     Creates a new AnyEvent::ReadLine object.
66    
67     Actually, it only configures readline and provides a convenient way to
68     call the show and hide methods, as well as readline methods - this is a
69     singleton.
70    
71     The returned object is the standard L<Term::ReadLine::Gnu> object, all
72     methods that are documented (or working) for that module should work on
73     this object.
74    
75     Once initialised, this module will also restore the terminal settings on a
76     normal program exit.
77    
78     The following key-value pairs are supported:
79    
80     =over 4
81    
82     =item on_line => $cb->($string)
83    
84     The only mandatory parameter - passes the callback that will receive lines
85     that are completed by the user.
86    
87 root 1.2 The string will be in locale-encoding (a multibyte character string). For
88     example, in an utf-8 using locale it will be utf-8. There is no portable
89     way known to the author to convert this into e.g. a unicode string.
90    
91 root 1.1 =item prompt => $string
92    
93     The prompt string to use, defaults to C<< > >>.
94    
95     =item name => $string
96    
97     The readline application name, defaults to C<$0>.
98    
99     =item in => $glob
100    
101     The input filehandle (should be a glob): defaults to C<*STDIN>.
102    
103     =item out => $glob
104    
105     The output filehandle (should be a glob): defaults to C<*STDOUT>.
106    
107     =back
108    
109     =cut
110    
111     our $self;
112     our $prompt;
113     our $cb;
114     our $hidden;
115     our $rw;
116     our ($in, $out);
117    
118     our $saved_point;
119     our $saved_line;
120    
121 root 1.2 # we postpone calling the user clalback here because readline
122     # still has the input buffer at this point, so calling hide and
123     # show might not have the desired effect.
124     sub on_line {
125     my $line = shift;
126     my $point = $self->{point};
127    
128     AE::postpone sub {
129     $cb->($line, $point);
130     };
131     }
132    
133 root 1.1 sub new {
134     my ($class, %arg) = @_;
135    
136     $in = $arg{in} || *STDIN;
137     $out = $arg{out} || *STDOUT;
138     $prompt = $arg{prompt} || "> ";
139 root 1.2 $cb = $arg{on_line} || $arg{cb}
140     or do { require Carp; Carp::croak ("AnyEvent::ReadLine::Gnu->new on_line callback argument mandatry, but missing") };
141 root 1.1
142     $self = $class->SUPER::new ($arg{name} || $0, $in, $out);
143    
144 root 1.2 $self->CallbackHandlerInstall ($prompt, \&on_line);
145 root 1.1 # set the unadorned prompt
146     $self->rl_set_prompt ($prompt);
147    
148     $hidden = 1;
149     $self->show;
150    
151     $self
152     }
153    
154     =item $rl->hide
155    
156     =item AnyEvent::ReadLine::Gnu->hide
157    
158     These methods I<hide> the readline prompt and text. Basically, it removes
159     the readline feedback from your terminal.
160    
161     It is safe to call even when AnyEvent::ReadLine::Gnu has not yet been
162     initialised.
163    
164     This is immensely useful in an event-based program when you want to output
165     some stuff to the terminal without disturbing the prompt - just C<hide>
166     readline, output your thing, then C<show> it again.
167    
168     Since user input will not be processed while readline is hidden, you
169     should call C<show> as soon as possible.
170    
171     =cut
172    
173     sub hide {
174     return if !$self || $hidden++;
175    
176     undef $rw;
177    
178     $saved_point = $self->{point};
179     $saved_line = $self->{line_buffer};
180    
181     $self->rl_set_prompt ("");
182     $self->{line_buffer} = "";
183     $self->rl_redisplay;
184     }
185    
186     =item $rl->show
187    
188     =item AnyEvent::ReadLine::Gnu->show
189    
190     Undos any hiding. Every call to C<hide> has to be followed to a call to
191     C<show>. The last call will redisplay the readline prompt, current input
192     line and cursor position. Keys entered while the prompt was hidden will be
193     processed again.
194    
195     =cut
196    
197     sub show {
198     return if !$self || --$hidden;
199    
200     if (defined $saved_point) {
201     $self->rl_set_prompt ($prompt);
202     $self->{line_buffer} = $saved_line;
203     $self->{point} = $saved_point;
204     $self->redisplay;
205     }
206    
207     $rw = AE::io $in, 0, sub {
208     $self->rl_callback_read_char;
209     };
210     }
211    
212     =item $rl->print ($string, ...)
213    
214     =item AnyEvent::ReadLine::Gnu->print ($string, ...)
215    
216     Prints the given strings to the terminal, by first hiding the readline,
217     printing the message, and showing it again.
218    
219 root 1.2 This function can be called even when readline has never been initialised.
220 root 1.1
221     The last string should end with a newline.
222    
223     =cut
224    
225     sub print {
226     shift;
227    
228     hide;
229     my $out = $out || *STDOUT;
230     print $out @_;
231     show;
232     }
233    
234     END {
235     return unless $self;
236    
237     $self->hide;
238     $self->callback_handler_remove;
239     }
240    
241     1;
242    
243     =back
244    
245 root 1.3 =head1 CAVEATS
246    
247     There are some issues with readline that can be problematic in event-based
248     programs:
249    
250     =over 4
251    
252     =item blocking I/O
253    
254     Readline uses blocking terminal I/O. Under most circumstances, this does
255     not cause big delays, but ttys have the potential to block programs
256     indefinitely (e.g. on XOFF).
257    
258     =item unexpected disk I/O
259    
260     By default, readline does filename completion on TAB, and reads it's config files.
261    
262     =item output intermixing
263    
264     After readline has been initialised, it will mangle the termios tty
265     settings. This does not normally affect output very much, but should be
266     taken into consideration.
267    
268     =back
269    
270     Oh, and the above list is probably not complete.
271    
272 root 1.1 =head1 AUTHOR, CONTACT, SUPPORT
273    
274     Marc Lehmann <schmorp@schmorp.de>
275     http://software.schmorp.de/pkg/AnyEvent-Readline-Gnu.html
276    
277     =cut
278