tconf: move variables to conf.h - 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 c217902ff19a4981fef0f0e478f2cae4416e99c7
 (DIR) parent 84c242d464735708949dc486a36af9ef16853a70
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue, 19 May 2015 11:52:26 +0430
       
       conf: move variables to conf.h
       
       Diffstat:
         M Makefile                            |       5 ++++-
         A conf.c                              |      46 +++++++++++++++++++++++++++++++
         A conf.h                              |      52 +++++++++++++++++++++++++++++++
         M dir.c                               |      54 +++++++++----------------------
         M kmap.h                              |       7 +++++--
         M led.c                               |      26 ++++++++++++++++++--------
         M ren.c                               |      30 ++++++++++--------------------
         M vi.c                                |       2 +-
         M vi.h                                |       6 ++++++
       
       9 files changed, 157 insertions(+), 71 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -2,9 +2,12 @@ CC = cc
        CFLAGS = -Wall -O2
        LDFLAGS =
        
       -OBJS = vi.o ex.o lbuf.o sbuf.o ren.o dir.o reg.o led.o uc.o term.o rset.o cmd.o
       +OBJS = vi.o ex.o lbuf.o sbuf.o ren.o dir.o reg.o led.o uc.o term.o rset.o cmd.o conf.o
        
        all: vi
       +
       +conf.o: conf.h
       +
        %.o: %.c
                $(CC) -c $(CFLAGS) $<
        vi: $(OBJS)
 (DIR) diff --git a/conf.c b/conf.c
       t@@ -0,0 +1,46 @@
       +#include "conf.h"
       +#include "vi.h"
       +
       +char *conf_kmapalt(void)
       +{
       +        return KMAPALT;
       +}
       +
       +int conf_dirmark(int idx, char **pat, int *ctx, int *dir, int *grp)
       +{
       +        if (idx < 0 || idx >= LEN(dirmarks))
       +                return 1;
       +        if (pat)
       +                *pat = dirmarks[idx].pat;
       +        if (ctx)
       +                *ctx = dirmarks[idx].ctx;
       +        if (dir)
       +                *dir = dirmarks[idx].dir;
       +        if (grp)
       +                *grp = dirmarks[idx].grp;
       +        return 0;
       +}
       +
       +int conf_dircontext(int idx, char **pat, int *ctx)
       +{
       +        if (idx < 0 || idx >= LEN(dircontexts))
       +                return 1;
       +        if (pat)
       +                *pat = dircontexts[idx].pat;
       +        if (ctx)
       +                *ctx = dircontexts[idx].dir;
       +        return 0;
       +}
       +
       +int conf_placeholder(int idx, char **s, char **d, int *wid)
       +{
       +        if (idx < 0 || idx >= LEN(placeholders))
       +                return 1;
       +        if (s)
       +                *s = placeholders[idx].s;
       +        if (d)
       +                *d = placeholders[idx].d;
       +        if (wid)
       +                *wid = placeholders[idx].wid;
       +        return 0;
       +}
 (DIR) diff --git a/conf.h b/conf.h
       t@@ -0,0 +1,52 @@
       +/* neatvi configuration file */
       +
       +/* the alternate keymap (^F and ^E in insert mode to switch) */
       +#define KMAPALT                "fa"
       +
       +/* right-to-left characters (used only in dircontexts and dirmarks) */
       +#define CR2L                "ءآأؤإئابةتثجحخدذرزسشصضطظعغـفقكلمنهوىييپچژکگی‌‍؛،»«؟ًٌٍَُِّْ"
       +/* neutral characters (used only in dircontexts and dirmarks) */
       +#define CNEUT                "-!\"#$%&'()*+,./:;<=>?@^_`{|}~ "
       +
       +/* direction context patterns; specifies the direction of a whole line */
       +static struct dircontext {
       +        int dir;
       +        char *pat;
       +} dircontexts[] = {
       +        {-1, "^[" CR2L "]"},
       +        {+1, "^[a-zA-Z_0-9]"},
       +};
       +
       +/* direction marks; the direction of a few words in a line */
       +static struct dirmark {
       +        int ctx;        /* the direction context for this mark; 0 means any */
       +        int dir;        /* the direction of the matched text */
       +        int grp;        /* the nested subgroup; 0 means no groups */
       +        char *pat;
       +} dirmarks[] = {
       +        {+0, +1, 1, "\\\\\\*\\[([^]]+)\\]"},
       +        {+1, -1, 0, "[" CR2L "][" CNEUT CR2L "]*[" CR2L "]"},
       +        {-1, +1, 0, "[a-zA-Z0-9_][^" CR2L "\\\\`$']*[a-zA-Z0-9_]"},
       +        {+0, +1, 0, "$([^$]+)\\$"},
       +        {+0, +1, 1, "\\\\[a-zA-Z0-9_]+\\{([^}]+)\\}"},
       +        {-1, +1, 0, "\\\\."},
       +        {-1, +1, 0, "\\\\[^ \t]+"},
       +};
       +
       +/* character placeholders */
       +static struct placeholder {
       +        char *s;        /* the source character */
       +        char *d;        /* the placeholder */
       +        int wid;        /* the width of the placeholder */
       +} placeholders[] = {
       +        {"‌", "-", 1},
       +        {"‍", "-", 1},
       +        {"ْ", "ـْ", 1},
       +        {"ٌ", "ـٌ", 1},
       +        {"ٍ", "ـٍ", 1},
       +        {"ً", "ـً", 1},
       +        {"ُ", "ـُ", 1},
       +        {"ِ", "ـِ", 1},
       +        {"َ", "ـَ", 1},
       +        {"ّ", "ـّ", 1},
       +};
 (DIR) diff --git a/dir.c b/dir.c
       t@@ -3,31 +3,6 @@
        #include <string.h>
        #include "vi.h"
        
       -#define CR2L                "ءآأؤإئابةتثجحخدذرزسشصضطظعغـفقكلمنهوىييپچژکگی‌‍؛،»«؟ًٌٍَُِّْ"
       -#define CNEUT                "-!\"#$%&'()*+,./:;<=>?@^_`{|}~ "
       -
       -/* direction context patterns */
       -static struct dcontext {
       -        int dir;
       -        char *pat;
       -} dcontexts[] = {
       -        {-1, "^[" CR2L "]"},
       -        {+1, "^[a-zA-Z_0-9]"},
       -};
       -
       -/* direction marks */
       -static struct dmark {
       -        int ctx;        /* the direction context for this mark; 0 means any */
       -        int dir;        /* the direction of matched text */
       -        int grp;        /* the nested subgroup; 0 means no groups */
       -        char *pat;
       -} dmarks[] = {
       -        {+0, +1, 0, "$([^$]+)\\$"},
       -        {+0, +1, 1, "\\\\\\*\\[([^]]+)\\]"},
       -        {+1, -1, 0, "[" CR2L "][" CNEUT CR2L "]*[" CR2L "]"},
       -        {-1, +1, 0, "[a-zA-Z0-9_][^" CR2L "\\\\`$']*[a-zA-Z0-9_]"},
       -};
       -
        static struct rset *dir_rslr;        /* pattern of marks for left-to-right strings */
        static struct rset *dir_rsrl;        /* pattern of marks for right-to-left strings */
        static struct rset *dir_rsctx;        /* direction context patterns */
       t@@ -38,21 +13,20 @@ static int dir_match(char **chrs, int beg, int end, int ctx, int *rec,
                int subs[16 * 2];
                struct rset *rs = ctx < 0 ? dir_rsrl : dir_rslr;
                struct sbuf *str = sbuf_make();
       +        int grp;
                int flg = (beg ? RE_NOTBOL : 0) | (chrs[end][0] ? RE_NOTEOL : 0);
                int found;
                sbuf_mem(str, chrs[beg], chrs[end] - chrs[beg]);
                found = rset_find(rs, sbuf_buf(str), LEN(subs) / 2, subs, flg);
                if (found >= 0 && r_beg && r_end && c_beg && c_end) {
       -                struct dmark *dm = &dmarks[found];
                        char *s = sbuf_buf(str);
       -                int grp = dm->grp;
       +                conf_dirmark(found, NULL, NULL, dir, &grp);
                        *r_beg = beg + uc_off(s, subs[0]);
                        *r_end = beg + uc_off(s, subs[1]);
                        *c_beg = subs[grp * 2 + 0] >= 0 ?
                                beg + uc_off(s, subs[grp * 2 + 0]) : *r_beg;
                        *c_end = subs[grp * 2 + 1] >= 0 ?
                                beg + uc_off(s, subs[grp * 2 + 1]) : *r_end;
       -                *dir = dm->dir;
                        *rec = grp > 0;
                }
                sbuf_free(str);
       t@@ -93,13 +67,14 @@ static void dir_fix(char **chrs, int *ord, int dir, int beg, int end)
        int dir_context(char *s)
        {
                int found;
       +        int dir;
                if (xdir == 'L')
                        return +1;
                if (xdir == 'R')
                        return -1;
                found = rset_find(dir_rsctx, s ? s : "", 0, NULL, 0);
       -        if (found >= 0)
       -                return dcontexts[found].dir;
       +        if (!conf_dircontext(found, NULL, &dir))
       +                return dir;
                return xdir == 'r' ? -1 : +1;
        }
        
       t@@ -122,16 +97,17 @@ void dir_init(void)
                char *relr[128];
                char *rerl[128];
                char *ctx[128];
       -        int i;
       -        for (i = 0; i < LEN(dmarks); i++) {
       -                relr[i] = dmarks[i].ctx >= 0 ? dmarks[i].pat : NULL;
       -                rerl[i] = dmarks[i].ctx <= 0 ? dmarks[i].pat : NULL;
       +        int curctx, i;
       +        char *pat;
       +        for (i = 0; !conf_dirmark(i, &pat, &curctx, NULL, NULL); i++) {
       +                relr[i] = curctx >= 0 ? pat : NULL;
       +                rerl[i] = curctx <= 0 ? pat : NULL;
                }
       -        dir_rslr = rset_make(LEN(dmarks), relr, 0);
       -        dir_rsrl = rset_make(LEN(dmarks), rerl, 0);
       -        for (i = 0; i < LEN(dcontexts); i++)
       -                ctx[i] = dcontexts[i].pat;
       -        dir_rsctx = rset_make(LEN(dcontexts), ctx, 0);
       +        dir_rslr = rset_make(i, relr, 0);
       +        dir_rsrl = rset_make(i, rerl, 0);
       +        for (i = 0; !conf_dircontext(i, &pat, NULL); i++)
       +                ctx[i] = pat;
       +        dir_rsctx = rset_make(i, ctx, 0);
        }
        
        void dir_done(void)
 (DIR) diff --git a/kmap.h b/kmap.h
       t@@ -1,6 +1,9 @@
       -static char *kmap_def[256];
       +static char *kmap_en[256] = {
       +        [0] = "en",
       +};
        
       -static char *kmap_farsi[256] = {
       +static char *kmap_fa[256] = {
       +        [0] = "fa",
                ['`'] = "‍",
                ['1'] = "۱",
                ['2'] = "۲",
 (DIR) diff --git a/led.c b/led.c
       t@@ -5,9 +5,19 @@
        #include "vi.h"
        #include "kmap.h"
        
       -static char **led_kmap = kmap_def;
       +static char **kmaps[] = {kmap_en, kmap_fa};
       +static char **led_kmap = kmap_en;
        
       -static char *keymap(char **kmap, int c)
       +static char **kmap_find(char *name)
       +{
       +        int i;
       +        for (i = 0; i < LEN(kmaps); i++)
       +                if (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];
                cs[0] = c;
       t@@ -22,7 +32,7 @@ int led_pos(char *s, int pos)
        
        char *led_keymap(int c)
        {
       -        return c >= 0 ? keymap(led_kmap, c) : NULL;
       +        return c >= 0 ? kmap_map(led_kmap, c) : NULL;
        }
        
        static char *led_render(char *s0)
       t@@ -115,7 +125,7 @@ static void led_printparts(char *ai, char *pref, char *main, char *post)
                /* cursor position for inserting the next character */
                if (*pref || *main || *ai) {
                        int len = sbuf_len(ln);
       -                sbuf_str(ln, keymap(led_kmap, 'a'));
       +                sbuf_str(ln, kmap_map(led_kmap, 'a'));
                        sbuf_str(ln, post);
                        idir = ren_pos(sbuf_buf(ln), off) -
                                ren_pos(sbuf_buf(ln), off - 1) < 0 ? -1 : +1;
       t@@ -143,10 +153,10 @@ static char *led_line(char *pref, char *post, char *ai, int ai_max, int *key, ch
                        c = term_read(-1);
                        switch (c) {
                        case TK_CTL('f'):
       -                        *kmap = kmap_farsi;
       +                        *kmap = kmap_find(conf_kmapalt());
                                continue;
                        case TK_CTL('e'):
       -                        *kmap = kmap_def;
       +                        *kmap = kmap_en;
                                continue;
                        case TK_CTL('h'):
                        case 127:
       t@@ -174,7 +184,7 @@ static char *led_line(char *pref, char *post, char *ai, int ai_max, int *key, ch
                        default:
                                if (c == '\n' || TK_INT(c))
                                        break;
       -                        sbuf_str(sb, keymap(*kmap, c));
       +                        sbuf_str(sb, kmap_map(*kmap, c));
                        }
                        if (c == '\n' || TK_INT(c))
                                break;
       t@@ -186,7 +196,7 @@ static char *led_line(char *pref, char *post, char *ai, int ai_max, int *key, ch
        /* read an ex command */
        char *led_prompt(char *pref, char *post)
        {
       -        char **kmap = kmap_def;
       +        char **kmap = kmap_en;
                char *s;
                int key;
                s = led_line(pref, post, "", 0, &key, &kmap);
 (DIR) diff --git a/ren.c b/ren.c
       t@@ -177,36 +177,26 @@ int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed)
                return 0;
        }
        
       -static struct placeholder {
       -        char *s;        /* the source character */
       -        char *d;        /* the placeholder */
       -} placeholders[] = {
       -        {"‌", "-"},
       -        {"‍", "-"},
       -        {"ْ", "ـْ"},
       -        {"ٌ", "ـٌ"},
       -        {"ٍ", "ـٍ"},
       -        {"ً", "ـً"},
       -        {"ُ", "ـُ"},
       -        {"ِ", "ـِ"},
       -        {"َ", "ـَ"},
       -        {"ّ", "ـّ"},
       -};
       -
        static char *ren_placeholder(char *s)
        {
       -        int i = 0;
       +        char *src, *dst;
       +        int wid, i;
                int c = uc_code(s);
       -        for (i = 0; i < LEN(placeholders); i++)
       -                if (uc_code(placeholders[i].s) == c)
       -                        return placeholders[i].d;
       +        for (i = 0; !conf_placeholder(i, &src, &dst, &wid); i++)
       +                if (uc_code(src) == c)
       +                        return dst;
                return NULL;
        }
        
        int ren_cwid(char *s, int pos)
        {
       +        char *src, *dst;
       +        int wid, i;
                if (s[0] == '\t')
                        return 8 - (pos & 7);
       +        for (i = 0; !conf_placeholder(i, &src, &dst, &wid); i++)
       +                if (uc_code(src) == uc_code(s))
       +                        return wid;
                return 1;
        }
        
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -32,7 +32,7 @@ static void vi_draw(void)
                term_record();
                for (i = xtop; i < xtop + xrows; i++) {
                        char *s = lbuf_get(xb, i);
       -                led_print(s ? s : "~", i - xtop);
       +                led_print(s ? s : (i ? "~" : ""), i - xtop);
                }
                vi_drawmsg();
                term_pos(xrow, led_pos(lbuf_get(xb, i), xcol));
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -124,6 +124,12 @@ void ex_show(char *msg);
        /* process management */
        char *cmd_pipe(char *cmd, char *s);
        
       +/* 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);
       +
        /* global variables */
        #define PATHLEN                512