Skip to content

Commit

Permalink
ed: better relative addresses (#902)
Browse files Browse the repository at this point in the history
* The initial implementation of relative addresses was too limited
* GNU and OpenBSD ed allow repeated +n, mixed +n and --++, as well as basing address from dot, dollar or a marked address
* tests..

++1= invalid: ambiguous
+=   current +1
.+=  current + 1
+1=  current + 1
.+1= current + 1
.+3++=   current + 5: ++ follows +n
$---=   end - 3
$-3=   end - 3
$-3+3=   end: repeated +n
'x-5,'x+5nl      list 5 lines of context around marked line x
  • Loading branch information
mknos authored Jan 3, 2025
1 parent 79a9162 commit 9f22ceb
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions bin/ed
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ my $NO_QUESTIONS_MODE = 0;
my $PRINT_NUM = 1;
my $PRINT_BIN = 2;

our $VERSION = '0.23';
our $VERSION = '0.24';

my @ESC = (
'\\000', '\\001', '\\002', '\\003', '\\004', '\\005', '\\006', '\\a',
Expand Down Expand Up @@ -974,18 +974,10 @@ sub edParse {

sub getAddr {
my $n;
if (s/\A([\-\+])([0-9]+)//) { # '+1' or '-1'
my $is_neg = $1 eq '-';
my $x = $2;
$x = -$x if $is_neg;
$n = $CurrentLineNum + $x;
} elsif (s/\A([\-\^\+]+)//) { # '++--' == current+0
$n = $CurrentLineNum;
foreach my $c (split //, $1) {
$n += $c eq '+' ? 1 : -1;
}
} elsif (s/\A\'([a-z])//) {
$n = exists $marks{$1} ? $marks{$1} : A_NOMARK;
if (s/\A\'([a-z])//) {
my $letter = $1;
return A_NOMARK unless exists $marks{$letter};
$n = $marks{$letter};
} elsif (s/\A([0-9]+)//) { # '10' == 10
$n = $1;
} elsif (s/\A\.//) { # '.' == current line
Expand All @@ -1001,7 +993,20 @@ sub getAddr {
$re = $SearchPat;
}
$n = edSearch($re, $delim eq '?');
$n = A_NOMATCH unless $n;
return A_NOMATCH unless $n;
}
while (s/\A([\-\+])([0-9]+)//) { # '+1' or '-1'
$n = $CurrentLineNum unless defined $n;
my $is_neg = $1 eq '-';
my $x = $2;
$x = -$x if $is_neg;
$n += $x;
}
while (s/\A([\-\^\+]+)//) { # '++--' == current+0
$n = $CurrentLineNum unless defined $n;
foreach my $c (split //, $1) {
$n += $c eq '+' ? 1 : -1;
}
}
if (defined $n) {
return A_RANGE if $n < 0 || $n > maxline();
Expand Down

0 comments on commit 9f22ceb

Please sign in to comment.