tex: save edit buffer state when editing different files - 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 b531d476541da6bdec69e574dc703985c4637cd9 (DIR) parent ebe8300559aa61f5a7c2f8933f96e04cb13eace1 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir> 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(-) --- (DIR) 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); +} (DIR) 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; (DIR) 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(); (DIR) 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[];