tsyn: nested and overlapping highlighting regions - 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 ba371ba7ddd6c24a7b8fd605de5143a45486cb74
 (DIR) parent e3d2ac66bd83987579f970043be6e6c31b29dd19
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Sun,  7 Jun 2015 11:32:53 +0430
       
       syn: nested and overlapping highlighting regions
       
       Diffstat:
         M conf.c                              |       6 +++---
         M conf.h                              |      32 +++++++++++++++++--------------
         M led.c                               |       7 -------
         M syn.c                               |      35 ++++++++++++++++++++++---------
         M vi.h                                |       3 ++-
       
       5 files changed, 48 insertions(+), 35 deletions(-)
       ---
 (DIR) diff --git a/conf.c b/conf.c
       t@@ -46,7 +46,7 @@ int conf_placeholder(int idx, char **s, char **d, int *wid)
                return 0;
        }
        
       -int conf_highlight(int idx, char **ft, int *att, int *grp, char **pat)
       +int conf_highlight(int idx, char **ft, int **att, char **pat, int *end)
        {
                if (idx < 0 || idx >= LEN(highlights))
                        return 1;
       t@@ -54,10 +54,10 @@ int conf_highlight(int idx, char **ft, int *att, int *grp, char **pat)
                        *ft = highlights[idx].ft;
                if (att)
                        *att = highlights[idx].att;
       -        if (grp)
       -                *grp = highlights[idx].grp;
                if (pat)
                        *pat = highlights[idx].pat;
       +        if (end)
       +                *end = highlights[idx].end;
                return 0;
        }
        
 (DIR) diff --git a/conf.h b/conf.h
       t@@ -56,28 +56,32 @@ static struct filetype {
                char *pat;                /* file name pattern */
        } filetypes[] = {
                {"c", "\\.[hc]$"},
       -        {"tr", "\\.(ms|tr|roff)$"},
       +        {"tr", "\\.(ms|tr|roff|tmac)$"},
        };
        
        /* syntax highlighting patterns */
        static struct highlight {
                char *ft;                /* the filetype of this pattern */
       -        int att;                /* attributes of the matched region */
       -        int grp;                /* regular expression subgroup to highlight */
       +        int att[16];                /* attributes of the matched groups */
                char *pat;                /* regular expression */
       +        int end;                /* the group ending this pattern */
        } highlights[] = {
       -        {"c", 5, 0, "\\<(signed|unsigned|char|short|int|long|float|double|void|struct|enum|union|typedef)\\>"},
       -        {"c", 5, 0, "\\<(static|extern|register)\\>"},
       -        {"c", 5, 0, "\\<(return|for|while|if|else|do|sizeof|goto|switch|case|default|break|continue)\\>"},
       -        {"c", 2 | SYN_IT, 0, "//.*$"},
       -        {"c", 2 | SYN_IT, 0, "/\\*([^*]|\\*[^/])*\\*/"},
       -        {"c", 6, 0, "^#[ \t]*[a-zA-Z0-9_]+"},
       -        {"c", SYN_BD, 1, "([a-zA-Z][a-zA-Z0-9_]+)\\("},
       -        {"c", 4, 0, "\"([^\"]|\\\\\")*\""},
       -        {"c", 4, 0, "'([^\\]|\\\\.)'"},
       +        {"c", {5}, "\\<(signed|unsigned|char|short|int|long|float|double|void|struct|enum|union|typedef)\\>"},
       +        {"c", {5}, "\\<(static|extern|register)\\>"},
       +        {"c", {4}, "\\<(return|for|while|if|else|do|sizeof|goto|switch|case|default|break|continue)\\>"},
       +        {"c", {2 | SYN_IT}, "//.*$"},
       +        {"c", {2 | SYN_IT}, "/\\*([^*]|\\*[^/])*\\*/"},
       +        {"c", {6}, "^#[ \t]*[a-zA-Z0-9_]+"},
       +        {"c", {0, SYN_BD}, "([a-zA-Z][a-zA-Z0-9_]+)\\(", 1},
       +        {"c", {4}, "\"([^\"]|\\\\\")*\""},
       +        {"c", {4}, "'([^\\]|\\\\.)'"},
        
       -        {"tr", SYN_BD, 0, "^\\.SH.*$"},
       -        {"tr", 4, 0, "^\\.[a-zA-Z0-9]{2}.*$"},
       +        {"tr", {4, 0, 5 | SYN_BD, 4 | SYN_BD, 5 | SYN_BD, 4 | SYN_BD},
       +                "^[.'][ \t]*((SH.*)|(de) (.*)|([^ \t\\]{2,}))?.*$", 1},
       +        {"tr", {2 | SYN_IT}, "\\\\\".*$"},
       +        {"tr", {3}, "\\\\{1,2}[*$fgkmns]([^[(]|\\(..|\\[[^]]*\\])"},
       +        {"tr", {3}, "\\\\([^[(*$fgkmns]|\\(..|\\[[^]]*\\])"},
       +        {"tr", {3}, "\\$[^$]+\\$"},
        };
        
        /* how to hightlight text in the reverse direction */
 (DIR) diff --git a/led.c b/led.c
       t@@ -45,13 +45,6 @@ static int led_offdir(char **chrs, int *pos, int i)
                return 0;
        }
        
       -static int syn_merge(int old, int new)
       -{
       -        int fg = SYN_FG(new) ? SYN_FG(new) : SYN_FG(old);
       -        int bg = SYN_BG(new) ? SYN_BG(new) : SYN_BG(old);
       -        return fg | SYN_BGMK(bg);
       -}
       -
        static void led_markrev(int n, char **chrs, int *pos, int *att)
        {
                int i = 0, j;
 (DIR) diff --git a/syn.c b/syn.c
       t@@ -22,6 +22,14 @@ static struct rset *syn_find(char *ft)
                return NULL;
        }
        
       +int syn_merge(int old, int new)
       +{
       +        int fg = SYN_FG(new) ? SYN_FG(new) : SYN_FG(old);
       +        int bg = SYN_BG(new) ? SYN_BG(new) : SYN_BG(old);
       +        int flg = (old | new) & (SYN_IT | SYN_BD | SYN_RV);
       +        return flg | fg | SYN_BGMK(bg);
       +}
       +
        int *syn_highlight(char *ft, char *s)
        {
                int subs[16 * 2];
       t@@ -30,19 +38,26 @@ int *syn_highlight(char *ft, char *s)
                int sidx = 0;
                struct rset *rs = syn_find(ft);
                int flg = 0;
       -        int hl, j;
       +        int hl, j, i;
                memset(att, 0, n * sizeof(att[0]));
                if (!rs)
                        return att;
                while ((hl = rset_find(rs, s + sidx, LEN(subs) / 2, subs, flg)) >= 0) {
       -                int beg, end;
       -                int catt, cgrp;
       -                conf_highlight(hl, NULL, &catt, &cgrp, NULL);
       -                beg = uc_off(s, sidx + subs[cgrp * 2 + 0]);
       -                end = uc_off(s, sidx + subs[cgrp * 2 + 1]);
       -                for (j = beg; j < end; j++)
       -                        att[j] = catt;
       -                sidx += subs[cgrp * 2 + 1] ? subs[cgrp * 2 + 1] : 1;
       +                int grp = 0;
       +                int cend = 1;
       +                int *catt;
       +                conf_highlight(hl, NULL, &catt, NULL, &grp);
       +                for (i = 0; i < LEN(subs) / 2; i++) {
       +                        if (subs[i * 2] >= 0) {
       +                                int beg = uc_off(s, sidx + subs[i * 2 + 0]);
       +                                int end = uc_off(s, sidx + subs[i * 2 + 1]);
       +                                for (j = beg; j < end; j++)
       +                                        att[j] = syn_merge(att[j], catt[i]);
       +                                if (i == grp)
       +                                        cend = MAX(cend, subs[i * 2 + 1]);
       +                        }
       +                }
       +                sidx += cend;
                        flg = RE_NOTBOL;
                }
                return att;
       t@@ -53,7 +68,7 @@ static void syn_initft(char *name)
                char *pats[128] = {NULL};
                char *ft, *pat;
                int i, n;
       -        for (i = 0; !conf_highlight(i, &ft, NULL, NULL, &pat) && i < LEN(pats); i++)
       +        for (i = 0; !conf_highlight(i, &ft, NULL, &pat, NULL) && i < LEN(pats); i++)
                        if (!strcmp(ft, name))
                                pats[i] = pat;
                n = i;
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -157,6 +157,7 @@ int cmd_exec(char *cmd);
        
        int *syn_highlight(char *ft, char *s);
        char *syn_filetype(char *path);
       +int syn_merge(int old, int new);
        void syn_init(void);
        void syn_done(void);
        
       t@@ -165,7 +166,7 @@ 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, int *grp, char **pat);
       +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);