qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs clang.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs clang.c
Date: Tue, 13 Dec 2016 09:10:47 +0000 (UTC)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        16/12/13 09:10:47

Modified files:
        .              : clang.c 

Log message:
        added js specific colorizer for speed on large json files

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/clang.c?cvsroot=qemacs&r1=1.108&r2=1.109

Patches:
Index: clang.c
===================================================================
RCS file: /sources/qemacs/qemacs/clang.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -b -r1.108 -r1.109
--- clang.c     26 Nov 2016 11:01:55 -0000      1.108
+++ clang.c     13 Dec 2016 09:10:47 -0000      1.109
@@ -773,6 +773,7 @@
         line_num--;
         offsetl = eb_prev_line(s->b, offsetl);
         offset1 = offsetl;
+        /* XXX: deal with truncation */
         len = s->get_colorized_line(s, buf, countof(buf), &offset1, line_num);
         /* store indent position */
         pos1 = find_indent1(s, buf);
@@ -897,6 +898,7 @@
   end_parse:
     /* compute special cases which depend on the chars on the current line */
     offset1 = offset;
+    /* XXX: deal with truncation */
     len = s->get_colorized_line(s, buf, countof(buf), &offset1, line_num1);
 
     if (stack_ptr == 0) {
@@ -1441,11 +1443,249 @@
     "void|var|"
 };
 
