File Coverage

blib/lib/IO/EditPrompt.pm
Criterion Covered Total %
statement 52 60 86.6
branch 12 24 50.0
condition 10 13 76.9
subroutine 11 12 91.6
pod 2 2 100.0
total 87 111 78.3


line stmt bran cond sub pod time code
1             package IO::EditPrompt;
2              
3 6     6   160723 use warnings;
  6         10  
  6         162  
4 6     6   24 use strict;
  6         8  
  6         141  
5              
6 6     6   2614 use File::Temp ();
  6         70524  
  6         118  
7 6     6   4148 use IO::Prompter ();
  6         151210  
  6         3937  
8              
9             our $VERSION = '0.01';
10              
11             sub new {
12 5     5 1 2026 my ($class, $opts) = (@_);
13              
14 5   100     26 $opts ||= {};
15 5 50       17 die "parameter is not a hashref.\n" unless ref $opts eq ref {};
16 5 50 66     49 die "'$opts->{tmpdir}' is not a directory.\n" if defined $opts->{tmpdir} and !-d $opts->{tmpdir};
17              
18 5         38 my $self = bless {
19             dir => $opts->{tmpdir},
20             editor => $opts->{editor},
21             editor_args => [],
22             }, $class;
23 5         25 $self->_normalize_editor( $opts->{default_editor} );
24 5         15 return $self;
25             }
26              
27             sub prompt {
28 2     2 1 7 my ($self, $prompt, $deftext) = @_;
29              
30 2         3 my $output = '';
31 2         4 my $fmt_prompt = _format_prompt( $prompt );
32              
33 2   66     3 do {
34 2         5 my ($tmp, $filename) = $self->_create_tmp_file( $fmt_prompt, $deftext );
35 2         5 $self->_run_editor( $filename );
36 2         65 $output = $self->_get_output( $filename, $fmt_prompt );
37             } while( (0 == length $output) && IO::Prompter::prompt( 'Content is empty, retry?', '-y' ) );
38              
39 2         225 return $output;
40             }
41              
42             sub _normalize_editor {
43 13     13   5705 my ($self, $def_editor) = @_;
44 13   100     93 $self->{editor} ||= $ENV{EDITOR} || $def_editor || 'vim';
      66        
45              
46             # Turn off saving state on vim
47 13 100       60 $self->{editor_args} = [ '-i', 'NONE' ] if $self->{editor} =~ /\bvim$/;
48 13         22 return;
49             }
50              
51             sub _format_prompt {
52 7     7   14 my ($prompt) = @_;
53 7 100       20 return '' unless defined $prompt;
54 6         19 return join( q{}, map { "# $_\n" } split /\n/, $prompt );
  6         21  
55             }
56              
57             sub _create_tmp_file {
58 4     4   13 my ($self, @texts) = @_;
59              
60 4 100       30 my $tmp = File::Temp->new( UNLINK => 1, EXLOCK => 1, ($self->{dir} ? (DIR => $self->{dir}) : ()) );
61 4         1531 my $filename = $tmp->filename;
62 4         13 print {$tmp} grep { defined $_ } @texts;
  4         8  
  6         43  
63 4 50       119 close( $tmp ) or die "Unable to write '$filename': $!\n";
64              
65 4         13 return ($tmp, $filename);
66             }
67              
68             sub _read_file {
69 5     5   7 my ($self, $filename) = @_;
70 5 50       117 open my $fh, '<', $filename or die "Unable to re-read '$filename': $!\n";
71 5         15 local $/;
72 5         85 return scalar <$fh>;
73             }
74              
75             sub _get_output {
76 8     8   5958 my ($self, $filename, $prompt) = @_;
77 8 100       126 return '' if -s $filename eq length $prompt;
78 5         16 my $output = $self->_read_file( $filename );
79 5         36 $output =~ s/^#[^\n]*(?:\n|\Z)//smg;
80 5         25 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__