keep $VERSION right in the repo
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / ReadLineHistory.pm
1 # First cut at using the readline history directly rather than reimplementing
2 # it. It does save history but it's a little crappy; still playing with it ;)
3 #
4 # epitaph, 22nd April 2007
5
6 use strict;
7 use warnings;
8 package Devel::REPL::Plugin::ReadLineHistory;
9
10 our $VERSION = '1.003027';
11
12 use Devel::REPL::Plugin;
13 use File::HomeDir;
14 use File::Spec;
15 use namespace::autoclean;
16
17 my $hist_file = $ENV{PERLREPL_HISTFILE} ||
18     File::Spec->catfile(File::HomeDir->my_home, '.perlreplhist');
19
20 # HISTLEN should probably be in a config file to stop people accidentally
21 # truncating their history if they start the program and forget to set
22 # PERLREPL_HISTLEN
23 my $hist_len=$ENV{PERLREPL_HISTLEN} || 100;
24
25 around 'run' => sub {
26    my $orig=shift;
27    my ($self, @args)=@_;
28    if ($self->term->ReadLine eq 'Term::ReadLine::Gnu') {
29       $self->term->stifle_history($hist_len);
30    }
31    if ($self->term->ReadLine eq 'Term::ReadLine::Perl') {
32       $self->term->Attribs->{MaxHistorySize} = $hist_len;
33    }
34    if (-f($hist_file)) {
35       if ($self->term->ReadLine eq 'Term::ReadLine::Gnu') {
36          $self->term->ReadHistory($hist_file);
37       }
38       if ($self->term->ReadLine eq 'Term::ReadLine::Perl') {
39          open HIST, $hist_file or die "ReadLineHistory: could not open $hist_file: $!\n";
40          while (my $line = <HIST>) {
41             chomp $line;
42             $self->term->addhistory($line);
43          }
44          close HIST;
45       }
46    }
47
48    $self->term->Attribs->{do_expand}=1;  # for Term::ReadLine::Gnu
49    $self->term->MinLine(2);              # don't save one letter commands
50
51    # let History plugin know we have Term::ReadLine support
52    $self->have_readline_history(1) if $self->can('have_readline_history');
53
54
55    $self->$orig(@args);
56
57    if ($self->term->ReadLine eq 'Term::ReadLine::Gnu') {
58       $self->term->WriteHistory($hist_file) ||
59       $self->print("warning: failed to write history file $hist_file");
60    }
61    if ($self->term->ReadLine eq 'Term::ReadLine::Perl') {
62       my @lines = $self->term->GetHistory() if $self->term->can('GetHistory');
63       if( open HIST, ">$hist_file" ) {
64          print HIST join("\n",@lines);
65          close HIST;
66       } else {
67          $self->print("warning: unable to WriteHistory to $hist_file");
68       }
69    }
70 };
71
72 1;
73
74 __END__
75
76 =head1 NAME
77
78 Devel::REPL::Plugin::ReadLineHistory - Integrate history with the facilities provided by L<Term::ReadLine>
79
80 =head1 DESCRIPTION
81
82 This plugin enables loading and saving command line history from
83 a file as well has history expansion of previous commands using
84 the !-syntax a la bash.
85
86 By default, history expansion is enabled with this plugin when
87 using L<Term::ReadLine::Gnu|Term::ReadLine::Gnu>. That means that
88 "loose" '!' characters will be treated as history events which
89 may not be what you wish.
90
91 To avoid this, you need to quote the '!' with '\':
92
93   my $var = "foo\!";
94
95 or place the arguments in single quotes---but enable the
96 C<Term::ReadLine> attribute C<history_quotes_inhibit_expansion>:
97
98   $_REPL->term->Attribs->{history_quotes_inhibit_expansion} = 1;
99   my $var = 'foo!';
100
101 and to disable history expansion from GNU readline/history do
102
103   $_REPL->term->Attribs->{do_expand} = 0;
104
105 =head1 CONFLICTS
106
107 Note that L<Term::ReadLine::Perl> does not support a history
108 expansion method.  In that case, you may wish to use the
109 L<Devel::REPL History plugin|Devel::REPL::Plugin::History> which provides similar functions.
110 Work is underway to make use of either L<History|Devel::REPL::Plugin::History> or
111 L<ReadLineHistory|Devel::REPL::Plugin::ReadHistory>> consistent for expansion with either the
112 L<Term::ReadLine::Gnu> support or L<Term::ReadLine::Perl>.
113
114 =cut
115