tvi: specifying yank buffer for d, c, y, and p - neatvi - [fork] simple vi-type editor with UTF-8 support
(HTM) git clone git://src.adamsgaard.dk/neatvi
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 6e9f030b017fe128151501d6c0bad0c6e72a8c73
(DIR) parent d7772d9c05727a0892b134ed83bd2f834a039fa6
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
Date: Fri, 15 May 2015 10:18:52 +0430
vi: specifying yank buffer for d, c, y, and p
Diffstat:
M vi.c | 211 +++++++++++++++++--------------
1 file changed, 117 insertions(+), 94 deletions(-)
---
(DIR) diff --git a/vi.c b/vi.c
t@@ -26,6 +26,8 @@ static char vi_findlast[256]; /* the last searched keyword */
static int vi_finddir; /* the last search direction */
static char vi_charlast[8]; /* the last character searched via f, t, F, or T */
static int vi_charcmd; /* the character finding command */
+static int vi_arg1, vi_arg2; /* the first and second arguments */
+static int vi_ybuf; /* current yank buffer */
static void vi_draw(void)
{
t@@ -60,18 +62,27 @@ static char *vi_char(void)
return TK_INT(key) ? NULL : led_keymap(key);
}
+static int vi_yankbuf(void)
+{
+ int c = vi_read();
+ if (c == '"')
+ return vi_read();
+ vi_back(c);
+ return 0;
+}
+
static int vi_prefix(void)
{
- int pre = 0;
+ int n = 0;
int c = vi_read();
if ((c >= '1' && c <= '9')) {
while (isdigit(c)) {
- pre = pre * 10 + c - '0';
+ n = n * 10 + c - '0';
c = vi_read();
}
}
vi_back(c);
- return pre;
+ return n;
}
static int lbuf_lnnext(struct lbuf *lb, int *r, int *c, int dir)
t@@ -271,21 +282,21 @@ static int lbuf_wordend(struct lbuf *lb, int *row, int *col, int big, int dir)
}
/* read a line motion */
-static int vi_motionln(int *row, int cmd, int pre1, int pre2)
+static int vi_motionln(int *row, int cmd)
{
- int pre = (pre1 ? pre1 : 1) * (pre2 ? pre2 : 1);
+ int cnt = (vi_arg1 ? vi_arg1 : 1) * (vi_arg2 ? vi_arg2 : 1);
int c = vi_read();
int mark;
switch (c) {
case '\n':
case '+':
- *row = MIN(*row + pre, lbuf_len(xb) - 1);
+ *row = MIN(*row + cnt, lbuf_len(xb) - 1);
break;
case '-':
- *row = MAX(*row - pre, 0);
+ *row = MAX(*row - cnt, 0);
break;
case '_':
- *row = MIN(*row + pre - 1, lbuf_len(xb) - 1);
+ *row = MIN(*row + cnt - 1, lbuf_len(xb) - 1);
break;
case '\'':
if ((mark = vi_read()) > 0 && (isalpha(mark) || mark == '\''))
t@@ -293,23 +304,23 @@ static int vi_motionln(int *row, int cmd, int pre1, int pre2)
*row = lbuf_markpos(xb, mark);
break;
case 'j':
- *row = MIN(*row + pre, lbuf_len(xb) - 1);
+ *row = MIN(*row + cnt, lbuf_len(xb) - 1);
break;
case 'k':
- *row = MAX(*row - pre, 0);
+ *row = MAX(*row - cnt, 0);
break;
case 'G':
- *row = (pre1 || pre2) ? pre - 1 : lbuf_len(xb) - 1;
+ *row = (vi_arg1 || vi_arg2) ? cnt - 1 : lbuf_len(xb) - 1;
break;
case 'H':
if (lbuf_len(xb))
- *row = MIN(xtop + pre - 1, lbuf_len(xb) - 1);
+ *row = MIN(xtop + cnt - 1, lbuf_len(xb) - 1);
else
*row = 0;
break;
case 'L':
if (lbuf_len(xb))
- *row = MIN(xtop + xrows - 1 - pre + 1, lbuf_len(xb) - 1);
+ *row = MIN(xtop + xrows - 1 - cnt + 1, lbuf_len(xb) - 1);
else
*row = 0;
break;
t@@ -321,7 +332,7 @@ static int vi_motionln(int *row, int cmd, int pre1, int pre2)
break;
default:
if (c == cmd) {
- *row = MIN(*row + pre - 1, lbuf_len(xb) - 1);
+ *row = MIN(*row + cnt - 1, lbuf_len(xb) - 1);
break;
}
vi_back(c);
t@@ -331,92 +342,92 @@ static int vi_motionln(int *row, int cmd, int pre1, int pre2)
}
/* read a motion */
-static int vi_motion(int *row, int *col, int pre1, int pre2)
+static int vi_motion(int *row, int *col)
{
- int pre = (pre1 ? pre1 : 1) * (pre2 ? pre2 : 1);
+ int cnt = (vi_arg1 ? vi_arg1 : 1) * (vi_arg2 ? vi_arg2 : 1);
char *ln = lbuf_get(xb, *row);
int dir = dir_context(ln ? ln : "");
char *cs;
int mv;
int i;
- if ((mv = vi_motionln(row, 0, pre1, pre2))) {
+ if ((mv = vi_motionln(row, 0))) {
*col = -1;
return mv;
}
mv = vi_read();
switch (mv) {
case ' ':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_lnnext(xb, row, col, 1))
break;
break;
case 'f':
if ((cs = vi_char()))
- if (lbuf_findchar(xb, row, col, cs, mv, pre))
+ if (lbuf_findchar(xb, row, col, cs, mv, cnt))
return -1;
break;
case 'F':
if ((cs = vi_char()))
- if (lbuf_findchar(xb, row, col, cs, mv, pre))
+ if (lbuf_findchar(xb, row, col, cs, mv, cnt))
return -1;
break;
case ';':
if (vi_charlast[0])
- if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, pre))
+ if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, cnt))
return -1;
break;
case ',':
if (vi_charlast[0])
- if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, -pre))
+ if (lbuf_findchar(xb, row, col, vi_charlast, vi_charcmd, -cnt))
return -1;
break;
case 'h':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_lnnext(xb, row, col, -1 * dir))
break;
break;
case 'l':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_lnnext(xb, row, col, +1 * dir))
break;
break;
case 't':
if ((cs = vi_char()))
- if (lbuf_findchar(xb, row, col, cs, mv, pre))
+ if (lbuf_findchar(xb, row, col, cs, mv, cnt))
return -1;
break;
case 'T':
if ((cs = vi_char()))
- if (lbuf_findchar(xb, row, col, cs, mv, pre))
+ if (lbuf_findchar(xb, row, col, cs, mv, cnt))
return -1;
break;
case 'B':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordend(xb, row, col, 1, -1))
break;
break;
case 'E':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordend(xb, row, col, 1, +1))
break;
break;
case 'W':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordbeg(xb, row, col, 1, +1))
break;
break;
case 'b':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordend(xb, row, col, 0, -1))
break;
break;
case 'e':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordend(xb, row, col, 0, +1))
break;
break;
case 'w':
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_wordbeg(xb, row, col, 0, +1))
break;
break;
t@@ -431,27 +442,27 @@ static int vi_motion(int *row, int *col, int pre1, int pre2)
lbuf_lnnext(xb, row, col, -1);
break;
case '|':
- *col = pre - 1;
+ *col = cnt - 1;
break;
case '/':
- if (vi_search(mv, pre, row, col))
+ if (vi_search(mv, cnt, row, col))
return -1;
break;
case '?':
- if (vi_search(mv, pre, row, col))
+ if (vi_search(mv, cnt, row, col))
return -1;
break;
case 'n':
- if (vi_search(mv, pre, row, col))
+ if (vi_search(mv, cnt, row, col))
return -1;
break;
case 'N':
- if (vi_search(mv, pre, row, col))
+ if (vi_search(mv, cnt, row, col))
return -1;
break;
case 127:
case TK_CTL('h'):
- for (i = 0; i < pre; i++)
+ for (i = 0; i < cnt; i++)
if (lbuf_lnnext(xb, row, col, -1))
break;
break;
t@@ -534,7 +545,7 @@ static void vi_yank(int r1, int c1, int r2, int c2, int lnmode, int closed)
int l1, l2;
vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed);
region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2);
- reg_put(0, region, lnmode);
+ reg_put(vi_ybuf, region, lnmode);
free(region);
xrow = r1;
xcol = lnmode ? xcol : c1;
t@@ -547,7 +558,7 @@ static void vi_delete(int r1, int c1, int r2, int c2, int lnmode, int closed)
int l1, l2;
vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed);
region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2);
- reg_put(0, region, lnmode);
+ reg_put(vi_ybuf, region, lnmode);
free(region);
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1);
t@@ -640,7 +651,7 @@ static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
char *pref, *post;
vi_commandregion(&r1, &r2, &c1, &c2, &l1, &l2, closed);
region = lbuf_region(xb, r1, lnmode ? 0 : l1, r2, lnmode ? -1 : l2);
- reg_put(0, region, lnmode);
+ reg_put(vi_ybuf, region, lnmode);
free(region);
pref = lnmode ? vi_indents(lbuf_get(xb, r1)) : uc_sub(lbuf_get(xb, r1), 0, l1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1);
t@@ -656,23 +667,24 @@ static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
free(post);
}
-static void vc_motion(int cmd, int pre1)
+static int vc_motion(int cmd)
{
int r1 = xrow, r2 = xrow; /* region rows */
int c1 = xcol, c2 = xcol; /* visual region columns */
int lnmode = 0; /* line-based region */
int closed = 1; /* include the last character */
int mv;
- int pre2 = vi_prefix();
- if (pre2 < 0)
- return;
- if ((mv = vi_motionln(&r2, cmd, pre1, pre2))) {
+ vi_arg2 = vi_prefix();
+ if (vi_arg2 < 0)
+ return 1;
+ if ((mv = vi_motionln(&r2, cmd))) {
c2 = -1;
- } else if (!(mv = vi_motion(&r2, &c2, pre1, pre2))) {
- return;
+ } else if (!(mv = vi_motion(&r2, &c2))) {
+ vi_read();
+ return 1;
}
if (mv < 0)
- return;
+ return 1;
if (!strchr("fFtTeE$", mv))
closed = 0;
lnmode = c2 < 0;
t@@ -686,9 +698,10 @@ static void vc_motion(int cmd, int pre1)
vi_delete(r1, c1, r2, c2, lnmode, closed);
if (cmd == 'c')
vi_change(r1, c1, r2, c2, lnmode, closed);
+ return 0;
}
-static void vc_insert(int cmd)
+static int vc_insert(int cmd)
{
char *pref, *post;
char *ln = lbuf_get(xb, xrow);
t@@ -721,18 +734,20 @@ static void vc_insert(int cmd)
}
free(pref);
free(post);
+ return !rep;
}
-static void vc_put(int cmd, int cnt)
+static int vc_put(int cmd)
{
+ int cnt = MAX(1, vi_arg1);
int lnmode;
char *ln;
- char *buf = reg_get(0, &lnmode);
+ char *buf = reg_get(vi_ybuf, &lnmode);
struct sbuf *sb;
int off;
int i;
if (!buf)
- return;
+ return 1;
ln = lnmode ? NULL : lbuf_get(xb, xrow);
off = ln ? vi_insertionoffset(ln, xcol, cmd == 'P') : 0;
if (cmd == 'p' && !ln)
t@@ -750,11 +765,13 @@ static void vc_put(int cmd, int cnt)
sbuf_str(sb, s);
free(s);
}
+ if (!ln && !lbuf_len(xb))
+ lbuf_put(xb, 0, "\n");
if (ln)
lbuf_rm(xb, xrow, xrow + 1);
lbuf_put(xb, xrow, sbuf_buf(sb));
sbuf_free(sb);
-
+ return 0;
}
static int join_spaces(char *prev, char *next)
t@@ -767,16 +784,16 @@ static int join_spaces(char *prev, char *next)
return prev[prevlen - 1] == '.' ? 2 : 1;
}
-static void vc_join(int arg)
+static int vc_join(void)
{
struct sbuf *sb;
- int cnt = arg <= 1 ? 2 : arg;
+ int cnt = vi_arg1 <= 1 ? 2 : vi_arg1;
int beg = xrow;
int end = xrow + cnt;
int off = 0;
int i;
if (!lbuf_get(xb, beg) || !lbuf_get(xb, end - 1))
- return;
+ return 1;
sb = sbuf_make();
for (i = beg; i < end; i++) {
char *ln = lbuf_get(xb, i);
t@@ -796,6 +813,7 @@ static void vc_join(int arg)
lbuf_put(xb, beg, sbuf_buf(sb));
xcol = ren_pos(sbuf_buf(sb), off);
sbuf_free(sb);
+ return 0;
}
static int vi_scrollforeward(int cnt)
t@@ -824,9 +842,9 @@ static void vi_status(void)
led_print(stat, xrows);
}
-static int vc_replace(int arg)
+static int vc_replace(void)
{
- int cnt = MAX(1, arg);
+ int cnt = MAX(1, vi_arg1);
char *cs = vi_char();
char *ln = lbuf_get(xb, xrow);
struct sbuf *sb;
t@@ -872,10 +890,13 @@ static void vi(void)
int redraw = 0;
int orow = xrow;
int ocol = xcol;
- int pre1, mv;
- if ((pre1 = vi_prefix()) < 0)
- continue;
- mv = vi_motion(&xrow, &xcol, pre1, 0);
+ int mv, n;
+ vi_arg2 = 0;
+ vi_ybuf = vi_yankbuf();
+ vi_arg1 = vi_prefix();
+ if (!vi_ybuf)
+ vi_ybuf = vi_yankbuf();
+ mv = vi_motion(&xrow, &xcol);
if (mv > 0) {
if (strchr("\'GHML/?", mv))
lbuf_mark(xb, '\'', orow);
t@@ -892,24 +913,24 @@ static void vi(void)
continue;
switch (c) {
case TK_CTL('b'):
- if (vi_scrollbackward((pre1 ? pre1 : 1) * (xrows - 1)))
+ if (vi_scrollbackward(MAX(1, vi_arg1) * (xrows - 1)))
break;
lbuf_postindents(xb, &xrow, &xcol);
redraw = 1;
break;
case TK_CTL('f'):
- if (vi_scrollforeward((pre1 ? pre1 : 1) * (xrows - 1)))
+ if (vi_scrollforeward(MAX(1, vi_arg1) * (xrows - 1)))
break;
lbuf_postindents(xb, &xrow, &xcol);
redraw = 1;
break;
case TK_CTL('e'):
- if (vi_scrollforeward((pre1 ? pre1 : 1)))
+ if (vi_scrollforeward(MAX(1, vi_arg1)))
break;
redraw = 1;
break;
case TK_CTL('y'):
- if (vi_scrollbackward((pre1 ? pre1 : 1)))
+ if (vi_scrollbackward(MAX(1, vi_arg1)))
break;
redraw = 1;
break;
t@@ -943,8 +964,8 @@ static void vi(void)
case 'c':
case 'd':
case 'y':
- vc_motion(c, pre1);
- redraw = 1;
+ if (!vc_motion(c))
+ redraw = 1;
break;
case 'i':
case 'I':
t@@ -952,12 +973,12 @@ static void vi(void)
case 'A':
case 'o':
case 'O':
- vc_insert(c);
- redraw = 1;
+ if (!vc_insert(c))
+ redraw = 1;
break;
case 'J':
- vc_join(pre1);
- redraw = 1;
+ if (!vc_join())
+ redraw = 1;
break;
case 'm':
if ((mark = vi_read()) > 0 && isalpha(mark))
t@@ -965,20 +986,22 @@ static void vi(void)
break;
case 'p':
case 'P':
- vc_put(c, pre1);
- redraw = 1;
+ if (!vc_put(c))
+ redraw = 1;
break;
case 'z':
z = vi_read();
switch (z) {
case '\n':
- xtop = pre1 ? pre1 : xrow;
+ xtop = vi_arg1 ? vi_arg1 : xrow;
break;
case '.':
- xtop = MAX(0, (pre1 ? pre1 : xrow) - xrows / 2);
+ n = vi_arg1 ? vi_arg1 : xrow;
+ xtop = MAX(0, n - xrows / 2);
break;
case '-':
- xtop = MAX(0, (pre1 ? pre1 : xrow) - xrows + 1);
+ n = vi_arg1 ? vi_arg1 : xrow;
+ xtop = MAX(0, n - xrows + 1);
break;
case 'l':
case 'r':
t@@ -991,42 +1014,42 @@ static void vi(void)
break;
case 'x':
vi_back(' ');
- vc_motion('d', pre1);
- redraw = 1;
+ if (!vc_motion('d'))
+ redraw = 1;
break;
case 'X':
vi_back(TK_CTL('h'));
- vc_motion('d', pre1);
- redraw = 1;
+ if (!vc_motion('d'))
+ redraw = 1;
break;
case 'C':
vi_back('$');
- vc_motion('c', pre1);
- redraw = 1;
+ if (!vc_motion('c'))
+ redraw = 1;
break;
case 'D':
vi_back('$');
- vc_motion('d', pre1);
- redraw = 1;
+ if (vc_motion('d'))
+ redraw = 1;
break;
case 'r':
- vc_replace(pre1);
- redraw = 1;
+ if (!vc_replace())
+ redraw = 1;
break;
case 's':
vi_back(' ');
- vc_motion('c', pre1);
- redraw = 1;
+ if (!vc_motion('c'))
+ redraw = 1;
break;
case 'S':
vi_back('c');
- vc_motion('c', pre1);
- redraw = 1;
+ if (!vc_motion('c'))
+ redraw = 1;
break;
case 'Y':
vi_back('y');
- vc_motion('y', pre1);
- redraw = 1;
+ if (!vc_motion('y'))
+ redraw = 1;
break;
default:
continue;