tex: mark the region before executing glob 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 57077e595860fb487d95316fc8dfc41df965342f
(DIR) parent d3b961346505dc8b1be900ce63a5a593f2ff9895
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
Date: Thu, 30 Jun 2016 10:52:06 +0430
ex: mark the region before executing glob commands
Diffstat:
M ex.c | 45 ++++++++++++++++++++-----------
M lbuf.c | 85 ++++++++++++++++++-------------
M vi.h | 1 +
3 files changed, 79 insertions(+), 52 deletions(-)
---
(DIR) diff --git a/ex.c b/ex.c
t@@ -185,14 +185,6 @@ static char *ex_argeol(char *ec)
return s;
}
-static char *ex_line(char *s, char *ln)
-{
- while (*s && *s != '|' && *s != '\n')
- *ln++ = *s++;
- *ln = '\0';
- return *s ? s + 1 : s;
-}
-
/* the previous search keyword */
int ex_kwd(char **kwd, int *dir)
{
t@@ -825,18 +817,22 @@ static int ec_glob(char *ec)
return 1;
if (!(re = rset_make(1, pats, xic ? RE_ICASE : 0)))
return 1;
+ for (i = beg + 1; i < end; i++)
+ lbuf_glob(xb, i, 1);
i = beg;
- while (i < end) {
+ while (i < lbuf_len(xb)) {
char *ln = lbuf_get(xb, i);
if ((rset_find(re, ln, LEN(offs) / 2, offs, 0) < 0) == not) {
- int len = lbuf_len(xb);
xrow = i;
- ex_exec(s);
- i = xrow;
- end += lbuf_len(xb) - len;
+ if (ex_exec(s))
+ break;
+ i = MIN(i, xrow);
}
- i++;
+ while (i < lbuf_len(xb) && !lbuf_glob(xb, i, 0))
+ i++;
}
+ for (i = 0; i < lbuf_len(xb); i++)
+ lbuf_glob(xb, i, 0);
rset_free(re);
return 0;
}
t@@ -945,6 +941,21 @@ static struct excmd {
{"", "", ec_null},
};
+/* read an ex command and its arguments from src into dst */
+static void ex_line(int (*ec)(char *s), char *dst, char **src)
+{
+ if (!ec || ec != ec_glob) {
+ while (**src && **src != '|' && **src != '\n')
+ *dst++ = *(*src)++;
+ *dst = '\0';
+ if (**src)
+ (*src)++;
+ } else { /* the rest of the line for :g */
+ strcpy(dst, *src);
+ *src = strchr(*src, '\0');
+ }
+}
+
/* execute a single ex command */
static int ex_exec(char *ln)
{
t@@ -953,17 +964,19 @@ static int ex_exec(char *ln)
int i;
int ret = 0;
while (*ln) {
- ln = ex_line(ln, ec);
- ex_cmd(ec, cmd);
+ ex_cmd(ln, cmd);
for (i = 0; i < LEN(excmds); i++) {
if (!strcmp(excmds[i].abbr, cmd) ||
!strcmp(excmds[i].name, cmd)) {
+ ex_line(excmds[i].ec, ec, &ln);
ret = excmds[i].ec(ec);
break;
}
}
if (!xvis && !cmd[0])
ret = ec_print(ec);
+ if (i == LEN(excmds))
+ ex_line(NULL, ec, &ln);
}
return ret;
}
(DIR) diff --git a/lbuf.c b/lbuf.c
t@@ -23,6 +23,7 @@ struct lbuf {
int mark[NMARKS]; /* mark lines */
int mark_off[NMARKS]; /* mark line offsets */
char **ln; /* buffer lines */
+ char *ln_glob; /* line global mark */
int ln_n; /* number of lines in ln[] */
int ln_sz; /* size of ln[] */
int useq; /* current operation sequence */
t@@ -110,48 +111,61 @@ void lbuf_free(struct lbuf *lb)
lopt_done(&lb->hist[i]);
free(lb->hist);
free(lb->ln);
+ free(lb->ln_glob);
free(lb);
}
-/* insert a line at pos */
-static void lbuf_insertline(struct lbuf *lb, int pos, char *s)
+static int linelength(char *s)
{
- if (lb->ln_n == lb->ln_sz) {
+ char *r = strchr(s, '\n');
+ return r ? r - s + 1 : strlen(s);
+}
+
+static int linecount(char *s)
+{
+ int n;
+ for (n = 0; s && *s; n++)
+ s += linelength(s);
+ return n;
+}
+
+
+/* low-level line replacement */
+static void lbuf_replace(struct lbuf *lb, char *s, int pos, int n_del)
+{
+ int n_ins = linecount(s);
+ int i;
+ while (lb->ln_n + n_ins - n_del >= lb->ln_sz) {
int nsz = lb->ln_sz + 512;
char **nln = malloc(nsz * sizeof(nln[0]));
+ char *nln_glob = malloc(nsz * sizeof(nln_glob[0]));
memcpy(nln, lb->ln, lb->ln_n * sizeof(lb->ln[0]));
+ memcpy(nln_glob, lb->ln_glob, lb->ln_n * sizeof(lb->ln_glob[0]));
free(lb->ln);
+ free(lb->ln_glob);
lb->ln = nln;
+ lb->ln_glob = nln_glob;
lb->ln_sz = nsz;
}
- memmove(lb->ln + pos + 1, lb->ln + pos,
- (lb->ln_n - pos) * sizeof(lb->ln[0]));
- lb->ln_n++;
- lb->ln[pos] = s;
-}
-
-/* low-level replacement */
-static void lbuf_replace(struct lbuf *lb, char *s, int pos, int n_del)
-{
- char *r, *n;
- int n_ins = 0;
- int i;
for (i = 0; i < n_del; i++)
free(lb->ln[pos + i]);
- memmove(lb->ln + pos, lb->ln + pos + n_del,
+ memmove(lb->ln + pos + n_ins, lb->ln + pos + n_del,
(lb->ln_n - pos - n_del) * sizeof(lb->ln[0]));
- lb->ln_n -= n_del;
- while (s && *s) {
- r = strchr(s, '\n');
- if (!r) /* no eol */
- r = strchr(s, '\0');
- n = malloc(r - s + 2);
- memcpy(n, s, r - s);
- n[r - s + 0] = '\n';
- n[r - s + 1] = '\0';
- lbuf_insertline(lb, pos + n_ins++, n);
- s = *r ? r + 1 : r;
+ memmove(lb->ln_glob + pos + n_ins, lb->ln_glob + pos + n_del,
+ (lb->ln_n - pos - n_del) * sizeof(lb->ln_glob[0]));
+ lb->ln_n += n_ins - n_del;
+ for (i = 0; i < n_ins; i++) {
+ int l = s ? linelength(s) : 0;
+ int l_nonl = l - (s[l - 1] == '\n');
+ char *n = malloc(l_nonl + 2);
+ memcpy(n, s, l_nonl);
+ n[l_nonl + 0] = '\n';
+ n[l_nonl + 1] = '\0';
+ lb->ln[pos + i] = n;
+ s += l;
}
+ for (i = n_del; i < n_ins; i++)
+ lb->ln_glob[pos + i] = 0;
for (i = 0; i < LEN(lb->mark); i++) { /* updating marks */
if (!s && lb->mark[i] >= pos && lb->mark[i] < pos + n_del)
lb->mark[i] = -1;
t@@ -164,14 +178,6 @@ static void lbuf_replace(struct lbuf *lb, char *s, int pos, int n_del)
lbuf_mark(lb, ']', pos + (n_ins ? n_ins - 1 : 0), 0);
}
-static int uc_newlines(char *s)
-{
- int n;
- for (n = 0; (s = strchr(s, '\n')); n++)
- s++;
- return n;
-}
-
/* append undo/redo history */
static void lbuf_opt(struct lbuf *lb, char *buf, int pos, int n_del)
{
t@@ -195,7 +201,7 @@ static void lbuf_opt(struct lbuf *lb, char *buf, int pos, int n_del)
lo->pos = pos;
lo->n_del = n_del;
lo->del = n_del ? lbuf_cp(lb, pos, pos + n_del) : NULL;
- lo->n_ins = buf ? uc_newlines(buf) : 0;
+ lo->n_ins = buf ? linecount(buf) : 0;
lo->ins = buf ? uc_dup(buf) : NULL;
lo->seq = lb->useq;
lbuf_savepos(lb, lo);
t@@ -344,3 +350,10 @@ int lbuf_modified(struct lbuf *lb)
lb->useq++;
return lbuf_seq(lb) != lb->useq_zero;
}
+
+int lbuf_glob(struct lbuf *lb, int pos, int v)
+{
+ int o = lb->ln_glob[pos];
+ lb->ln_glob[pos] = v;
+ return o;
+}
(DIR) diff --git a/vi.h b/vi.h
t@@ -22,6 +22,7 @@ int lbuf_modified(struct lbuf *lb);
void lbuf_saved(struct lbuf *lb, int clear);
int lbuf_indents(struct lbuf *lb, int r);
int lbuf_eol(struct lbuf *lb, int r);
+int lbuf_glob(struct lbuf *lb, int pos, int v);
/* motions */
int lbuf_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *r, int *o);
int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *o, int *len);