Skip to content

Commit 471b8fd

Browse files
authored
ed: implement repeat search for g// & v// (#787)
* Empty search pattern provided to g and v should be interpreted in the same way as for a basic search with //, i.e. repeat the previous search using saved pattern * I found this when testing against BSD version * test1: g//l ---> error: no previous pattern * test2: /t ---> find next /t/ and save search pattern * test3: g//n ---> run n command globally for lines matching saved pattern /t/ * test4: v//d ---> run d command for all lines not matching /t/
1 parent f1bf501 commit 471b8fd

File tree

1 file changed

+37
-21
lines changed

1 file changed

+37
-21
lines changed

bin/ed

+37-21
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ use Getopt::Std qw(getopts);
6363
use constant A_NOMATCH => -1;
6464
use constant A_NOPAT => -2;
6565
use constant A_ALL => -3;
66+
use constant A_PATTERN => -4;
6667

6768
use constant E_ADDREXT => 'unexpected address';
6869
use constant E_ADDRBAD => 'invalid address';
@@ -109,7 +110,7 @@ my $NO_QUESTIONS_MODE = 0;
109110
my $PRINT_NUM = 1;
110111
my $PRINT_BIN = 2;
111112

112-
our $VERSION = '0.12';
113+
our $VERSION = '0.13';
113114

114115
my @ESC = (
115116
'\\000', '\\001', '\\002', '\\003', '\\004', '\\005', '\\006', '\\a',
@@ -240,6 +241,9 @@ sub input {
240241
} elsif ($ad == A_NOPAT) {
241242
edWarn(E_NOPAT);
242243
return;
244+
} elsif ($ad == A_PATTERN) {
245+
edWarn(E_PATTERN);
246+
return;
243247
} elsif ($ad > maxline() || $ad < 0) {
244248
edWarn(E_ADDRBAD);
245249
return;
@@ -923,18 +927,19 @@ sub edParse {
923927
}
924928
if (s/\A([gv])\///) {
925929
my $invert = $1 eq 'v';
926-
my $i;
927-
my @chars = split //;
928-
my $lim = scalar @chars;
929-
for ($i = 0; $i < $lim; $i++) {
930-
my $j = $i - 1;
931-
$j = 0 if $j < 0;
932-
last if $chars[$i] eq '/' && $chars[$j] ne '\\';
930+
my $re = getRe('/', 1);
931+
unless (defined $re) {
932+
$adrs[0] = A_PATTERN;
933+
return 1;
934+
}
935+
if (length($re) == 0) {
936+
unless (defined $SearchPat) {
937+
$adrs[0] = A_NOPAT;
938+
return 1;
939+
}
940+
$re = $SearchPat;
933941
}
934-
return 0 if $i == $lim; # g/re/p needs trailing /
935-
my $pat = substr $_, 0, $i;
936-
$_ = substr $_, $i + 1;
937-
my @found = edSearchGlobal($pat, $invert);
942+
my @found = edSearchGlobal($re, $invert);
938943
return 1 unless @found; # nothing to do
939944
$isGlobal = 1;
940945
@adrs = @found;
@@ -972,19 +977,12 @@ sub getAddr {
972977
$n = maxline();
973978
} elsif (s/\A([\/\?])//) { # search: '/re/' or '?re?'
974979
my $delim = $1;
975-
my $i;
976-
my @chars = split //;
977-
for ($i = 0; $i < scalar(@chars); $i++) {
978-
my $j = $i - 1;
979-
$j = 0 if $j < 0;
980-
last if $chars[$i] eq $delim && $chars[$j] ne '\\';
981-
}
982-
my $re = substr $_, 0, $i;
980+
my $re = getRe($delim);
981+
$re = '' unless defined $re; # delim not needed
983982
if (length($re) == 0) {
984983
return A_NOPAT unless defined $SearchPat;
985984
$re = $SearchPat;
986985
}
987-
$_ = substr $_, $i + 1;
988986
if ($delim eq '/') {
989987
$n = edSearchForward($re);
990988
} else {
@@ -995,6 +993,23 @@ sub getAddr {
995993
return $n;
996994
}
997995

996+
sub getRe {
997+
my ($delim, $delimreq) = @_;
998+
my $i;
999+
my @chars = split //;
1000+
my $sz = scalar @chars;
1001+
1002+
for ($i = 0; $i < $sz; $i++) {
1003+
my $j = $i - 1;
1004+
$j = 0 if $j < 0;
1005+
last if $chars[$i] eq $delim && $chars[$j] ne '\\';
1006+
}
1007+
return if $delimreq && $i == $sz;
1008+
my $re = substr $_, 0, $i;
1009+
$_ = substr $_, $i + 1;
1010+
return $re;
1011+
}
1012+
9981013
#
9991014
# Search forward for a pattern...wrap if not found
10001015
#
@@ -1065,6 +1080,7 @@ sub edSearchGlobal {
10651080
}
10661081
$end = $adrs[1];
10671082
}
1083+
$SearchPat = $pattern;
10681084
my @found;
10691085
for my $i ($start .. $end) {
10701086
my $match;

0 commit comments

Comments
 (0)