qemacs-commit
[Top][All Lists]
Advanced

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

[Qemacs-commit] qemacs extra-modes.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs extra-modes.c
Date: Sun, 13 Apr 2014 14:47:14 +0000

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        14/04/13 14:47:14

Modified files:
        .              : extra-modes.c 

Log message:
        add colorizing mode for ocaml

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/extra-modes.c?cvsroot=qemacs&r1=1.14&r2=1.15

Patches:
Index: extra-modes.c
===================================================================
RCS file: /sources/qemacs/qemacs/extra-modes.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- extra-modes.c       10 Apr 2014 08:01:50 -0000      1.14
+++ extra-modes.c       13 Apr 2014 14:47:14 -0000      1.15
@@ -21,6 +21,29 @@
 #include "qe.h"
 
 #define MAX_KEYWORD_SIZE  16
+
+static int is_keyword(unsigned int *str, int from, int to, const char *list)
+{
+    char keyword[MAX_KEYWORD_SIZE];
+    int c, i, len = to - from;
+
+    if (len >= MAX_KEYWORD_SIZE)
+        return 0;
+
+    for (i = 0; i < len; i++) {
+        c = str[from + i];
+        if (c >= 0x80)
+            return 0;
+        keyword[i] = c;
+    }
+    keyword[len] = '\0';
+
+    if (strfind(list, keyword))
+        return 1;
+
+    return 0;
+}
+
 static int is_lc_keyword(unsigned int *str, int from, int to, const char *list)
 {
     char keyword[MAX_KEYWORD_SIZE];
@@ -737,9 +760,10 @@
                 continue;
             }
             style = PASCAL_STYLE_IDENTIFIER;
-            for (k = i; qe_isblank(str[k]); k++)
-                continue;
-            if (str[k] == '(')
+            k = i;
+            if (qe_isblank(str[k]))
+                k++;
+            if (str[k] == '(' && str[k + 1] != '*')
                 style = PASCAL_STYLE_FUNCTION;
             SET_COLOR(str, start, i, style);
             continue;
