tex: save edit buffer state when editing different files - neatvi - [fork] simp… | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit b531d476541da6bdec69e574dc703985c4637cd9 | |
parent ebe8300559aa61f5a7c2f8933f96e04cb13eace1 | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Sat, 6 Jun 2015 16:23:03 +0430 | |
ex: save edit buffer state when editing different files | |
Diffstat: | |
M ex.c | 189 ++++++++++++++++++++++++-----… | |
M led.c | 2 +- | |
M vi.c | 11 +++-------- | |
M vi.h | 14 ++++++++------ | |
4 files changed, 160 insertions(+), 56 deletions(-) | |
--- | |
diff --git a/ex.c b/ex.c | |
t@@ -9,22 +9,89 @@ | |
#define EXLEN 512 | |
-char xpath[PATHLEN]; /* current file */ | |
-char xpath_alt[PATHLEN]; /* alternate file */ | |
-char xft[32]; /* filetype */ | |
+int xrow, xoff, xtop; /* current row, column, and top row */ | |
int xquit; /* exit if set */ | |
int xvis; /* visual mode */ | |
int xai = 1; /* autoindent option */ | |
int xic = 1; /* ignorecase option */ | |
int xaw; /* autowrite option */ | |
-struct lbuf *xb; /* current buffer */ | |
-int xrow, xoff, xtop; /* current row, column, and top row */ | |
-int xrow_alt; /* alternate row, column, and top row */ | |
int xled = 1; /* use the line editor */ | |
int xdir = +1; /* current direction context */ | |
int xshape = 1; /* perform letter shaping */ | |
int xorder = 1; /* change the order of characters */ | |
+static struct buf { | |
+ char ft[32]; | |
+ char *path; | |
+ struct lbuf *lb; | |
+ int row; | |
+} bufs[8]; | |
+ | |
+static int bufs_find(char *path) | |
+{ | |
+ int i; | |
+ for (i = 0; i < LEN(bufs); i++) | |
+ if (bufs[i].lb && !strcmp(bufs[i].path, path)) | |
+ return i; | |
+ return -1; | |
+} | |
+ | |
+static void bufs_free(int idx) | |
+{ | |
+ if (bufs[idx].lb) { | |
+ free(bufs[idx].path); | |
+ lbuf_free(bufs[idx].lb); | |
+ memset(&bufs[idx], 0, sizeof(bufs[idx])); | |
+ } | |
+} | |
+ | |
+static int bufs_open(char *path) | |
+{ | |
+ int i; | |
+ for (i = 0; i < LEN(bufs) - 1; i++) | |
+ if (!bufs[i].lb) | |
+ break; | |
+ bufs_free(i); | |
+ bufs[i].path = uc_dup(path); | |
+ bufs[i].lb = lbuf_make(); | |
+ bufs[i].row = 0; | |
+ strcpy(bufs[i].ft, syn_filetype(path)); | |
+ return i; | |
+} | |
+ | |
+static void bufs_swap(int i, int j) | |
+{ | |
+ struct buf tmp; | |
+ if (i == j) | |
+ return; | |
+ memcpy(&tmp, &bufs[i], sizeof(tmp)); | |
+ memcpy(&bufs[i], &bufs[j], sizeof(tmp)); | |
+ memcpy(&bufs[j], &tmp, sizeof(tmp)); | |
+} | |
+ | |
+static void bufs_switch(int idx) | |
+{ | |
+ if (idx > 1) | |
+ bufs_swap(0, 1); | |
+ bufs_swap(0, idx); | |
+ xrow = bufs[0].row; | |
+} | |
+ | |
+char *ex_path(void) | |
+{ | |
+ return bufs[0].path; | |
+} | |
+ | |
+struct lbuf *ex_lbuf(void) | |
+{ | |
+ return bufs[0].lb; | |
+} | |
+ | |
+char *ex_filetype(void) | |
+{ | |
+ return bufs[0].ft; | |
+} | |
+ | |
/* read ex command location */ | |
static char *ex_loc(char *s, char *loc) | |
{ | |
t@@ -170,7 +237,7 @@ static int ex_modifiedbuffer(char *msg) | |
{ | |
if (!lbuf_modified(xb)) | |
return 0; | |
- if (xaw && xpath[0]) | |
+ if (xaw && ex_path()[0]) | |
return ec_write("w"); | |
if (msg) | |
ex_show(msg); | |
t@@ -188,50 +255,68 @@ static int ec_quit(char *ec) | |
return 0; | |
} | |
+static int ex_expand(char *d, char *s) | |
+{ | |
+ while (*s) { | |
+ int c = (unsigned char) *s++; | |
+ if (c == '%') { | |
+ if (!bufs[0].path || !bufs[0].path[0]) { | |
+ ex_show("\"%\" is unset\n"); | |
+ return 1; | |
+ } | |
+ strcpy(d, bufs[0].path); | |
+ d = strchr(d, '\0'); | |
+ continue; | |
+ } | |
+ if (c == '#') { | |
+ if (!bufs[1].path || !bufs[1].path[0]) { | |
+ ex_show("\"#\" is unset\n"); | |
+ return 1; | |
+ } | |
+ strcpy(d, bufs[1].path); | |
+ d = strchr(d, '\0'); | |
+ continue; | |
+ } | |
+ if (c == '\\' && (*s == '%' || *s == '#')) | |
+ c = *s++; | |
+ *d++ = c; | |
+ } | |
+ *d = '\0'; | |
+ return 0; | |
+} | |
+ | |
static int ec_edit(char *ec) | |
{ | |
char msg[128]; | |
char arg[EXLEN], cmd[EXLEN]; | |
+ char path[PATHLEN]; | |
int fd; | |
ex_cmd(ec, cmd); | |
ex_arg(ec, arg); | |
if (!strchr(cmd, '!')) | |
- if (ex_modifiedbuffer("buffer modified\n")) | |
- return 1; | |
- if (!arg[0] || !strcmp(arg, "%") || !strcmp(xpath, arg)) { | |
- strcpy(arg, xpath); | |
- } else if (!strcmp(arg, "#")) { | |
- char xpath_tmp[PATHLEN]; | |
- int xrow_tmp = xrow; | |
- if (!xpath_alt[0]) { | |
- ex_show("\"#\" is unset\n"); | |
+ if (xb && ex_modifiedbuffer("buffer modified\n")) | |
return 1; | |
- } | |
- strcpy(xpath_tmp, xpath_alt); | |
- strcpy(xpath_alt, xpath); | |
- strcpy(xpath, xpath_tmp); | |
- xrow = xrow_alt; | |
- xrow_alt = xrow_tmp; | |
- xoff = 0; | |
- xtop = 0; | |
- } else { | |
- strcpy(xpath_alt, xpath); | |
- snprintf(xpath, PATHLEN, "%s", arg); | |
- xrow_alt = xrow; | |
- xrow = xvis ? 0 : 1 << 20; | |
+ if (ex_expand(path, arg)) | |
+ return 1; | |
+ bufs[0].row = xrow; | |
+ if (arg[0] && bufs_find(path) >= 0) { | |
+ bufs_switch(bufs_find(path)); | |
+ return 0; | |
} | |
- strcpy(xft, syn_filetype(xpath)); | |
- fd = open(xpath, O_RDONLY); | |
- lbuf_rm(xb, 0, lbuf_len(xb)); | |
+ if (path[0] || !bufs[0].path) | |
+ 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); | |
close(fd); | |
snprintf(msg, sizeof(msg), "\"%s\" %d lines [r]\n", | |
- xpath, lbuf_len(xb)); | |
+ ex_path(), lbuf_len(xb)); | |
ex_show(msg); | |
} | |
xrow = MAX(0, MIN(xrow, lbuf_len(xb) - 1)); | |
- lbuf_saved(xb, 1); | |
+ lbuf_modified(xb); | |
+ lbuf_saved(xb, path[0] != '\0'); | |
return 0; | |
} | |
t@@ -245,7 +330,7 @@ static int ec_read(char *ec) | |
int n = lbuf_len(xb); | |
ex_arg(ec, arg); | |
ex_loc(ec, loc); | |
- path = arg[0] ? arg : xpath; | |
+ path = arg[0] ? arg : ex_path(); | |
fd = open(path, O_RDONLY); | |
if (fd < 0) { | |
ex_show("read failed\n"); | |
t@@ -272,7 +357,7 @@ static int ec_write(char *ec) | |
ex_cmd(ec, cmd); | |
ex_arg(ec, arg); | |
ex_loc(ec, loc); | |
- path = arg[0] ? arg : xpath; | |
+ path = arg[0] ? arg : ex_path(); | |
if (ex_region(loc, &beg, &end)) | |
return 1; | |
if (!loc[0]) { | |
t@@ -289,9 +374,11 @@ static int ec_write(char *ec) | |
snprintf(msg, sizeof(msg), "\"%s\" %d lines [w]\n", | |
path, end - beg); | |
ex_show(msg); | |
- if (!xpath[0]) | |
- strcpy(xpath, path); | |
- if (!strcmp(xpath, path)) | |
+ if (!ex_path()[0]) { | |
+ free(bufs[0].path); | |
+ bufs[0].path = uc_dup(path); | |
+ } | |
+ if (!strcmp(ex_path(), path)) | |
lbuf_saved(xb, 0); | |
if (!strcmp("wq", cmd)) | |
ec_quit("wq"); | |
t@@ -500,16 +587,22 @@ static int ec_substitute(char *ec) | |
static int ec_exec(char *ec) | |
{ | |
char cmd[EXLEN]; | |
+ char arg[EXLEN]; | |
ex_modifiedbuffer(NULL); | |
- return cmd_exec(ex_cmd(ec, cmd)); | |
+ if (ex_expand(arg, ex_cmd(ec, cmd))) | |
+ return 1; | |
+ return cmd_exec(arg); | |
} | |
static int ec_make(char *ec) | |
{ | |
char cmd[EXLEN]; | |
+ char arg[EXLEN]; | |
char make[EXLEN]; | |
ex_modifiedbuffer(NULL); | |
- sprintf(make, "make %s", ex_cmd(ec, cmd)); | |
+ if (ex_expand(arg, ex_cmd(ec, cmd))) | |
+ return 1; | |
+ sprintf(make, "make %s", arg); | |
return cmd_exec(make); | |
} | |
t@@ -635,3 +728,17 @@ void ex(void) | |
if (xled) | |
term_done(); | |
} | |
+ | |
+void ex_init(char **files) | |
+{ | |
+ char cmd[EXLEN]; | |
+ snprintf(cmd, sizeof(cmd), "e %s", files[0] ? files[0] : ""); | |
+ ec_edit(cmd); | |
+} | |
+ | |
+void ex_done(void) | |
+{ | |
+ int i; | |
+ for (i = 0; i < LEN(bufs); i++) | |
+ bufs_free(i); | |
+} | |
diff --git a/led.c b/led.c | |
t@@ -96,7 +96,7 @@ static char *led_render(char *s0) | |
} | |
} | |
} | |
- att = syn_highlight(xft, s0); | |
+ att = syn_highlight(ex_filetype(), s0); | |
led_markrev(n, chrs, pos, att); | |
out = sbuf_make(); | |
i = 0; | |
diff --git a/vi.c b/vi.c | |
t@@ -879,7 +879,7 @@ static void vc_status(void) | |
int col = vi_off2col(xb, xrow, xoff); | |
snprintf(vi_msg, sizeof(vi_msg), | |
"\"%s\"%c %d lines L%d C%d\n", | |
- xpath[0] ? xpath : "unnamed", | |
+ ex_path()[0] ? ex_path() : "unnamed", | |
lbuf_modified(xb) ? '*' : ' ', | |
lbuf_len(xb), xrow + 1, | |
ren_cursor(lbuf_get(xb, xrow), col) + 1); | |
t@@ -1201,9 +1201,7 @@ static void vi(void) | |
int main(int argc, char *argv[]) | |
{ | |
- char ecmd[PATHLEN]; | |
int i; | |
- xb = lbuf_make(); | |
xvis = 1; | |
for (i = 1; i < argc && argv[i][0] == '-'; i++) { | |
if (argv[i][1] == 's') | |
t@@ -1215,15 +1213,12 @@ int main(int argc, char *argv[]) | |
} | |
dir_init(); | |
syn_init(); | |
- if (i < argc) { | |
- snprintf(ecmd, PATHLEN, "e %s", argv[i]); | |
- ex_command(ecmd); | |
- } | |
+ ex_init(argv + i); | |
if (xvis) | |
vi(); | |
else | |
ex(); | |
- lbuf_free(xb); | |
+ ex_done(); | |
reg_done(); | |
syn_done(); | |
dir_done(); | |
diff --git a/vi.h b/vi.h | |
t@@ -135,6 +135,13 @@ void ex(void); | |
void ex_command(char *cmd); | |
char *ex_read(char *msg); | |
void ex_show(char *msg); | |
+void ex_init(char **files); | |
+void ex_done(void); | |
+char *ex_path(void); | |
+char *ex_filetype(void); | |
+struct lbuf *ex_lbuf(void); | |
+ | |
+#define xb ex_lbuf() | |
/* process management */ | |
char *cmd_pipe(char *cmd, char *s); | |
t@@ -165,19 +172,14 @@ int conf_highlight_revdir(int *att); | |
/* global variables */ | |
#define PATHLEN 512 | |
-extern int xvis; | |
-extern struct lbuf *xb; | |
extern int xrow; | |
extern int xoff; | |
extern int xtop; | |
+extern int xvis; | |
extern int xled; | |
-extern int xrow_alt; | |
-extern char xpath[]; | |
-extern char xpath_alt[]; | |
extern int xquit; | |
extern int xic; | |
extern int xai; | |
extern int xdir; | |
extern int xshape; | |
extern int xorder; | |
-extern char xft[]; |