Introduction
Introduction Statistics Contact Development Disclaimer Help
tlbuf: preserve marks during change and delete commands - neatvi - [fork] simpl…
git clone git://src.adamsgaard.dk/neatvi
Log
Files
Refs
README
---
commit 70f7eb3e153a4b749d07c242945d4a693085c6fc
parent 86c9ce2ce6d2ca663846199b322fcb341e23d527
Author: Ali Gholami Rudi <[email protected]>
Date: Thu, 3 Sep 2015 18:22:28 +0430
lbuf: preserve marks during change and delete commands
Also, the undo command restores the marks inside the changing region.
Diffstat:
M ex.c | 29 +++++++++++++----------------
M lbuf.c | 171 ++++++++++++++---------------…
M vi.c | 41 ++++++++++++-----------------…
M vi.h | 5 ++---
4 files changed, 110 insertions(+), 136 deletions(-)
---
diff --git a/ex.c b/ex.c
t@@ -336,8 +336,7 @@ static int ec_edit(char *ec)
bufs_switch(bufs_open(path));
fd = open(ex_path(), O_RDONLY);
if (fd >= 0) {
- lbuf_rm(xb, 0, lbuf_len(xb));
- lbuf_rd(xb, fd, 0);
+ lbuf_rd(xb, fd, 0, lbuf_len(xb));
close(fd);
snprintf(msg, sizeof(msg), "\"%s\" %d lines [r]\n",
ex_path(), lbuf_len(xb));
t@@ -362,19 +361,21 @@ static int ec_read(char *ec)
if (ex_region(loc, &beg, &end))
return 1;
if (arg[0] == '!') {
+ int pos = MIN(xrow + 1, lbuf_len(xb));
if (ex_expand(arg, ex_argeol(ec)))
return 1;
obuf = cmd_pipe(arg + 1, NULL, 0, 1);
if (obuf)
- lbuf_put(xb, MIN(xrow + 1, lbuf_len(xb)), obuf);
+ lbuf_edit(xb, obuf, pos, pos);
free(obuf);
} else {
int fd = open(path, O_RDONLY);
+ int pos = lbuf_len(xb) ? end : 0;
if (fd < 0) {
ex_show("read failed\n");
return 1;
}
- lbuf_rd(xb, fd, lbuf_len(xb) ? end : 0);
+ lbuf_rd(xb, fd, pos, pos);
close(fd);
}
xrow = end + lbuf_len(xb) - n - 1;
t@@ -445,11 +446,6 @@ static int ec_insert(char *ec)
ex_loc(ec, loc);
if (ex_region(loc, &beg, &end) && (beg != 0 || end != 0))
return 1;
- if (cmd[0] == 'c') {
- if (lbuf_len(xb))
- lbuf_rm(xb, beg, end);
- end = beg + 1;
- }
sb = sbuf_make();
while ((s = ex_read(""))) {
if (!strcmp(".", s)) {
t@@ -461,10 +457,12 @@ static int ec_insert(char *ec)
free(s);
}
if (cmd[0] == 'a')
- if (end > lbuf_len(xb))
- end = lbuf_len(xb);
+ if (beg + 1 <= lbuf_len(xb))
+ beg++;
+ if (cmd[0] != 'c')
+ end = beg;
n = lbuf_len(xb);
- lbuf_put(xb, end, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), beg, end);
xrow = MIN(lbuf_len(xb) - 1, end + lbuf_len(xb) - n - 1);
sbuf_free(sb);
return 0;
t@@ -522,7 +520,7 @@ static int ec_delete(char *ec)
if (ex_region(loc, &beg, &end) || !lbuf_len(xb))
return 1;
ex_yank(arg[0], beg, end);
- lbuf_rm(xb, beg, end);
+ lbuf_edit(xb, NULL, beg, end);
xrow = beg;
return 0;
}
t@@ -553,7 +551,7 @@ static int ec_put(char *ec)
buf = reg_get(arg[0], &lnmode);
if (!buf || ex_region(loc, &beg, &end))
return 1;
- lbuf_put(xb, end, buf);
+ lbuf_edit(xb, buf, end, end);
xrow = MIN(lbuf_len(xb) - 1, end + lbuf_len(xb) - n - 1);
return 0;
}
t@@ -647,8 +645,7 @@ static int ec_substitute(char *ec)
break;
}
sbuf_str(r, ln);
- lbuf_rm(xb, i, i + 1);
- lbuf_put(xb, i, sbuf_buf(r));
+ lbuf_edit(xb, sbuf_buf(r), i, i + 1);
sbuf_free(r);
}
rset_free(re);
diff --git a/lbuf.c b/lbuf.c
t@@ -1,3 +1,4 @@
+#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
t@@ -8,9 +9,9 @@
/* line operations */
struct lopt {
- char *buf; /* text inserted or deleted */
- int ins; /* insertion operation if non-zero */
- int beg, end;
+ char *ins; /* inserted text */
+ char *del; /* deleted text */
+ int pos, n_ins, n_del; /* modification location */
int seq; /* operation number */
int *mark, *mark_off; /* saved marks */
};
t@@ -27,7 +28,6 @@ struct lbuf {
int hist_sz; /* size of hist[] */
int hist_n; /* current history head in hist[] */
int hist_u; /* current undo head in hist[] */
- int mod_new; /* clear modification marks */
int useq_zero; /* useq for lbuf_saved() */
int useq_last; /* useq before hist[] */
};
t@@ -45,11 +45,33 @@ struct lbuf *lbuf_make(void)
static void lopt_done(struct lopt *lo)
{
- free(lo->buf);
+ free(lo->ins);
+ free(lo->del);
free(lo->mark);
free(lo->mark_off);
}
+static void lbuf_savemark(struct lbuf *lb, struct lopt *lo, int m)
+{
+ if (lb->mark[m] >= 0) {
+ if (!lo->mark) {
+ lo->mark = malloc(sizeof(lb->mark));
+ lo->mark_off = malloc(sizeof(lb->mark_off));
+ memset(lo->mark, 0xff, sizeof(lb->mark));
+ }
+ lo->mark[m] = lb->mark[m];
+ lo->mark_off[m] = lb->mark_off[m];
+ }
+}
+
+static void lbuf_loadmark(struct lbuf *lb, struct lopt *lo, int m)
+{
+ if (lo->mark && lo->mark[m] >= 0) {
+ lb->mark[m] = lo->mark[m];
+ lb->mark_off[m] = lo->mark_off[m];
+ }
+}
+
void lbuf_free(struct lbuf *lb)
{
int i;
t@@ -79,51 +101,46 @@ static void lbuf_insertline(struct lbuf *lb, int pos, cha…
lb->ln[pos] = s;
}
-/* low-level insertion */
-static void lbuf_insert(struct lbuf *lb, int pos, char *s)
+/* low-level replacement */
+static void lbuf_replace(struct lbuf *lb, char *s, int pos, int n_del)
{
- int lb_len = lbuf_len(lb);
- int beg = pos, end;
char *r;
+ int n_ins = 0;
int i;
- while ((r = strchr(s, '\n'))) {
+ for (i = 0; i < n_del; i++)
+ free(lb->ln[pos + i]);
+ memmove(lb->ln + pos, lb->ln + pos + n_del,
+ (lb->ln_n - pos - n_del) * sizeof(lb->ln[0]));
+ lb->ln_n -= n_del;
+ while (s && (r = strchr(s, '\n'))) {
char *n = malloc(r - s + 2);
memcpy(n, s, r - s + 1);
n[r - s + 1] = '\0';
- lbuf_insertline(lb, pos++, n);
+ lbuf_insertline(lb, pos + n_ins++, n);
s = r + 1;
}
- for (i = 0; i < LEN(lb->mark); i++) /* updating marks */
- if (lb->mark[i] >= pos)
- lb->mark[i] += lbuf_len(lb) - lb_len;
- end = beg + lbuf_len(lb) - lb_len;
- if (lb->mod_new || lb->mark['['] < 0 || lb->mark['['] > beg)
- lbuf_mark(lb, '[', beg, 0);
- if (lb->mod_new || lb->mark[']'] < 0 || lb->mark[']'] < end - 1)
- lbuf_mark(lb, ']', end - 1, 0);
- lb->mod_new = 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;
+ else if (lb->mark[i] >= pos + n_del)
+ lb->mark[i] += n_ins - n_del;
+ else if (lb->mark[i] >= pos + n_ins)
+ lb->mark[i] = pos + n_ins - 1;
+ }
+ lbuf_mark(lb, '[', pos, 0);
+ lbuf_mark(lb, ']', pos + n_ins - n_del, 0);
}
-/* low-level deletion */
-static void lbuf_delete(struct lbuf *lb, int beg, int end)
+static int uc_newlines(char *s)
{
- int i;
- for (i = beg; i < end; i++)
- free(lb->ln[i]);
- memmove(lb->ln + beg, lb->ln + end, (lb->ln_n - end) * sizeof(lb->ln[0…
- lb->ln_n -= end - beg;
- for (i = 0; i < LEN(lb->mark); i++) /* updating marks */
- if (lb->mark[i] > beg)
- lb->mark[i] = MAX(beg, lb->mark[i] + beg - end);
- if (lb->mod_new || lb->mark['['] < 0 || lb->mark['['] > beg)
- lbuf_mark(lb, '[', beg, 0);
- if (lb->mod_new || lb->mark[']'] < 0 || lb->mark[']'] < beg)
- lbuf_mark(lb, ']', beg, 0);
- lb->mod_new = 0;
+ int n;
+ for (n = 0; (s = strchr(s, '\n')); n++)
+ s++;
+ return n;
}
/* append undo/redo history */
-static void lbuf_opt(struct lbuf *lb, int ins, int beg, int end)
+static void lbuf_opt(struct lbuf *lb, char *buf, int pos, int n_del)
{
struct lopt *lo;
int i;
t@@ -142,14 +159,19 @@ static void lbuf_opt(struct lbuf *lb, int ins, int beg, …
lb->hist_n++;
lb->hist_u = lb->hist_n;
memset(lo, 0, sizeof(*lo));
- lo->ins = ins;
- lo->beg = beg;
- lo->end = end;
- lo->buf = lbuf_cp(lb, beg, end);
+ 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->ins = buf ? uc_dup(buf) : NULL;
lo->seq = lb->useq;
+ for (i = 0; i < LEN(lb->mark); i++)
+ if (lb->mark[i] >= pos && lb->mark[i] < pos + n_del)
+ if (isalpha(i))
+ lbuf_savemark(lb, lo, i);
}
-void lbuf_rd(struct lbuf *lbuf, int fd, int pos)
+void lbuf_rd(struct lbuf *lbuf, int fd, int beg, int end)
{
char buf[1 << 10];
struct sbuf *sb;
t@@ -157,7 +179,7 @@ void lbuf_rd(struct lbuf *lbuf, int fd, int pos)
sb = sbuf_make();
while ((nr = read(fd, buf, sizeof(buf))) > 0)
sbuf_mem(sb, buf, nr);
- lbuf_put(lbuf, pos, sbuf_buf(sb));
+ lbuf_edit(lbuf, sbuf_buf(sb), beg, end);
sbuf_free(sb);
}
t@@ -168,23 +190,17 @@ void lbuf_wr(struct lbuf *lbuf, int fd, int beg, int end)
write(fd, lbuf->ln[i], strlen(lbuf->ln[i]));
}
-void lbuf_rm(struct lbuf *lb, int beg, int end)
+/* replace lines beg through end with buf */
+void lbuf_edit(struct lbuf *lb, char *buf, int beg, int end)
{
+ if (beg > lb->ln_n)
+ beg = lb->ln_n;
if (end > lb->ln_n)
end = lb->ln_n;
- if (beg == end)
- return;
- lbuf_opt(lb, 0, beg, end);
- lbuf_delete(lb, beg, end);
-}
-
-void lbuf_put(struct lbuf *lb, int pos, char *s)
-{
- int lb_len = lbuf_len(lb);
- if (!*s)
+ if (beg == end && !buf)
return;
- lbuf_insert(lb, pos, s);
- lbuf_opt(lb, 1, pos, pos + lbuf_len(lb) - lb_len);
+ lbuf_opt(lb, buf, beg, end - beg);
+ lbuf_replace(lb, buf, beg, end - beg);
}
char *lbuf_cp(struct lbuf *lb, int beg, int end)
t@@ -226,42 +242,18 @@ int lbuf_jump(struct lbuf *lbuf, int mark, int *pos, int…
return 0;
}
-static void lbuf_savemarks(struct lbuf *lb, struct lopt *lo)
-{
- int i;
- lo->mark = malloc(sizeof(lb->mark));
- lo->mark_off = malloc(sizeof(lb->mark_off));
- for (i = 0; i < LEN(lb->mark); i++)
- lo->mark[i] = -1;
- lo->mark['*'] = lb->mark['*'];
- lo->mark_off['*'] = lb->mark_off['*'];
-}
-
-static void lbuf_loadmarks(struct lbuf *lb, struct lopt *lo)
-{
- int i;
- for (i = 0; lo->mark && i < LEN(lb->mark); i++) {
- if (lo->mark[i] >= 0) {
- lb->mark[i] = lo->mark[i];
- lb->mark_off[i] = lo->mark_off[i];
- }
- }
-}
-
int lbuf_undo(struct lbuf *lb)
{
- int useq;
+ int useq, i;
if (!lb->hist_u)
return 1;
useq = lb->hist[lb->hist_u - 1].seq;
- lb->mod_new = 1;
while (lb->hist_u && lb->hist[lb->hist_u - 1].seq == useq) {
struct lopt *lo = &lb->hist[--(lb->hist_u)];
- if (lo->ins)
- lbuf_delete(lb, lo->beg, lo->end);
- else
- lbuf_insert(lb, lo->beg, lo->buf);
- lbuf_loadmarks(lb, lo);
+ lbuf_replace(lb, lo->del, lo->pos, lo->n_ins);
+ lbuf_loadmark(lb, lo, '*');
+ for (i = 0; i < LEN(lb->mark); i++)
+ lbuf_loadmark(lb, lo, i);
}
return 0;
}
t@@ -272,14 +264,10 @@ int lbuf_redo(struct lbuf *lb)
if (lb->hist_u == lb->hist_n)
return 1;
useq = lb->hist[lb->hist_u].seq;
- lb->mod_new = 1;
while (lb->hist_u < lb->hist_n && lb->hist[lb->hist_u].seq == useq) {
struct lopt *lo = &lb->hist[lb->hist_u++];
- if (lo->ins)
- lbuf_insert(lb, lo->beg, lo->buf);
- else
- lbuf_delete(lb, lo->beg, lo->end);
- lbuf_loadmarks(lb, lo);
+ lbuf_replace(lb, lo->ins, lo->pos, lo->n_del);
+ lbuf_loadmark(lb, lo, '*');
}
return 0;
}
t@@ -309,8 +297,7 @@ int lbuf_modified(struct lbuf *lb)
{
struct lopt *lo = lb->hist_n ? &lb->hist[lb->hist_n - 1] : NULL;
if (lb->hist_u == lb->hist_n && lo && !lo->mark)
- lbuf_savemarks(lb, lo);
- lb->mod_new = 1;
+ lbuf_savemark(lb, lo, '*');
lb->useq++;
return lbuf_seq(lb) != lb->useq_zero;
}
diff --git a/vi.c b/vi.c
t@@ -572,13 +572,14 @@ static void vi_delete(int r1, int o1, int r2, int o2, in…
free(region);
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, o1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -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));
+ lbuf_edit(xb, sbuf_buf(sb), r1, r2 + 1);
sbuf_free(sb);
+ } else {
+ lbuf_edit(xb, NULL, r1, r2 + 1);
}
xrow = r1;
xoff = lnmode ? lbuf_indents(xb, xrow) : o1;
t@@ -653,8 +654,7 @@ static void vi_change(int r1, int o1, int r2, int o2, int …
vi_drawrm(r1, r2, 0);
rep = vi_input(pref, post, &row, &off);
if (rep) {
- lbuf_rm(xb, r1, r2 + 1);
- lbuf_put(xb, r1, rep);
+ lbuf_edit(xb, rep, r1, r2 + 1);
xrow = r1 + row - 1;
xoff = off;
free(rep);
t@@ -683,16 +683,15 @@ static void vi_case(int r1, int o1, int r2, int o2, int …
}
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, o1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -1);
- lbuf_rm(xb, r1, r2 + 1);
if (!lnmode) {
struct sbuf *sb = sbuf_make();
sbuf_str(sb, pref);
sbuf_str(sb, region);
sbuf_str(sb, post);
- lbuf_put(xb, r1, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), r1, r2 + 1);
sbuf_free(sb);
} else {
- lbuf_put(xb, r1, region);
+ lbuf_edit(xb, region, r1, r2 + 1);
}
xrow = r2;
xoff = lnmode ? lbuf_indents(xb, r2) : o2;
t@@ -711,10 +710,8 @@ static void vi_pipe(int r1, int r2)
return;
text = lbuf_cp(xb, r1, r2 + 1);
rep = cmd_pipe(cmd, text, 1, 1);
- if (rep) {
- lbuf_rm(xb, r1, r2 + 1);
- lbuf_put(xb, r1, rep);
- }
+ if (rep)
+ lbuf_edit(xb, rep, r1, r2 + 1);
free(cmd);
free(text);
free(rep);
t@@ -734,8 +731,7 @@ static void vi_shift(int r1, int r2, int dir)
else
ln = ln[0] == ' ' || ln[0] == '\t' ? ln + 1 : ln;
sbuf_str(sb, ln);
- lbuf_rm(xb, i, i + 1);
- lbuf_put(xb, i, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), i, i + 1);
sbuf_free(sb);
}
xrow = r1;
t@@ -813,11 +809,9 @@ static int vc_insert(int cmd)
vi_drawrm(xrow, xrow, cmd == 'o' || cmd == 'O');
rep = vi_input(pref, post, &row, &off);
if ((cmd == 'o' || cmd == 'O') && !lbuf_len(xb))
- lbuf_put(xb, 0, "\n");
+ lbuf_edit(xb, "\n", 0, 0);
if (rep) {
- if (cmd != 'o' && cmd != 'O')
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, rep);
+ lbuf_edit(xb, rep, xrow, xrow + (cmd != 'o' && cmd != 'O'));
xrow += row - 1;
xoff = off;
free(rep);
t@@ -842,10 +836,10 @@ static int vc_put(int cmd)
for (i = 0; i < cnt; i++)
sbuf_str(sb, buf);
if (!lbuf_len(xb))
- lbuf_put(xb, 0, "\n");
+ lbuf_edit(xb, "\n", 0, 0);
if (cmd == 'p')
xrow++;
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow);
xoff = lbuf_indents(xb, xrow);
sbuf_free(sb);
} else {
t@@ -860,8 +854,7 @@ static int vc_put(int cmd)
s = uc_sub(ln, off, -1);
sbuf_str(sb, s);
free(s);
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow + 1);
xoff = off + uc_slen(buf) * cnt - 1;
sbuf_free(sb);
}
t@@ -903,8 +896,7 @@ static int vc_join(void)
sbuf_mem(sb, ln, lnend - ln);
}
sbuf_chr(sb, '\n');
- lbuf_rm(xb, beg, end);
- lbuf_put(xb, beg, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), beg, end);
xoff = off;
sbuf_free(sb);
return 0;
t@@ -963,8 +955,7 @@ static int vc_replace(void)
for (i = 0; i < cnt; i++)
sbuf_str(sb, cs);
sbuf_str(sb, post);
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow + 1);
off += cnt - 1;
xoff = off;
sbuf_free(sb);
diff --git a/vi.h b/vi.h
t@@ -8,11 +8,10 @@
/* line buffer, managing a number of lines */
struct lbuf *lbuf_make(void);
void lbuf_free(struct lbuf *lbuf);
-void lbuf_rd(struct lbuf *lbuf, int fd, int pos);
+void lbuf_rd(struct lbuf *lbuf, int fd, int beg, int end);
void lbuf_wr(struct lbuf *lbuf, int fd, int beg, int end);
-void lbuf_rm(struct lbuf *lbuf, int beg, int end);
+void lbuf_edit(struct lbuf *lbuf, char *s, int beg, int end);
char *lbuf_cp(struct lbuf *lbuf, int beg, int end);
-void lbuf_put(struct lbuf *lbuf, int pos, char *s);
char *lbuf_get(struct lbuf *lbuf, int pos);
int lbuf_len(struct lbuf *lbuf);
void lbuf_mark(struct lbuf *lbuf, int mark, int pos, int off);
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.