+static int get_js_identifier(char *buf, int buf_size, unsigned int *p)
+{
+    unsigned int c;
+    int i, j;
+
+    i = j = 0;
+    c = p[i];
+    if (qe_isalpha_(c) || c == '$') {
+        for (;;) {
+            if (j < buf_size - 1)
+                buf[j++] = (c < 0xFF) ? c : 0xFF;
+            i++;
+            c = p[i];
+            if (!qe_isalnum_(c))
+                break;
+        }
+    }
+    buf[j] = '\0';
+    return i;
+}
+
+static void js_colorize_line(QEColorizeContext *cp,
+                             unsigned int *str, int n, ModeDef *syn)
+{
+    int i = 0, start, i1, indent;
+    int c, style, type_decl, klen, delim, prev;
+    char kbuf[32];
+    int mode_flags = syn->colorize_flags;
+    int flavor = (mode_flags & CLANG_FLAVOR);
+    int state = cp->colorize_state;
+
+    indent = 0;
+    //for (; qe_isblank(str[indent]); indent++) continue;
+
+    start = i;
+    type_decl = 0;
+    c = 0;
+    style = 0;
+
+    if (i >= n)
+        goto the_end;
+
+    if (state) {
+        /* if already in a state, go directly in the code parsing it */
+        if (state & IN_C_COMMENT)
+            goto parse_comment;
+        if (state & IN_C_STRING)
+            goto parse_string;
+        if (state & IN_C_STRING_Q)
+            goto parse_string_q;
+        if (state & IN_C_REGEX) {
+            delim = '/';
+            goto parse_regex;
+        }
+    }
+
+    while (i < n) {
+        start = i;
+        c = str[i++];
+
+        switch (c) {
+        case '/':
+            if (str[i] == '*') {
+                /* C style multi-line comment */
+                i++;
+            parse_comment:
+                style = C_STYLE_COMMENT;
+                state |= IN_C_COMMENT;
+                for (; i < n; i++) {
+                    if (str[i] == '*' && str[i + 1] == '/') {
+                        i += 2;
+                        state &= ~IN_C_COMMENT;
+                        break;
+                    }
+                }
+                break;
+            } else
+            if (str[i] == '/') {
+                /* line comment */
+            parse_comment1:
+                style = C_STYLE_COMMENT;
+                state |= IN_C_COMMENT1;
+                i = n;
+                break;
+            }
+            /* XXX: should use more context to tell regex from divide */
+            prev = ' ';
+            for (i1 = start; i1 > indent; ) {
+                prev = str[--i1] & CHAR_MASK;
+                if (!qe_isblank(prev))
+                    break;
+            }
+            if ((mode_flags & CLANG_REGEX)
+            &&  (qe_findchar(" [({},;=<>!~^&|*/%?:", prev)
+            ||   (str[i1] >> STYLE_SHIFT) == C_STYLE_KEYWORD
+            ||   (str[i] != ' ' && (str[i] != '=' || str[i + 1] != ' ')
+            &&    !(qe_isalnum(prev) || prev == ')')))) {
+                /* parse regex */
+                state |= IN_C_REGEX;
+                delim = '/';
+            parse_regex:
+                style = C_STYLE_REGEX;
+                while (i < n) {
+                    c = str[i++];
+                    if (c == '\\') {
+                        if (i < n) {
+                            i += 1;
+                        }
+                    } else
+                    if (state & IN_C_CHARCLASS) {
+                        if (c == ']') {
+                            state &= ~IN_C_CHARCLASS;
+                        }
+                        /* ECMA 5: ignore '/' inside char classes */
+                    } else {
+                        if (c == '[') {
+                            state |= IN_C_CHARCLASS;
+                        } else
+                        if (c == delim) {
+                            while (qe_isalnum_(str[i])) {
+                                i++;
+                            }
+                            state &= ~IN_C_REGEX;
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+            continue;
+        case '#':       /* preprocessor */
+            if (start == 0 && str[i] == '!') {
+                /* recognize a shebang comment line */
+                style = C_STYLE_PREPROCESS;
+                i = n;
+                break;
+            }
+            continue;
+        case '\'':      /* character constant */
+        parse_string_q:
+            state |= IN_C_STRING_Q;
+            style = C_STYLE_STRING_Q;
+            delim = '\'';
+            goto string;
+
+        case '\"':      /* string literal */
+        parse_string:
+            state |= IN_C_STRING;
+            style = C_STYLE_STRING;
+            delim = '\"';
+        string:
+            while (i < n) {
+                c = str[i++];
+                if (c == '\\') {
+                    if (i >= n)
+                        break;
+                    i++;
+                } else
+                if (c == delim) {
+                    state &= ~(IN_C_STRING | IN_C_STRING_Q);
+                    break;
+                }
+            }
+            break;
+        case '=':
+            /* exit type declaration */
+            /* does not handle this: int i = 1, j = 2; */
+            type_decl = 0;
+            continue;
+        case '<':       /* JavaScript extension */
+            if (flavor == CLANG_JS) {
+                if (str[i] == '!' && str[i + 1] == '-' && str[i + 2] == '-')
+                    goto parse_comment1;
+            }
+            continue;
+        default:
+            if (qe_isdigit(c)) {
+                /* XXX: should parse actual number syntax */
+                /* maybe ignore '_' in integers */
+                /* XXX: should parse decimal and hex floating point syntaxes */
+                while (qe_isalnum_(str[i]) || str[i] == '.') {
+                    i++;
+                }
+                style = C_STYLE_NUMBER;
+                break;
+            }
+            if (qe_isalpha_(c) || c == '$') {
+                klen = get_js_identifier(kbuf, countof(kbuf), str + start);
+                i = start + klen;
+
+                if (cp->state_only)
+                    continue;
+
+                if (strfind(syn->keywords, kbuf)) {
+                    style = C_STYLE_KEYWORD;
+                    break;
+                }
+
+                i1 = i;
+                while (qe_isblank(str[i1]))
+                    i1++;
+
+                if (str[i1] == '(') {
+                    /* function call */
+                    style = C_STYLE_FUNCTION;
+                    break;
+                }
+                if ((start == 0 || str[start - 1] != '.')
+                &&  !qe_findchar(".(:", str[i])
+                &&  strfind(syn->types, kbuf)) {
+                    /* if not cast, assume type declaration */
+                    type_decl = 1;
+                    style = C_STYLE_TYPE;
+                    break;
+                }
+                continue;
+            }
+            continue;
+        }
+        if (style) {
+            if (!cp->state_only) {
+                SET_COLOR(str, start, i, style);
+            }
+            style = 0;
+        }
+    }
+ the_end:
+    if (state & (IN_C_COMMENT | IN_C_COMMENT1 | IN_C_STRING | IN_C_STRING_Q)) {
+        /* set style on eol char */
+        SET_COLOR1(str, n, style);
+    }
+
+    /* strip state if not overflowing from a comment */
+    state &= ~IN_C_COMMENT1;
+
+    cp->colorize_state = state;
+}
+
 ModeDef js_mode = {
     .name = "Javascript",
     .extensions = "js",
     .shell_handlers = "node",
-    .colorize_func = c_colorize_line,
+    .colorize_func = js_colorize_line,
     .colorize_flags = CLANG_JS | CLANG_REGEX,
     .keywords = js_keywords,
     .types = js_types,
@@ -1456,6 +1696,14 @@
 
 /*---------------- JSON data format ----------------*/
 
+static const char json_keywords[] = {
+    "null|true|false|NaN"
+};
+
+static const char json_types[] = {
+    ""
+};
+
 static int json_mode_probe(ModeDef *mode, ModeProbeData *pd)
 {
     const char *p = cs8(pd->buf);
@@ -1476,10 +1724,10 @@
     .name = "json",
     .extensions = "json",
     .mode_probe = json_mode_probe,
-    .colorize_func = c_colorize_line,
+    .colorize_func = js_colorize_line,
     .colorize_flags = CLANG_JSON,
-    .keywords = js_keywords,
-    .types = js_types,
+    .keywords = json_keywords,
+    .types = json_types,
     .indent_func = c_indent_line,
     .auto_indent = 1,
     .fallback = &c_mode,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]