Download raw body.
Another vi(1) paste improvement
This improvement:
https://marc.info/?l=openbsd-cvs&m=175598284729256&w=2
https://github.com/lichray/nvi2/commit/95c6b23d2f8eb32858698bae46c71392f1d90562
paved the rode for another improvement.
Now that cursor movement doesn't affect count+paste anymore we can
modify where the cursor lands after character mode pasting safely and
indepenently. The interest in doing this is to circumvent the
inconvenience described here by Nils Ola Nilsson:
https://marc.info/?l=openbsd-tech&m=174551571311274&w=2
And, since now we're talking about vi(1), were we also have to consider
*line* mode pasting, where happens something analogous, as the following
example shows.
One <- First put your cursor here and hit '3yy'
Two
Three <- Then, put your cursor here and hit 'p' several times
consecutively (without manually repositioning the cursor
between each 'p'.)
The result:
One
Two
Three
One <- The cursor lands here the first time
One <- The cursor lands here the second time (and so on)
Two
Three
Two
Three
To test *cursor* mode pasting just yank some word (eg "Hello") with 'ye'
and hit 'p' several times. (In any case you can also repeat the command
with '.').
Now, apply the diff at bottom, perform again those tests and compare the
results. The results will speak for themselves.
Regarding *line* mode pasting there's another interesting comparison to
do. In a file where text reaches or surpasses the bottom of the window,
put the cursor in the last visible line and hit 'p'. With the new
behavior the buffer is scrolled automatically in the same action,
letting you see the whole text you pasted.
Where is the trick? As clearly explained in the comments I added to the
code, what the diff below does is to modify only the 'p' command to move
the cursor to the last character pasted in cursor mode pasting and to
the last line pasted in line mode pasting. 'P' preserves its current
behavior in both cases.
Index: common/put.c
===================================================================
RCS file: /cvs/src/usr.bin/vi/common/put.c,v
diff -u -p -r1.17 put.c
--- common/put.c 23 Aug 2025 21:02:10 -0000 1.17
+++ common/put.c 25 Aug 2025 06:10:17 -0000
@@ -70,9 +70,6 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MAR
* historic vi couldn't deal with a file that had no lines in it. This
* implementation treats that as a bug, and does not retain the blank
* line.
- *
- * Historical practice is that the cursor ends at the first character
- * in the file.
*/
if (cp->lno == 1) {
if (db_last(sp, &lno))
@@ -86,7 +83,18 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MAR
return (1);
tp = TAILQ_FIRST(&cbp->textq);
}
- rp->lno = 1;
+
+ /*
+ * Historical practice was that the cursor ends at the
+ * first character in the file. This is preserved only
+ * for the 'P' command. With 'p', now the cursor is
+ * moved to the last line pasted.
+ */
+ if (append)
+ rp->lno = lno;
+ else
+ rp->lno = 1;
+
rp->cno = 0;
return (0);
}
@@ -104,7 +112,15 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MAR
return (1);
tp = TAILQ_FIRST(&cbp->textq);
}
+
+ /*
+ * With the 'p' command move the cursor to the last line
+ * pasted.
+ */
+ if (append)
+ rp->lno = lno;
rp->cno = 0;
+
(void)nonblank(sp, rp->lno, &rp->cno);
return (0);
}
@@ -158,9 +174,19 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MAR
* of vi, character mode puts that cross line boundaries leave the
* cursor on the first character. Nvi implements the System III/V
* behavior, and expect POSIX.2 to do so as well.
+ *
+ * Update (Aug 24, 2025): Now, with the 'p' command, the cursor
+ * moves to the last character of the pasted string. The 'P'
+ * command hasn't been modified; the cursor still rests on the
+ * first character of the pasted string. This is convenient when
+ * running 'p' or 'P' consecutive times or by hitting '.' (dot).
*/
rp->lno = lno;
- rp->cno = len == 0 ? 0 : sp->cno + (append && tp->len ? 1 : 0);
+ if (append == 0)
+ rp->cno = len == 0 ? 0 : sp->cno;
+ else
+ rp->cno = len == 0 ? (tp->len * cnt) - 1 : sp->cno +
+ append + (tp->len * cnt) - 1;
/*
* If no more lines in the CB, append the rest of the original
--
Walter
Another vi(1) paste improvement