File Coverage

blib/lib/AnyEvent/EditText.pm
Criterion Covered Total %
statement 15 69 21.7
branch 0 20 0.0
condition n/a
subroutine 5 9 55.5
pod 2 2 100.0
total 22 100 22.0


line stmt bran cond sub pod time code
1             package AnyEvent::EditText;
2 1     1   23395 no warnings;
  1         2  
  1         30  
3 1     1   5 use strict;
  1         1  
  1         28  
4              
5 1     1   954 use IO::Handle;
  1         7390  
  1         44  
6 1     1   11809 use File::Temp qw/tempfile/;
  1         22379  
  1         79  
7 1     1   2220 use AnyEvent;
  1         7053  
  1         662  
8              
9             our %PIDS;
10             our %READER;
11             our @EDITOR = ("rxvt", "-e", "vim");
12              
13             =head1 NAME
14              
15             AnyEvent::EditText - An easy way to startup a text editor
16              
17             =head1 VERSION
18              
19             Version 0.2
20              
21             =cut
22              
23             our $VERSION = '0.2';
24              
25             =head1 SYNOPSIS
26              
27             my $content = "Hello There!";
28              
29             AnyEvent::EditText::edit ($content, sub {
30             my ($newcontent, $has_changed) = @_;
31              
32             if ($has_changed) {
33             print "the content was edited";
34             }
35             });
36              
37             =head1 DESCRIPTION
38              
39             This little module will start a text editor in a seperate process without
40             stopping the current process. Usually something like a terminal with a vim
41             instance running in it will be started, but also a graphical editor could be
42             used (like I or I).
43              
44             The editor will get the content passed to the C routine as temporary
45             file, and after you are done editing it (closed the editor) the callback
46             will be called with the possibly new content.
47              
48             =head1 FUNCTIONS
49              
50             =head2 set_editor (@sysargs)
51              
52             This function configures the editor used. C<@sysargs> is a list of
53             arguments for the C function, which will be called like this
54             by C:
55              
56             system (@sysargs, $filename);
57              
58             The default editor used will be:
59              
60             AnyEvent::EditText::set_editor ("rxvt", "-e", "vim");
61              
62             =cut
63              
64             sub set_editor {
65 0     0 1   @EDITOR = @_;
66             }
67              
68             =head2 edit ($content, $callback)
69              
70             This routine will write C<$content> to a temporary file, fork
71             and call the editing process. After the process terminates the
72             temporary file is read and erased.
73              
74             After that the content is sent back to the calling process, where the
75             C<$callback> is called with two arguments: The first will be the new content
76             and the second a flag indicating whether the content has changed.
77              
78             =cut
79              
80             sub edit {
81 0     0 1   my ($content, $finish) = @_;
82 0           pipe (my $par_rdr, my $child_wtr);
83 0           $par_rdr->autoflush (1);
84 0           $child_wtr->autoflush (1);
85              
86 0           my $pid;
87 0 0         if ($pid = fork) {
88 0           $child_wtr->close;
89              
90 0           my $buffer = '';
91             $READER{$pid} = AnyEvent->io (fh => $par_rdr, poll => 'r', cb => sub {
92 0     0     my $l = sysread $par_rdr, my $data, 1024;
93 0 0         if ($l) {
    0          
94 0           $buffer .= $data;
95             } elsif (defined $l) {
96 0           delete $READER{$pid};
97 0 0         if ($buffer =~ s/^(.+?)\n\n//) {
98 0           $finish->(undef, undef, $1);
99             } else {
100 0           $buffer =~ s/^\n\n//;
101 0           $finish->($buffer, $content ne $buffer);
102             }
103             } else {
104 0           warn "couldn't read from child: $!";
105 0           delete $READER{$pid};
106 0           $finish->(undef, undef);
107             }
108 0           });
109              
110             $PIDS{$pid} = AnyEvent->child (pid => $pid, cb => sub {
111 0     0     delete $PIDS{$pid};
112 0           });
113              
114             } else {
115 0           $par_rdr->close;
116 0 0         die "couldn't fork: $!" unless defined $pid;
117 0           my ($fh, $filename) = tempfile ("text_edit_XXXXX", DIR => "/tmp");
118 0           print $fh $content;
119 0           close $fh;
120              
121 0           my $ex = system (@EDITOR, $filename);
122 0 0         unless ($ex == 0) {
123 0           my $err;
124 0 0         if ($? == -1) {
    0          
125 0           $err = "system call failed: $!\n";
126             } elsif ($? & 127) {
127 0 0         $err = sprintf "system call died with signal %d, %s coredump\n",
128             ($? & 127), ($? & 128) ? 'with' : 'without';
129             }
130 0           $err =~ s/\n//g;
131 0           print $child_wtr "$err\n\n";
132 0           close $child_wtr;
133 0           unlink $filename;
134 0           exit;
135             }
136              
137             open $fh, "<$filename"
138 0 0         or do {
139 0           my $err = "Couldn't open '$filename' for reading: $!\n\n";
140 0           $err =~ s/\n//g;
141 0           print $child_wtr "$err\n\n";
142 0           close $child_wtr;
143 0           unlink $filename;
144 0           exit;
145             };
146              
147 0           $content = do { local $/; <$fh> };
  0            
  0            
148 0           close $fh;
149              
150 0           print $child_wtr "\n\n$content";
151 0           close $child_wtr;
152              
153 0           unlink $filename;
154 0           exit;
155             }
156             }
157              
158             =head1 AUTHOR
159              
160             Robin Redeker, C<< >>
161              
162             =head1 TODO
163              
164             This module should probably first look in the environment to determine
165             which editor and terminal to use. This will be fixed in the next release.
166              
167             =head1 BUGS
168              
169             Please report any bugs or feature requests to
170             C, or through the web interface at
171             L.
172             I will be notified, and then you'll automatically be notified of progress on
173             your bug as I make changes.
174              
175             =head1 SUPPORT
176              
177             You can find documentation for this module with the perldoc command.
178              
179             perldoc AnyEvent::EditText
180              
181             You can also look for information at:
182              
183             =over 4
184              
185             =item * AnnoCPAN: Annotated CPAN documentation
186              
187             L
188              
189             =item * CPAN Ratings
190              
191             L
192              
193             =item * RT: CPAN's request tracker
194              
195             L
196              
197             =item * Search CPAN
198              
199             L
200              
201             =back
202              
203             =head1 COPYRIGHT & LICENSE
204              
205             Copyright 2007 Robin Redeker, all rights reserved.
206             Copyright 2008 Robin Redeker, all rights reserved.
207              
208             This program is free software; you can redistribute it and/or modify it
209             under the same terms as Perl itself.
210              
211             =cut
212              
213             1; # End of AnyEvent::EditText