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'))