@@ -2199,17 +2223,17 @@
             if (qe_isdigit(c)) {
                 if (c == '0' && qe_tolower(str[i]) == 'b') {
                     /* binary numbers */
-                    for (i += 1; qe_isbindigit(str[i]) || str[i] == '_'; i++)
+                    for (i += 1; qe_isbindigit_(str[i]); i++)
                         continue;
                 } else
                 if (c == '0' && qe_tolower(str[i]) == 'o') {
                     /* octal numbers */
-                    for (i += 1; qe_isoctdigit(str[i]) || str[i] == '_'; i++)
+                    for (i += 1; qe_isoctdigit_(str[i]); i++)
                         continue;
                 } else
                 if (c == '0' && qe_tolower(str[i]) == 'x') {
                     /* hexadecimal numbers */
-                    for (i += 1; qe_isxdigit(str[i]) || str[i] == '_'; i++)
+                    for (i += 1; qe_isxdigit_(str[i]); i++)
                         continue;
                 } else
                 if (c == '0' && qe_tolower(str[i]) == 'd') {
@@ -2292,6 +2316,236 @@
     return 0;
 }
 
+/*---------------- ML/Ocaml coloring ----------------*/
+
+static char const ocaml_keywords[] = {
+    "|_|and|as|asr|assert|begin|class|constraint|do|done|downto"
+    "|else|end|exception|external|false|for|fun|function|functor"
+    "|if|ignore|in|include|incr|inherit|initializer"
+    "|land|lazy|let|lnot|loop|lor|lsl|lsr|lxor"
+    "|match|method|mod|module|mutable|new|not|object|of|open|or"
+    "|parser|prec|private|raise|rec|ref|self|sig|struct"
+    "|then|to|true|try|type|value|virtual|when|while|with"
+    "|"
+};
+
+static char const ocaml_types[] = {
+    "|array|bool|char|exn|float|format|format4||int|int32|int64"
+    "|lazy_t|list|nativeint|option|string|unit|val"
+    "|"
+};
+
+enum {
+    IN_OCAML_COMMENT  = 0x01,
+    IN_OCAML_STRING   = 0x02,
+};
+
+enum {
+    OCAML_STYLE_TEXT       = QE_STYLE_DEFAULT,
+    OCAML_STYLE_PREPROCESS = QE_STYLE_PREPROCESS,
+    OCAML_STYLE_COMMENT    = QE_STYLE_COMMENT,
+    OCAML_STYLE_STRING     = QE_STYLE_STRING,
+    OCAML_STYLE_STRING1    = QE_STYLE_STRING,
+    OCAML_STYLE_NUMBER     = QE_STYLE_NUMBER,
+    OCAML_STYLE_KEYWORD    = QE_STYLE_KEYWORD,
+    OCAML_STYLE_TYPE       = QE_STYLE_TYPE,
+    OCAML_STYLE_IDENTIFIER = QE_STYLE_DEFAULT,
+    OCAML_STYLE_FUNCTION   = QE_STYLE_FUNCTION,
+};
+
+static void ocaml_colorize_line(QEColorizeContext *cp,
+                                 unsigned int *str, int n, int mode_flags)
+{
+    int i = 0, start = i, c, k, style;
+    int colstate = cp->colorize_state;
+
+    if (colstate & IN_OCAML_COMMENT)
+        goto parse_comment;
+
+    if (colstate & IN_OCAML_STRING)
+        goto parse_string;
+
+    if (str[i] == '#') {
+        /* Handle shbang script heading ^#!.+
+         * and preprocessor # line directives
+         */
+        i = n;
+        SET_COLOR(str, start, i, OCAML_STYLE_PREPROCESS);
+    }
+
+    while (i < n) {
+        start = i;
+        style = OCAML_STYLE_TEXT;
+        c = str[i++];
+        switch (c) {
+        case '(':
+            /* check for comment */
+            if (str[i] != '*')
+                break;
+
+            /* regular comment (recursive?) */
+            colstate = IN_OCAML_COMMENT;
+            i++;
+        parse_comment:
+            style = OCAML_STYLE_COMMENT;
+            for (; i < n; i++) {
+                if (str[i] == '*' && str[i + 1] == ')') {
+                    i += 2;
+                    colstate = 0;
+                    break;
+                }
+            }
+            SET_COLOR(str, start, i, style);
+            continue;
+        case '\"':
+            colstate = IN_OCAML_STRING;
+        parse_string:
+            /* parse string */
+            style = OCAML_STYLE_STRING;
+            while (i < n) {
+                c = str[i++];
+                if (c == '\\' && i < n)
+                    i++;
+                else
+                if (c == '\"') {
+                    colstate = 0;
+                    break;
+                }
+            }
+            SET_COLOR(str, start, i, style);
+            continue;
+        case '\'':
+            /* parse type atom or char const */
+            if ((i + 1 < n && str[i] != '\\' && str[i + 1] == '\'')
+            ||  (i + 2 < n && str[i] == '\\' && str[i + 2] == '\'')
+            ||  (str[i] == '\\' && str[i + 1] == 'x' &&
+                 qe_isxdigit(str[i + 2]) && qe_isxdigit(str[i + 3]) &&
+                 str[i + 4] == '\'')
+            ||  (str[i] == '\\' && qe_isdigit(str[i + 1]) &&
+                 qe_isdigit(str[i + 2]) && qe_isdigit(str[i + 3]) &&
+                 str[i + 4] == '\'')) {
+                style = OCAML_STYLE_STRING1;
+                while (str[i++] != '\'')
+                    continue;
+            } else
+            if (qe_isalpha_(str[i])) {
+                while (i < n && (qe_isalnum_(str[i]) || str[i] == '\''))
+                    i++;
+                style = OCAML_STYLE_TYPE;
+            }
+            SET_COLOR(str, start, i, style);
+            continue;
+        default:
+            break;
+        }
+        /* parse numbers */
+        if (qe_isdigit(c)) {
+            style = OCAML_STYLE_NUMBER;
+            if (c == '0' && qe_tolower(str[i]) == 'o'
+            &&  qe_isoctdigit(str[i + 1])) {
+                /* octal int: 0[oO][0-7][0-7_]*[lLn]? */
+                for (i += 1; qe_isoctdigit_(str[i]); i++)
+                    continue;
+                if (qe_findchar("lLn", str[i]))
+                    i++;
+            } else
+            if (c == '0' && qe_tolower(str[i]) == 'x'
+            &&  qe_isxdigit(str[i + 1])) {
+                /* hex int: 0[xX][0-9a-fA-F][0-9a-zA-Z_]*[lLn]? */
+                for (i += 1; qe_isxdigit(str[i]); i++)
+                    continue;
+                if (qe_findchar("lLn", str[i]))
+                    i++;
+            } else
+            if (c == '0' && qe_tolower(str[i]) == 'b'
+            &&  qe_isbindigit(str[i + 1])) {
+                /* binary int: 0[bB][01][01_]*[lLn]? */
+                for (i += 1; qe_isbindigit_(str[i]); i++)
+                    continue;
+                if (qe_findchar("lLn", str[i]))
+                    i++;
+            } else {
+                /* decimal integer: [0-9][0-9_]*[lLn]? */
+                for (; qe_isdigit_(str[i]); i++)
+                    continue;
+                if (qe_findchar("lLn", str[i])) {
+                    i++;
+                } else {
+                    /* float:
+                     * [0-9][0-9_]*(.[0-9_]*])?([eE][-+]?[0-9][0-9_]*)? */
+                    if (str[i] == '.') {
+                        for (i += 1; qe_isdigit_(str[i]); i++)
+                            continue;
+                    }
+                    if (qe_tolower(str[i]) == 'e') {
+                        int k = i + 1;
+                        if (str[k] == '+' || str[k] == '-')
+                            k++;
+                        if (qe_isdigit(str[k])) {
+                            for (i = k + 1; qe_isdigit_(str[i]); i++)
+                                continue;
+                        }
+                    }
+                }
+            }
+            SET_COLOR(str, start, i, style);
+            continue;
+        }
+        /* parse identifiers and keywords */
+        if (qe_isalpha_(c)) {
+            for (; i < n; i++) {
+                if (!qe_isalnum_(str[i]) || str[i] == '\'')
+                    break;
+            }
+            if (is_keyword(str, start, i, ocaml_types)) {
+                style = OCAML_STYLE_TYPE;
+            } else
+            if (is_keyword(str, start, i, ocaml_keywords)) {
+                style = OCAML_STYLE_KEYWORD;
+            } else {
+                style = OCAML_STYLE_IDENTIFIER;
+                k = i;
+                if (qe_isblank(str[k]))
+                    k++;
+                if (str[k] == '(' && str[k + 1] != '*')
+                    style = OCAML_STYLE_FUNCTION;
+            }
+            SET_COLOR(str, start, i, style);
+            continue;
+        }
+    }
+    cp->colorize_state = colstate;
+}
+
+static int ocaml_mode_probe(ModeDef *mode, ModeProbeData *p)
+{
+    if (match_extension(p->filename, mode->extensions))
+        return 80;
+
+    return 1;
+}
+
+static CmdDef ocaml_commands[] = {
+    CMD_DEF_END,
+};
+
+static ModeDef ocaml_mode;
+
+static int ocaml_init(void)
+{
+    /* ocaml mode is almost like the text mode, so we copy and patch it */
+    memcpy(&ocaml_mode, &text_mode, sizeof(ModeDef));
+    ocaml_mode.name = "Ocaml";
+    ocaml_mode.extensions = "ml|mli|mll|mly";
+    ocaml_mode.mode_probe = ocaml_mode_probe;
+    ocaml_mode.colorize_func = ocaml_colorize_line;
+
+    qe_register_mode(&ocaml_mode);
+    qe_register_cmd_table(ocaml_commands, &ocaml_mode);
+
+    return 0;
+}
+
 /*----------------*/
 
 static int extra_modes_init(void)
@@ -2307,6 +2561,7 @@
     haskell_init();
     python_init();
     ruby_init();
+    ocaml_init();
     return 0;
 }
 



reply via email to

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