| 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.7 |
our $VERSION = '1.0'; |
| 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 |
root |
1.7 |
The callback will be installed with the C<CallbackHandlerInstall>, which |
| 79 |
|
|
means it handles history expansion and history, among other things. |
| 80 |
|
|
|
| 81 |
root |
1.1 |
The following key-value pairs are supported: |
| 82 |
|
|
|
| 83 |
|
|
=over 4 |
| 84 |
|
|
|
| 85 |
|
|
=item on_line => $cb->($string) |
| 86 |
|
|
|
| 87 |
|
|
The only mandatory parameter - passes the callback that will receive lines |
| 88 |
|
|
that are completed by the user. |
| 89 |
|
|
|
| 90 |
root |
1.2 |
The string will be in locale-encoding (a multibyte character string). For |
| 91 |
|
|
example, in an utf-8 using locale it will be utf-8. There is no portable |
| 92 |
|
|
way known to the author to convert this into e.g. a unicode string. |
| 93 |
|
|
|
| 94 |
root |
1.1 |
=item prompt => $string |
| 95 |
|
|
|
| 96 |
|
|
The prompt string to use, defaults to C<< > >>. |
| 97 |
|
|
|
| 98 |
|
|
=item name => $string |
| 99 |
|
|
|
| 100 |
|
|
The readline application name, defaults to C<$0>. |
| 101 |
|
|
|
| 102 |
|
|
=item in => $glob |
| 103 |
|
|
|
| 104 |
|
|
The input filehandle (should be a glob): defaults to C<*STDIN>. |
| 105 |
|
|
|
| 106 |
|
|
=item out => $glob |
| 107 |
|
|
|
| 108 |
|
|
The output filehandle (should be a glob): defaults to C<*STDOUT>. |
| 109 |
|
|
|
| 110 |
|
|
=back |
| 111 |
|
|
|
| 112 |
|
|
=cut |
| 113 |
|
|
|
| 114 |
|
|
our $self; |
| 115 |
|
|
our $prompt; |
| 116 |
|
|
our $cb; |
| 117 |
|
|
our $hidden; |
| 118 |
|
|
our $rw; |
| 119 |
|
|
our ($in, $out); |
| 120 |
|
|
|
| 121 |
|
|
our $saved_point; |
| 122 |
|
|
our $saved_line; |
| 123 |
|
|
|
| 124 |
root |
1.2 |
# we postpone calling the user clalback here because readline |
| 125 |
|
|
# still has the input buffer at this point, so calling hide and |
| 126 |
|
|
# show might not have the desired effect. |
| 127 |
|
|
sub on_line { |
| 128 |
|
|
my $line = shift; |
| 129 |
|
|
my $point = $self->{point}; |
| 130 |
|
|
|
| 131 |
|
|
AE::postpone sub { |
| 132 |
|
|
$cb->($line, $point); |
| 133 |
|
|
}; |
| 134 |
|
|
} |
| 135 |
|
|
|
| 136 |
root |
1.1 |
sub new { |
| 137 |
|
|
my ($class, %arg) = @_; |
| 138 |
|
|
|
| 139 |
|
|
$in = $arg{in} || *STDIN; |
| 140 |
|
|
$out = $arg{out} || *STDOUT; |
| 141 |
|
|
$prompt = $arg{prompt} || "> "; |
| 142 |
root |
1.2 |
$cb = $arg{on_line} || $arg{cb} |
| 143 |
|
|
or do { require Carp; Carp::croak ("AnyEvent::ReadLine::Gnu->new on_line callback argument mandatry, but missing") }; |
| 144 |
root |
1.1 |
|
| 145 |
|
|
$self = $class->SUPER::new ($arg{name} || $0, $in, $out); |
| 146 |
|
|
|
| 147 |
root |
1.7 |
$Term::ReadLine::Gnu::Attribs{term_set} = ["", "", "", ""]; |
| 148 |
root |
1.2 |
$self->CallbackHandlerInstall ($prompt, \&on_line); |
| 149 |
root |
1.1 |
|
| 150 |
|
|
$hidden = 1; |
| 151 |
|
|
$self->show; |
| 152 |
|
|
|
| 153 |
|
|
$self |
| 154 |
|
|
} |
| 155 |
|
|
|
| 156 |
|
|
=item $rl->hide |
| 157 |
|
|
|
| 158 |
|
|
=item AnyEvent::ReadLine::Gnu->hide |
| 159 |
|
|
|
| 160 |
|
|
These methods I<hide> the readline prompt and text. Basically, it removes |
| 161 |
|
|
the readline feedback from your terminal. |
| 162 |
|
|
|
| 163 |
|
|
It is safe to call even when AnyEvent::ReadLine::Gnu has not yet been |
| 164 |
|
|
initialised. |
| 165 |
|
|
|
| 166 |
|
|
This is immensely useful in an event-based program when you want to output |
| 167 |
|
|
some stuff to the terminal without disturbing the prompt - just C<hide> |
| 168 |
|
|
readline, output your thing, then C<show> it again. |
| 169 |
|
|
|
| 170 |
|
|
Since user input will not be processed while readline is hidden, you |
| 171 |
|
|
should call C<show> as soon as possible. |
| 172 |
|
|
|
| 173 |
|
|
=cut |
| 174 |
|
|
|
| 175 |
|
|
sub hide { |
| 176 |
|
|
return if !$self || $hidden++; |
| 177 |
|
|
|
| 178 |
|
|
undef $rw; |
| 179 |
|
|
|
| 180 |
|
|
$saved_point = $self->{point}; |
| 181 |
|
|
$saved_line = $self->{line_buffer}; |
| 182 |
|
|
|
| 183 |
|
|
$self->rl_set_prompt (""); |
| 184 |
|
|
$self->{line_buffer} = ""; |
| 185 |
|
|
$self->rl_redisplay; |
| 186 |
|
|
} |
| 187 |
|
|
|
| 188 |
|
|
=item $rl->show |
| 189 |
|
|
|
| 190 |
|
|
=item AnyEvent::ReadLine::Gnu->show |
| 191 |
|
|
|
| 192 |
|
|
Undos any hiding. Every call to C<hide> has to be followed to a call to |
| 193 |
|
|
C<show>. The last call will redisplay the readline prompt, current input |
| 194 |
|
|
line and cursor position. Keys entered while the prompt was hidden will be |
| 195 |
|
|
processed again. |
| 196 |
|
|
|
| 197 |
|
|
=cut |
| 198 |
|
|
|
| 199 |
|
|
sub show { |
| 200 |
|
|
return if !$self || --$hidden; |
| 201 |
|
|
|
| 202 |
|
|
if (defined $saved_point) { |
| 203 |
|
|
$self->rl_set_prompt ($prompt); |
| 204 |
|
|
$self->{line_buffer} = $saved_line; |
| 205 |
|
|
$self->{point} = $saved_point; |
| 206 |
|
|
$self->redisplay; |
| 207 |
|
|
} |
| 208 |
|
|
|
| 209 |
|
|
$rw = AE::io $in, 0, sub { |
| 210 |
|
|
$self->rl_callback_read_char; |
| 211 |
|
|
}; |
| 212 |
|
|
} |
| 213 |
|
|
|
| 214 |
|
|
=item $rl->print ($string, ...) |
| 215 |
|
|
|
| 216 |
|
|
=item AnyEvent::ReadLine::Gnu->print ($string, ...) |
| 217 |
|
|
|
| 218 |
|
|
Prints the given strings to the terminal, by first hiding the readline, |
| 219 |
|
|
printing the message, and showing it again. |
| 220 |
|
|
|
| 221 |
root |
1.2 |
This function can be called even when readline has never been initialised. |
| 222 |
root |
1.1 |
|
| 223 |
|
|
The last string should end with a newline. |
| 224 |
|
|
|
| 225 |
|
|
=cut |
| 226 |
|
|
|
| 227 |
|
|
sub print { |
| 228 |
|
|
shift; |
| 229 |
|
|
|
| 230 |
|
|
hide; |
| 231 |
|
|
my $out = $out || *STDOUT; |
| 232 |
|
|
print $out @_; |
| 233 |
|
|
show; |
| 234 |
|
|
} |
| 235 |
|
|
|
| 236 |
|
|
END { |
| 237 |
|
|
return unless $self; |
| 238 |
|
|
|
| 239 |
|
|
$self->hide; |
| 240 |
|
|
$self->callback_handler_remove; |
| 241 |
|
|
} |
| 242 |
|
|
|
| 243 |
|
|
1; |
| 244 |
|
|
|
| 245 |
|
|
=back |
| 246 |
|
|
|
| 247 |
root |
1.3 |
=head1 CAVEATS |
| 248 |
|
|
|
| 249 |
|
|
There are some issues with readline that can be problematic in event-based |
| 250 |
|
|
programs: |
| 251 |
|
|
|
| 252 |
|
|
=over 4 |
| 253 |
|
|
|
| 254 |
|
|
=item blocking I/O |
| 255 |
|
|
|
| 256 |
|
|
Readline uses blocking terminal I/O. Under most circumstances, this does |
| 257 |
|
|
not cause big delays, but ttys have the potential to block programs |
| 258 |
|
|
indefinitely (e.g. on XOFF). |
| 259 |
|
|
|
| 260 |
|
|
=item unexpected disk I/O |
| 261 |
|
|
|
| 262 |
root |
1.4 |
By default, readline does filename completion on TAB, and reads its |
| 263 |
|
|
config files. |
| 264 |
root |
1.3 |
|
| 265 |
root |
1.5 |
Tab completion can be disabled by calling C<< $rl->unbind_key (9) >>. |
| 266 |
|
|
|
| 267 |
root |
1.4 |
=item tty settings |
| 268 |
root |
1.3 |
|
| 269 |
|
|
After readline has been initialised, it will mangle the termios tty |
| 270 |
|
|
settings. This does not normally affect output very much, but should be |
| 271 |
|
|
taken into consideration. |
| 272 |
|
|
|
| 273 |
root |
1.4 |
=item output intermixing |
| 274 |
|
|
|
| 275 |
|
|
Your program might wish to print messages (for example, log messages) to |
| 276 |
|
|
STDOUT or STDERR. This will usually cause confusion, unless readline is |
| 277 |
|
|
hidden with the hide method. |
| 278 |
|
|
|
| 279 |
root |
1.3 |
=back |
| 280 |
|
|
|
| 281 |
|
|
Oh, and the above list is probably not complete. |
| 282 |
|
|
|
| 283 |
root |
1.1 |
=head1 AUTHOR, CONTACT, SUPPORT |
| 284 |
|
|
|
| 285 |
|
|
Marc Lehmann <schmorp@schmorp.de> |
| 286 |
root |
1.6 |
http://software.schmorp.de/pkg/AnyEvent-ReadLine-Gnu.html |
| 287 |
root |
1.1 |
|
| 288 |
root |
1.5 |
=head1 SEE ALSO |
| 289 |
|
|
|
| 290 |
|
|
L<rltelnet> - a simple tcp_connect-with-readline program using this module. |
| 291 |
|
|
|
| 292 |
root |
1.1 |
=cut |
| 293 |
|
|
|