File Coverage

blib/lib/IO/EditPrompt.pm
Criterion Covered Total %
statement 52 60 86.6
branch 14 24 58.3
condition 11 13 84.6
subroutine 11 12 91.6
pod 2 2 100.0
total 90 111 81.0


line stmt bran cond sub pod time code
1             package IO::EditPrompt;
2              
3 7     7   268493 use warnings;
  7         16  
  7         219  
4 7     7   31 use strict;
  7         81  
  7         214  
5              
6 7     7   2843 use File::Temp ();
  7         67993  
  7         155  
7 7     7   5435 use IO::Prompter ();
  7         193282  
  7         5861  
8              
9             our $VERSION = '0.02';
10              
11             sub new {
12 13     13 1 4708 my ($class, $opts) = (@_);
13              
14 13   100     55 $opts ||= {};
15 13 100       62 die "parameter is not a hashref.\n" unless ref $opts eq ref {};
16 11 100 100     162 die "'$opts->{tmpdir}' is not a directory.\n" if defined $opts->{tmpdir} and !-d $opts->{tmpdir};
17              
18 10         109 my $self = bless {
19             dir => $opts->{tmpdir},
20             editor => $opts->{editor},
21             editor_args => [],
22             }, $class;
23 10         53 $self->_normalize_editor( $opts->{default_editor} );
24 10         44 return $self;
25             }
26              
27             sub prompt {
28 2     2 1 8 my ($self, $prompt, $deftext) = @_;
29              
30 2         2 my $output = '';
31 2         5 my $fmt_prompt = _format_prompt( $prompt );
32              
33 2   66     4 do {
34 2         4 my ($tmp, $filename) = $self->_create_tmp_file( $fmt_prompt, $deftext );
35 2         7 $self->_run_editor( $filename );
36 2         83 $output = $self->_get_output( $filename, $fmt_prompt );
37             } while( (0 == length $output) && IO::Prompter::prompt( 'Content is empty, retry?', '-y' ) );
38              
39 2         305 return $output;
40             }
41              
42             sub _normalize_editor {
43 18     18   6742 my ($self, $def_editor) = @_;
44 18   100     167 $self->{editor} ||= $ENV{EDITOR} || $def_editor || 'vim';
      66        
45              
46             # Turn off saving state on vim
47 18 100       131 $self->{editor_args} = [ '-i', 'NONE' ] if $self->{editor} =~ /\bvim$/;
48 18         35 return;
49             }
50              
51             sub _format_prompt {
52 7     7   18 my ($prompt) = @_;
53 7 100       23 return '' unless defined $prompt;
54 6         20 return join( q{}, map { "# $_\n" } split /\n/, $prompt );
  6         22  
55             }
56              
57             sub _create_tmp_file {
58 4     4   16 my ($self, @texts) = @_;
59              
60 4 100       39 my $tmp = File::Temp->new( UNLINK => 1, EXLOCK => 1, ($self->{dir} ? (DIR => $self->{dir}) : ()) );
61 4         368307 my $filename = $tmp->filename;
62 4         21 print {$tmp} grep { defined $_ } @texts;
  4         9  
  6         49  
63 4 50       147 close( $tmp ) or die "Unable to write '$filename': $!\n";
64              
65 4         16 return ($tmp, $filename);
66             }
67              
68             sub _read_file {
69 5     5   6 my ($self, $filename) = @_;
70 5 50       92 open my $fh, '<', $filename or die "Unable to re-read '$filename': $!\n";
71 5         14 local $/;
72 5         71 return scalar <$fh>;
73             }
74              
75             sub _get_output {
76 8     8   4149 my ($self, $filename, $prompt) = @_;
77 8 100       116 return '' if -s $filename eq length $prompt;
78 5         13 my $output = $self->_read_file( $filename );
79 5         29 $output =~ s/^#[^\n]*(?:\n|\Z)//smg;
80 5         22 return $output;
81             }
82              
83             sub _run_editor {
84 0     0     my ($self, $file) = @_;
85 0           my $err = system $self->{editor}, @{$self->{editor_args}}, $file;
  0            
86 0 0         return unless $err;
87 0 0         if ($? == -1) {
    0          
88 0           die "failed to execute '$self->{editor}': $!\n";
89             }
90             elsif ($? & 127) {
91 0 0         die sprintf "'$self->{editor}' died with signal %d, %s coredump\n",
92             ($? & 127), ($? & 128) ? 'with' : 'without';
93             }
94             else {
95 0           die sprintf "'$self->{editor}' exited with value %d\n", $? >> 8;
96             }
97             }
98              
99             1;
100             __END__