tvi: repeat and execute 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 901e0cd396e087f435fa96b51196d01d0f94ca18 (DIR) parent 04a3edea64e70aae164a0550acaf5bf18ccac472 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir> Date: Tue, 2 Jun 2015 19:37:04 +0430 vi: repeat and execute commands Diffstat: M term.c | 45 +++++++++++++++++++++++++------ M vi.c | 39 +++++++++++++++++++++++++++++++ M vi.h | 2 ++ 3 files changed, 78 insertions(+), 8 deletions(-) --- (DIR) diff --git a/term.c b/term.c t@@ -109,17 +109,46 @@ int term_cols(void) return cols; } +static char ibuf[4096]; /* input character buffer */ +static char icmd[4096]; /* read after the last term_cmd() */ +static int ibuf_pos, ibuf_cnt; /* ibuf[] position and length */ +static int icmd_pos; /* icmd[] position */ + +/* read s before reading from the terminal */ +void term_push(char *s, int n) +{ + n = MIN(n, sizeof(ibuf) - ibuf_cnt); + memcpy(ibuf + ibuf_cnt, s, n); + ibuf_cnt += n; +} + +/* return a static buffer containing inputs read since the last term_cmd() */ +char *term_cmd(int *n) +{ + *n = icmd_pos; + icmd_pos = 0; + return icmd; +} + int term_read(int ms) { struct pollfd ufds[1]; - char b; - ufds[0].fd = 0; - ufds[0].events = POLLIN; - if (poll(ufds, 1, ms * 1000) <= 0) - return -1; - if (read(0, &b, 1) <= 0) - return -1; - return (unsigned char) b; + char n, c; + if (ibuf_pos >= ibuf_cnt) { + ufds[0].fd = 0; + ufds[0].events = POLLIN; + if (poll(ufds, 1, ms * 1000) <= 0) + return -1; + /* read a single input character */ + if ((n = read(0, ibuf, 1)) <= 0) + return -1; + ibuf_cnt = n; + ibuf_pos = 0; + } + c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1; + if (icmd_pos < sizeof(icmd)) + icmd[icmd_pos++] = c; + return c; } /* return a static string that changes text attributes from old to att */ (DIR) diff --git a/vi.c b/vi.c t@@ -907,6 +907,30 @@ static int vc_replace(void) return 0; } +static char rep_cmd[4096]; /* the last command */ +static int rep_len; + +static void vc_repeat(void) +{ + term_push(rep_cmd, rep_len); +} + +static void vc_execute(void) +{ + static int exec_buf; + int lnmode; + int c = vi_read(); + char *buf; + if (TK_INT(c)) + return; + if (c == '@') + c = exec_buf; + exec_buf = c; + buf = reg_get(exec_buf, &lnmode); + if (buf) + term_push(buf, strlen(buf)); +} + static void vi(void) { int xcol; t@@ -926,6 +950,7 @@ static void vi(void) int noff = ren_noeol(lbuf_get(xb, xrow), xoff); int otop = xtop; int mv, n; + term_cmd(&n); vi_arg2 = 0; vi_ybuf = vi_yankbuf(); vi_arg1 = vi_prefix(); t@@ -946,6 +971,7 @@ static void vi(void) if (mv == '|') xcol = vi_pcol; } else if (mv == 0) { + char *cmd; int c = vi_read(); int z, g; if (c <= 0) t@@ -1109,9 +1135,22 @@ static void vi(void) if (!vc_motion('~')) redraw = 1; break; + case '.': + vc_repeat(); + break; + case '@': + vc_execute(); + break; default: continue; } + cmd = term_cmd(&n); + if (strchr("!<>ACDIJOPRSXYacdioprsxy~", c)) { + if (n < sizeof(rep_cmd)) { + memcpy(rep_cmd, cmd, n); + rep_len = n; + } + } } if (xrow < 0 || xrow >= lbuf_len(xb)) xrow = lbuf_len(xb) ? lbuf_len(xb) - 1 : 0; (DIR) diff --git a/vi.h b/vi.h t@@ -116,6 +116,8 @@ int term_read(int timeout); void term_record(void); void term_commit(void); char *term_att(int att, int old); +void term_push(char *s, int n); +char *term_cmd(int *n); #define TK_CTL(x) ((x) & 037) #define TK_INT(c) ((c) < 0 || (c) == TK_ESC || (c) == TK_CTL('c'))