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;
                                }