@@ -47,6 +47,7 @@ use strict;
4747
4848use File::Temp qw( ) ;
4949use Getopt::Std qw( getopts) ;
50+ use Text::ParseWords qw( quotewords) ;
5051
5152use constant A_NOMATCH => -1;
5253use constant A_NOPAT => -2;
@@ -96,16 +97,10 @@ my $UndoLine;
9697
9798# constants
9899
99- my $NO_APPEND_MODE = 0;
100- my $NO_INSERT_MODE = 0;
101- my $INSERT_MODE = 1;
102- my $APPEND_MODE = 2;
103- my $QUESTIONS_MODE = 1;
104- my $NO_QUESTIONS_MODE = 0;
105100my $PRINT_NUM = 1;
106101my $PRINT_BIN = 2;
107102
108- our $VERSION = ' 0.26 ' ;
103+ our $VERSION = ' 0.27 ' ;
109104
110105my @ESC = (
111106 ' \\ 000' , ' \\ 001' , ' \\ 002' , ' \\ 003' , ' \\ 004' , ' \\ 005' , ' \\ 006' , ' \\ a' ,
@@ -222,7 +217,7 @@ $args[0] = shift;
222217$args [0] = undef if (defined ($args [0]) && $args [0] eq ' -' );
223218Usage() if @ARGV ;
224219$Scripted = $opt {' s' };
225- edEdit($NO_QUESTIONS_MODE , $NO_APPEND_MODE );
220+ edEdit(0 );
226221input() while 1;
227222
228223sub input {
@@ -509,8 +504,7 @@ sub edPrintBin { edPrint($PRINT_BIN); }
509504sub edQuitAsk { edQuit(1); }
510505sub edAppend { edInsert(1); }
511506sub edWriteAppend { edWrite(1); }
512- sub edEditAsk { edEdit(!$Scripted , $NO_INSERT_MODE ); }
513- sub edRead { edEdit($QUESTIONS_MODE ,$INSERT_MODE ); }
507+ sub edEditAsk { edEdit(!$Scripted ); }
514508
515509#
516510# Perform text substitution
@@ -678,6 +672,50 @@ sub edWrite {
678672 return ;
679673}
680674
675+ sub edRead {
676+ my (@tmp_lines , $chars , $fh , $filename , $do_pipe , $targ );
677+
678+ $targ = $adrs [1];
679+ $targ = $adrs [0] unless defined $targ ;
680+ $targ = maxline() unless defined $targ ;
681+
682+ if (defined $args [0]) {
683+ return E_FNAME unless (length $args [0]);
684+ if ($args [0] =~ s /\A\! // ) {
685+ $do_pipe = 1;
686+ $fh = init_pipe($args [0]);
687+ return E_OPEN unless $fh ;
688+ }
689+ $filename = $args [0];
690+ } elsif (defined $RememberedFilename ) {
691+ $filename = $RememberedFilename ;
692+ } else {
693+ return E_NOFILE;
694+ }
695+
696+ unless ($do_pipe ) {
697+ $fh = open_file_ro($filename );
698+ return E_OPEN unless $fh ;
699+ }
700+ @tmp_lines = readin_lines($fh , 0);
701+ $chars = 0;
702+ foreach (@tmp_lines ) {
703+ $chars += length ;
704+ }
705+ unless (close $fh ) {
706+ warn " $filename : $! \n " ;
707+ return E_CLOSE;
708+ }
709+ print " $chars \n " unless $Scripted ;
710+ return unless @tmp_lines ; # nothing to add
711+
712+ splice @lines , $targ + 1, 0, @tmp_lines ;
713+ $CurrentLineNum = $targ + scalar (@tmp_lines );
714+
715+ $NeedToSave = 1;
716+ $UserHasBeenWarned = 0;
717+ return ;
718+ }
681719
682720#
683721# Read in the named file
@@ -687,36 +725,24 @@ sub edWrite {
687725# 1 - success
688726
689727sub edEdit {
690- my ( $QuestionsMode , $InsertMode ) = @_ ;
728+ my $QuestionsMode = shift ;
691729 my (@tmp_lines , $chars , $fh , $filename );
692730
693- if ($InsertMode ) {
694- if (defined $adrs [1]) {
695- $adrs [0] = $adrs [1];
696- }
697- if (!defined ($adrs [0])) {
698- $adrs [0] = maxline();
699- }
700- } else {
701- if (defined ($adrs [0]) or defined ($adrs [1])) {
702- return E_ADDREXT;
703- }
704- if ($NeedToSave && $QuestionsMode && !$UserHasBeenWarned ) {
705- $UserHasBeenWarned = 1;
706- return E_UNSAVED;
707- }
731+ return E_ADDREXT if defined ($adrs [0]) or defined ($adrs [1]);
732+ if ($NeedToSave && $QuestionsMode && !$UserHasBeenWarned ) {
733+ $UserHasBeenWarned = 1;
734+ return E_UNSAVED;
708735 }
709-
710736 my $do_pipe = 0;
711737 if (defined $args [0]) {
712738 return E_FNAME unless (length $args [0]);
713739 if ($args [0] =~ s /\A\! // ) {
714740 $do_pipe = 1;
741+ $fh = init_pipe($args [0]);
742+ return E_OPEN unless $fh ;
743+ } else {
744+ $filename = $RememberedFilename = $args [0];
715745 }
716- if (!$InsertMode && !$do_pipe ) {
717- $RememberedFilename = $args [0];
718- }
719- $filename = $args [0];
720746 } elsif (defined $RememberedFilename ) {
721747 $filename = $RememberedFilename ;
722748 } else {
@@ -725,61 +751,67 @@ sub edEdit {
725751 return ;
726752 }
727753
728- if ($do_pipe ) {
729- return unless (open $fh , " $filename |" ); # no error
730- } else {
731- if (-d $filename ) {
732- warn " $filename : is a directory\n " ;
733- return E_READ;
734- }
735- unless (open $fh , ' <' , $filename ) {
736- warn " $filename : $! \n " ;
737- return E_OPEN;
738- }
754+ unless ($do_pipe ) {
755+ $fh = open_file_ro($filename );
756+ return E_OPEN unless $fh ;
739757 }
758+ @tmp_lines = readin_lines($fh , 0);
740759 $chars = 0;
741- while (<$fh >) {
742- push @tmp_lines , $_ ;
760+ foreach (@tmp_lines ) {
743761 $chars += length ;
744762 }
745763 unless (close $fh ) {
746764 warn " $filename : $! \n " ;
747765 return E_CLOSE;
748766 }
749- if ($chars == 0) {
750- $UserHasBeenWarned = 0;
751- $CurrentLineNum = 0;
752- @lines = (0);
753- print " 0\n " unless $Scripted ;
767+ print " $chars \n " unless $Scripted ;
768+
769+ @lines = (undef , @tmp_lines ); # tmp_lines can be empty
770+ $CurrentLineNum = maxline();
771+ $NeedToSave = $UserHasBeenWarned = 0;
772+ return ;
773+ }
774+
775+ sub init_pipe {
776+ my $cmd = shift ;
777+ return if $cmd =~ m /\0 / ;
778+ return unless $cmd =~ m /\S / ;
779+ $cmd =~ s / (\A\s +)|(\s +\z )// g ;
780+ my @arglist = quotewords(' \s+' , 0, $cmd );
781+ my $fh ;
782+ unless (open $fh , ' -|' , @arglist ) {
783+ warn " open: $! \n " ;
754784 return ;
755785 }
756- if (substr ($tmp_lines [-1], -1, 1) ne " \n " ) {
757- $tmp_lines [-1] .= " \n " ;
758- $chars ++;
786+ return $fh ;
787+ }
788+
789+ sub readin_lines {
790+ my ($fh , $dot ) = @_ ;
791+ my @tmp ;
792+ while (<$fh >) {
793+ last if $dot && m /\A\.\Z / ;
794+ push @tmp , $_ ;
795+ }
796+ if (@tmp && substr ($tmp [-1], -1, 1) ne " \n " ) {
797+ $tmp [-1] .= " \n " ;
759798 print " Newline appended\n " ;
760799 }
800+ return @tmp ;
801+ }
761802
762- # now that we've got it, figure out what to do with it
763-
764- if ($InsertMode ) {
765- if (maxline() != 0 && $adrs [0] == maxline()) {
766- push (@lines ,@tmp_lines );
767- } elsif ($adrs [0] == 0) {
768- splice @lines , 1, 0, @tmp_lines ;
769- } else {
770- splice @lines , $adrs [0] + 1, 0, @tmp_lines ;
771- }
772- $CurrentLineNum = $adrs [0] + scalar (@tmp_lines );
773- $NeedToSave = 1;
774- } else {
775- @lines = (undef , @tmp_lines );
776- $NeedToSave = 0;
777- $CurrentLineNum = maxline();
803+ sub open_file_ro {
804+ my $path = shift ;
805+ my $fh ;
806+ if (-d $path ) {
807+ warn " $path : is a directory\n " ;
808+ return ;
778809 }
779-
780- $UserHasBeenWarned = 0;
781- print " $chars \n " unless $Scripted ;
782- return ;
810+ unless (open $fh , ' <' , $path ) {
811+ warn " $path : $! \n " ;
812+ return ;
813+ }
814+ return $fh ;
783815}
784816
785817#
@@ -788,7 +820,6 @@ sub edEdit {
788820
789821sub edInsert {
790822 my $append = shift ;
791- my (@tmp_lines );
792823
793824 return E_ARGEXT if defined $args [0];
794825
@@ -799,11 +830,7 @@ sub edInsert {
799830 $adrs [0] = $CurrentLineNum ;
800831 }
801832
802- # suck the text into a temp array
803- while (<>) {
804- last if (/ ^\. $ / );
805- push (@tmp_lines ,$_ );
806- }
833+ my @tmp_lines = readin_lines(*STDIN , 1);
807834 return unless (@tmp_lines ); # no change
808835
809836 my $src = $adrs [0];
0 commit comments