Bug 272487

Summary: vi/nvi: :t wrongly adjusts current-line in the context of a :g command
Product: Base System Reporter: Tim Chase <freebsd>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Only Me CC: bapt, emaste, freebsd, leres
Priority: ---    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description Tim Chase 2023-07-13 14:36:51 UTC
With the following file:

    $ cat <<EOF > test.txt

    blank line above
    pattern line one
    pattern line two
    EOF

The aim was to copy that first blank line before each of the /pattern/
lines.  This works fine in ed(1):

    $ ed test.txt
    52
    g/^pattern/1t-
    ,p

    blank line above

    pattern line one

    pattern line two

However, when I use either of these commands in vi:

    :g/^pattern/1t-
    :g/^pattern/1t.-

it errors with

    Usage: [line [,line]] t line [flags].

Additionally, if I explicitly spell out the relative line count
with either

    :g/^pattern/1t-1
    :g/^pattern/1t.-1

it errors with

    Reference to a line number less than 0

It seems to set the current-line aspect with the absolute line-number
of "1" before processing the relative "-" or ".-" (which should be
relative to the :g/ match)

If I am on one of the /pattern/ lines and issue the same command:

    3G
    :1t-

it works as expected, copying the first/blank line before the current
line.

And strangely, if I do something with the line beforehand (printing
it, showing the line-number with `=`, etc), it works too:

    :g/^pattern/.=|1t-

Similarly, if I put the blank line at the bottom of the file:

    :1m$
    :g/^pattern/$t-

it also works as expected.  And, FWIW, the original/problematic
command works fine in vim.

Seems to be an `nvi(1)` thing, presenting in both FreeBSD & OpenBSD
Comment 1 Tim Chase 2023-07-26 12:29:26 UTC
Poking around further at this, if I add a single space (0x20) after the "-", changing

    :g/pattern/1t-

into

    :g/pattern/1t-{space}

it works as expected.  This seems to suggest some sort of parsing or off-by-one issue?