diff --git a/README b/README index 44ad211..8d8728d 100644 --- a/README +++ b/README @@ -3,16 +3,31 @@ NEATVI Neatvi is a vi/ex editor. It can edit bidirectional UTF-8 text. -Edit conf.h to adjust syntax highlighting rules, direction adjustment -patterns, and the alternate keymap. To define a new keymap, create a -new array in kmap.h, like kmap_fa, and add it to kmaps array in led.c. -When in input mode, ^f switches to the alternate keymap and ^e -switches back to the default keymap. +Edit conf.h to adjust syntax highlighting rules and text direction +patterns. To define a new keymap, create a new array in kmap.h, like +kmap_fa, and add it to kmaps array in the same header (the first entry +of the new array specifies its name). The current keymap may be +changed using :cm ex command. When in input mode, ^e changes to the +English kaymap and ^f changes to the alternate keymap (the last keymap +specified with :km). -The following options are supported: +Commands not available in ex(1): + +:cm[ap][!] [kmap] + Without kmap, print the current keymap name. + When kmap is specified, set the alternate keymap to + kmap and, unless ! is given, switch to this keymap. + +:ft [filetype] + Without filetype, print the current file type. + When filetype is specified, set the file type of the + current ex buffer. + +Options supported by neatvi: td, textdirection - Current direction context. The following values are meaningful: + Current direction context. The following values are + meaningful: * +2: always left-to-right. * +1: follow conf.h's dircontexts[]; left-to-right for others. @@ -23,7 +38,12 @@ shape If set (default), performs Arabic/Farsi letter shaping. order - If set, reorder characters based on the rules defined in conf.h. + If set, reorder characters based on the rules defined + in conf.h. + +hl, highlight + If set (default), text will receive syntax highlighting + based on the rules in conf.h. ai, autoindent As in vi(1). @@ -33,7 +53,3 @@ aw, autowrite ic, ignorecase As in vi(1). - -hl, highlight - If set (default), text will receive syntax highlighting based on the - rules in conf.h. diff --git a/conf.c b/conf.c index fd555db..fb7b0cc 100644 --- a/conf.c +++ b/conf.c @@ -1,11 +1,8 @@ #include +#include #include "vi.h" #include "conf.h" - -char *conf_kmapalt(void) -{ - return KMAPALT; -} +#include "kmap.h" int conf_dirmark(int idx, char **pat, int *ctx, int *dir, int *grp) { @@ -77,3 +74,21 @@ int conf_highlight_revdir(int *att) *att = SYN_REVDIR; return 0; } + +char **conf_kmap(char *name) +{ + int i; + for (i = 0; i < LEN(kmaps); i++) + if (name && kmaps[i][0] && !strcmp(name, kmaps[i][0])) + return kmaps[i]; + return kmap_en; +} + +char *conf_digraph(int c1, int c2) +{ + int i; + for (i = 0; i < LEN(digraphs); i++) + if (digraphs[i][0][0] == c1 && digraphs[i][0][1] == c2) + return digraphs[i][1]; + return NULL; +} diff --git a/conf.h b/conf.h index e0b0119..7a44e27 100644 --- a/conf.h +++ b/conf.h @@ -61,9 +61,6 @@ static struct highlight { {"sh", {4}, "\'[^\']*\'"}, }; -/* the alternate keymap (^F and ^E in insert mode to switch) */ -#define KMAPALT "fa" - /* how to hightlight text in the reverse direction */ #define SYN_REVDIR (SYN_BGMK(255)) diff --git a/ex.c b/ex.c index 7564e14..d9f17cb 100644 --- a/ex.c +++ b/ex.c @@ -21,6 +21,8 @@ int xshape = 1; /* perform letter shaping */ int xorder = 1; /* change the order of characters */ char xfindkwd[EXLEN]; /* the last searched keyword */ int xfinddir = +1; /* the last search direction */ +static char *xkmap = "en"; /* the current keymap */ +static char xkmap2[8] = "fa"; /* the alternate keymap */ static struct buf { char ft[32]; @@ -96,6 +98,16 @@ char *ex_filetype(void) return xhl ? bufs[0].ft : ""; } +char **ex_kmap(void) +{ + return &xkmap; +} + +char *ex_kmapalt(void) +{ + return xkmap2; +} + /* read ex command location */ static char *ex_loc(char *s, char *loc) { @@ -690,6 +702,21 @@ static int ec_ft(char *ec) return 0; } +static int ec_cmap(char *ec) +{ + char cmd[EXLEN]; + char arg[EXLEN]; + ex_cmd(ec, cmd); + ex_arg(ec, arg); + if (arg[0]) + snprintf(xkmap2, sizeof(xkmap2), arg); + else + ex_print(xkmap); + if (arg[0] && !strchr(cmd, '!')) + xkmap = xkmap2; + return 0; +} + static struct option { char *abbr; char *name; @@ -784,6 +811,8 @@ static struct excmd { {"!", "!", ec_exec}, {"make", "make", ec_make}, {"ft", "filetype", ec_ft}, + {"cm", "cmap", ec_cmap}, + {"cm!", "cmap!", ec_cmap}, {"", "", ec_null}, }; diff --git a/kmap.h b/kmap.h index 0ad8042..8f7a90e 100644 --- a/kmap.h +++ b/kmap.h @@ -100,6 +100,8 @@ static char *kmap_fa[256] = { ['|'] = "|", }; +static char **kmaps[] = {kmap_en, kmap_fa}; + static char *digraphs[][2] = { {"cq", "’"}, {"pl", "+"}, diff --git a/led.c b/led.c index 8903da0..66a3d9c 100644 --- a/led.c +++ b/led.c @@ -4,23 +4,11 @@ #include #include #include "vi.h" -#include "kmap.h" - -static char **kmaps[] = {kmap_en, kmap_fa}; - -static char **kmap_find(char *name) -{ - int i; - for (i = 0; i < LEN(kmaps); i++) - if (name && kmaps[i][0] && !strcmp(name, kmaps[i][0])) - return kmaps[i]; - return kmap_en; -} static char *kmap_map(char *kmap, int c) { static char cs[4]; - char **keymap = kmap_find(kmap); + char **keymap = conf_kmap(kmap); cs[0] = c; return keymap[c] ? keymap[c] : cs; } @@ -198,10 +186,7 @@ static char *led_readchar(int c, char *kmap) c2 = term_read(); if (TK_INT(c2)) return NULL; - for (i = 0; i < LEN(digraphs); i++) - if (digraphs[i][0][0] == c1 && digraphs[i][0][1] == c2) - return digraphs[i][1]; - return NULL; + return conf_digraph(c1, c2); } if ((c & 0xc0) == 0xc0) { /* utf-8 character */ buf[0] = c; @@ -220,10 +205,10 @@ char *led_read(char **kmap) while (!TK_INT(c)) { switch (c) { case TK_CTL('f'): - *kmap = conf_kmapalt(); + *kmap = ex_kmapalt(); break; case TK_CTL('e'): - *kmap = kmap_en[0]; + *kmap = "en"; break; default: return led_readchar(c, *kmap); @@ -249,10 +234,10 @@ static char *led_line(char *pref, char *post, char *ai, int ai_max, int *key, ch c = term_read(); switch (c) { case TK_CTL('f'): - *kmap = conf_kmapalt(); + *kmap = ex_kmapalt(); continue; case TK_CTL('e'): - *kmap = kmap_en[0]; + *kmap = "en"; continue; case TK_CTL('h'): case 127: diff --git a/vi.c b/vi.c index 41b1797..ab05e58 100644 --- a/vi.c +++ b/vi.c @@ -17,7 +17,6 @@ static char vi_charlast[8]; /* the last character searched via f, t, F, or T */ static int vi_charcmd; /* the character finding command */ static int vi_arg1, vi_arg2; /* the first and second arguments */ static int vi_ybuf; /* current yank buffer */ -static char *vi_kmap; /* current insertion keymap */ static int vi_pcol; /* the column requested by | command */ static int vi_printed; /* ex_print() calls since the last command */ static int vi_scroll; /* scroll amount for ^f and ^d*/ @@ -79,7 +78,7 @@ static void vi_back(int c) static char *vi_char(void) { - return led_read(&vi_kmap); + return led_read(ex_kmap()); } static char *vi_prompt(char *msg, char **kmap) @@ -101,7 +100,7 @@ char *ex_read(char *msg) struct sbuf *sb; char c; if (xled) { - char *s = led_prompt(msg, "", &vi_kmap); + char *s = led_prompt(msg, "", ex_kmap()); if (s) term_chr('\n'); return s; @@ -217,7 +216,7 @@ static int vi_search(int cmd, int cnt, int *row, int *off) char *soff = ""; if (cmd == '/' || cmd == '?') { char sign[4] = {cmd}; - char *kw = vi_prompt(sign, &vi_kmap); + char *kw = vi_prompt(sign, ex_kmap()); if (!kw) return 1; xfinddir = cmd == '/' ? +1 : -1; @@ -618,7 +617,7 @@ static int charcount(char *text, char *post) static char *vi_input(char *pref, char *post, int *row, int *off) { - char *rep = led_input(pref, post, &vi_kmap); + char *rep = led_input(pref, post, ex_kmap()); if (!rep) return NULL; *row = linecount(rep) - 1; diff --git a/vi.h b/vi.h index 1eb15a7..dd9df3c 100644 --- a/vi.h +++ b/vi.h @@ -141,6 +141,8 @@ int ex_init(char **files); void ex_done(void); char *ex_path(void); char *ex_filetype(void); +char **ex_kmap(void); +char *ex_kmapalt(void); struct lbuf *ex_lbuf(void); #define xb ex_lbuf() @@ -169,13 +171,14 @@ void syn_init(void); void syn_done(void); /* configuration variables */ -char *conf_kmapalt(void); int conf_dirmark(int idx, char **pat, int *ctx, int *dir, int *grp); int conf_dircontext(int idx, char **pat, int *ctx); int conf_placeholder(int idx, char **s, char **d, int *wid); int conf_highlight(int idx, char **ft, int **att, char **pat, int *end); int conf_filetype(int idx, char **ft, char **pat); int conf_highlight_revdir(int *att); +char **conf_kmap(char *name); +char *conf_digraph(int c1, int c2); /* global variables */ extern int xrow;