tvi: repeat and execute commands - neatvi - [fork] simple vi-type editor with U… | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 901e0cd396e087f435fa96b51196d01d0f94ca18 | |
parent 04a3edea64e70aae164a0550acaf5bf18ccac472 | |
Author: Ali Gholami Rudi <[email protected]> | |
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(-) | |
--- | |
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 */ | |
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; | |
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')) |