tvi: x, X, C, D, s, S, and Y commands - 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 c3ab582a5343baa7caccc526f432318eca7e9eb5
(DIR) parent 1dc67eff887a162e76d774b367ab3648e5876e17
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
Date: Thu, 7 May 2015 19:08:26 +0430
vi: x, X, C, D, s, S, and Y commands
Diffstat:
M vi.c | 179 +++++++++++++++++++++----------
1 file changed, 122 insertions(+), 57 deletions(-)
---
(DIR) diff --git a/vi.c b/vi.c
t@@ -372,21 +372,94 @@ static char *lbuf_region(struct lbuf *lb, int r1, int l1, int r2, int l2)
return sbuf_done(sb);
}
-static void vc_motion(int c, int pre1)
+static void vi_commandregion(int *r1, int *r2, int *c1, int *c2, int *l1, int *l2, int closed)
+{
+ if (*r2 < *r1 || (*r2 == *r1 && ren_cmp(lbuf_get(xb, *r1), *c1, *c2) > 0)) {
+ swap(r1, r2);
+ swap(c1, c2);
+ }
+ *l1 = lbuf_get(xb, *r1) ? ren_insertionoffset(lbuf_get(xb, *r1), *c1, 1) : 0;
+ *l2 = lbuf_get(xb, *r2) ? ren_insertionoffset(lbuf_get(xb, *r2), *c2, !closed) : 0;
+ if (*r1 == *r2 && *l2 < *l1)
+ swap(l1, l2);
+}
+
+static void vi_yank(int r1, int c1, int r2, int c2, int lnmode, int closed)
+{
+ char *region;
+ 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);
+ free(region);
+ xrow = r1;
+ xcol = lnmode ? xcol : c1;
+}
+
+static void vi_delete(int r1, int c1, int r2, int c2, int lnmode, int closed)
+{
+ char *pref, *post;
+ char *region;
+ 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);
+ 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);
+ lbuf_rm(xb, r1, r2 + 1);
+ if (!lnmode) {
+ struct sbuf *sb = sbuf_make();
+ sbuf_str(sb, pref);
+ sbuf_str(sb, post);
+ lbuf_put(xb, r1, sbuf_buf(sb));
+ sbuf_free(sb);
+ }
+ xrow = r1;
+ xcol = c1;
+ if (lnmode)
+ lbuf_postindents(xb, &xrow, &xcol);
+ free(pref);
+ free(post);
+}
+
+static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
+{
+ char *region;
+ int l1, l2;
+ int row, col;
+ char *rep;
+ 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);
+ 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);
+ rep = led_input(pref, post, &row, &col);
+ if (rep) {
+ lbuf_rm(xb, r1, r2 + 1);
+ lbuf_put(xb, r1, rep);
+ xrow = r1 + row;
+ xcol = col;
+ free(rep);
+ }
+ free(pref);
+ free(post);
+}
+
+static void vc_motion(int cmd, int pre1)
{
int r1 = xrow, r2 = xrow; /* region rows */
int c1 = xcol, c2 = xcol; /* visual region columns */
- int l1, l2; /* logical region columns */
- int ln = 0; /* line-based region */
+ int lnmode = 0; /* line-based region */
int closed = 1; /* include the last character */
- int mv, i;
- char *pref = NULL;
- char *post = NULL;
+ int mv;
int pre2 = vi_prefix();
if (pre2 < 0)
return;
- if (vi_motionln(&r2, c, pre1, pre2)) {
- ln = 1;
+ if (vi_motionln(&r2, cmd, pre1, pre2)) {
+ lnmode = 1;
lbuf_eol(xb, &r1, &c1, -1);
lbuf_eol(xb, &r2, &c2, +1);
} else if ((mv = vi_motion(&r2, &c2, pre1, pre2))) {
t@@ -395,55 +468,12 @@ static void vc_motion(int c, int pre1)
} else {
return;
}
- /* make sure the first position is visually before the second */
- if (r2 < r1 || (r2 == r1 && ren_cmp(lbuf_get(xb, r1), c1, c2) > 0)) {
- swap(&r1, &r2);
- swap(&c1, &c2);
- }
- if (c == 'y') { /* adjusting cursor position */
- xrow = r1;
- xcol = ln ? xcol : c1;
- }
- for (i = 0; i < 2; i++) {
- l1 = ren_insertionoffset(lbuf_get(xb, r1), c1, 1);
- l2 = ren_insertionoffset(lbuf_get(xb, r2), c2, !closed);
- if (r1 == r2 && l2 < l1) /* offsets out of order */
- swap(&l1, &l2);
- }
- pref = ln ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1);
- post = ln ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1);
- if (c == 'c' || c == 'd' || c == 'y') {
- char *region = lbuf_region(xb, r1, ln ? 0 : l1, r2, ln ? -1 : l2);
- reg_put(0, region, ln);
- free(region);
- }
- if (c == 'c') {
- int row, col;
- char *rep = led_input(pref, post, &row, &col);
- if (rep) {
- lbuf_rm(xb, r1, r2 + 1);
- lbuf_put(xb, r1, rep);
- xrow = r1 + row;
- xcol = col;
- free(rep);
- }
- }
- if (c == 'd') {
- lbuf_rm(xb, r1, r2 + 1);
- if (!ln) {
- struct sbuf *sb = sbuf_make();
- sbuf_str(sb, pref);
- sbuf_str(sb, post);
- lbuf_put(xb, r1, sbuf_buf(sb));
- sbuf_free(sb);
- }
- xrow = r1;
- xcol = c1;
- if (ln)
- lbuf_postindents(xb, &xrow, &xcol);
- }
- free(pref);
- free(post);
+ if (cmd == 'y')
+ vi_yank(r1, c1, r2, c2, lnmode, closed);
+ if (cmd == 'd')
+ vi_delete(r1, c1, r2, c2, lnmode, closed);
+ if (cmd == 'c')
+ vi_change(r1, c1, r2, c2, lnmode, closed);
}
static void vc_insert(int cmd)
t@@ -662,6 +692,41 @@ static void vi(void)
}
redraw = 1;
break;
+ case 'x':
+ vi_back(' ');
+ vc_motion('d', pre1);
+ redraw = 1;
+ break;
+ case 'X':
+ vi_back('h');
+ vc_motion('d', pre1);
+ redraw = 1;
+ break;
+ case 'C':
+ vi_back('$');
+ vc_motion('c', pre1);
+ redraw = 1;
+ break;
+ case 'D':
+ vi_back('$');
+ vc_motion('d', pre1);
+ redraw = 1;
+ break;
+ case 's':
+ vi_back(' ');
+ vc_motion('c', pre1);
+ redraw = 1;
+ break;
+ case 'S':
+ vi_back('c');
+ vc_motion('c', pre1);
+ redraw = 1;
+ break;
+ case 'Y':
+ vi_back('y');
+ vc_motion('y', pre1);
+ redraw = 1;
+ break;
default:
continue;
}