qemacs-commit
[Top][All Lists]
Advanced

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

[Qemacs-commit] qemacs util.c qe.h extra-modes.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs util.c qe.h extra-modes.c
Date: Fri, 07 Mar 2014 10:26:00 +0000

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        14/03/07 10:26:00

Modified files:
        .              : util.c qe.h extra-modes.c 

Log message:
        add haskell-mode
        
        * detect haskell files on extension: *.hs
        * fix small things
        * add qe_findchar(str, c) to search code point in ascii string

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/util.c?cvsroot=qemacs&r1=1.62&r2=1.63
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.145&r2=1.146
http://cvs.savannah.gnu.org/viewcvs/qemacs/extra-modes.c?cvsroot=qemacs&r1=1.2&r2=1.3

Patches:
Index: util.c
===================================================================
RCS file: /sources/qemacs/qemacs/util.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -b -r1.62 -r1.63
--- util.c      7 Feb 2014 07:38:31 -0000       1.62
+++ util.c      7 Mar 2014 10:25:59 -0000       1.63
@@ -207,8 +207,10 @@
 void canonicalize_path(char *buf, int buf_size, const char *path)
 {
     const char *p;
+
     /* check for URL protocol or windows drive */
     /* CG: should not skip '/' */
+    /* XXX: bogus if filename contains ':' */
     p = strchr(path, ':');
     if (p) {
         if ((p - path) == 1) {
@@ -232,6 +234,7 @@
 {
     const char *p;
 
+    /* XXX: should only accept 'drive:' and 'proto:' */
     p = strchr(path, ':');
     if (p)
         p++;

Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.145
retrieving revision 1.146
diff -u -b -r1.145 -r1.146
--- qe.h        6 Mar 2014 20:36:50 -0000       1.145
+++ qe.h        7 Mar 2014 10:25:59 -0000       1.146
@@ -276,6 +276,10 @@
     return (qe_inrange(c, 'A', 'Z') ? c + 'a' - 'A' : c);
 }
 
+static int inline qe_findchar(const char *str, int c) {
+    return qe_inrange(c, 1, 255) && strchr(str, c);
+}
+
 int qe_strcollate(const char *s1, const char *s2);
 void qe_strtolower(char *buf, int buf_size, const char *str);
 void skip_spaces(const char **pp);
@@ -1918,6 +1922,13 @@
                    ModeSavedData *saved_data,
                    int is_html, const char *default_stylesheet);
 
+/* extra-modes.c */
+
+void lua_colorize_line(unsigned int *buf, int len,
+                       int *colorize_state_ptr, int state_only);
+void haskell_colorize_line(unsigned int *buf, int len,
+                           int *colorize_state_ptr, int state_only);
+
 /* image.c */
 
 void fill_border(EditState *s, int x, int y, int w, int h, int color);

Index: extra-modes.c
===================================================================
RCS file: /sources/qemacs/qemacs/extra-modes.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- extra-modes.c       7 Mar 2014 02:24:14 -0000       1.2
+++ extra-modes.c       7 Mar 2014 10:26:00 -0000       1.3
@@ -290,7 +290,7 @@
         if (qe_isalpha_(str[i])) {
             for (j = i + 1; j < n; j++) {
                 if (!qe_isalnum_(str[j])) {
-                    if (strchr("$&address@hidden", str[j]))
+                    if (qe_findchar("$&address@hidden", str[j]))
                         j++;
                     break;
                 }
@@ -693,7 +693,7 @@
     PS_IDENTIFIER =   QE_STYLE_FUNCTION,
 };
 
-#define ispssep(c)      (strchr(" \t\r\n,()<>[]{}/", (c)) != NULL)
+#define ispssep(c)      (qe_findchar(" \t\r\n,()<>[]{}/", c))
 #define wrap 0
 
 static void ps_colorize_line(unsigned int *str, int n, int *statep,
@@ -965,7 +965,7 @@
     }
 }
 
-static void lua_colorize_line(unsigned int *str, int n, int *statep,
+void lua_colorize_line(unsigned int *str, int n, int *statep,
                               __unused__ int state_only)
 {
     int i = 0, j = i, c, sep = 0, level = 0, level1, klen, style;
@@ -1052,6 +1052,7 @@
             continue;
         default:
             if (qe_isdigit(c)) {
+                /* XXX: should parse actual number syntax */
                 for (j = i + 1; j < n; j++) {
                     if (!qe_isalnum(str[j] && str[j] != '.'))
                         break;
@@ -1125,6 +1126,245 @@
     return 0;
 }
 
+/*---------------- Haskell coloring ----------------*/
+
+static char const haskell_keywords[] = {
+    "|_|case|class|data|default|deriving|do|else|foreign"
+    "|if|import|in|infix|infixl|infixr|instance|let"
+    "|module|newtype|of|then|type|where"
+    "|"
+};
+
+#define IN_COMMENT   0x10
+#define IN_STRING    0x20
+#define IN_LEVEL     0x0F
+
+enum {
+    HASKELL_TEXT =         QE_STYLE_DEFAULT,
+    HASKELL_COMMENT =      QE_STYLE_COMMENT,
+    HASKELL_STRING =       QE_STYLE_STRING,
+    HASKELL_LONGLIT =      QE_STYLE_STRING,
+    HASKELL_NUMBER =       QE_STYLE_NUMBER,
+    HASKELL_KEYWORD =      QE_STYLE_KEYWORD,
+    HASKELL_FUNCTION =     QE_STYLE_FUNCTION,
+    HASKELL_SYMBOL =       QE_STYLE_NUMBER,
+};
+
+static inline int haskell_is_symbol(int c)
+{
+    return qe_findchar("!#$%&+./<=>address@hidden|-~:", c);
+}
+
+void haskell_colorize_line(unsigned int *str, int n, int *statep,
+                           __unused__ int state_only)
+{
+    int i = 0, j = i, c, sep = 0, level = 0, klen;
+    int state = *statep;
+    char kbuf[32];
+
+    if (state & IN_COMMENT)
+        goto parse_comment;
+
+    if (state & IN_STRING) {
+        sep = '\"';
+        state = 0;
+        while (qe_isspace(str[j]))
+            j++;
+        if (str[j] == '\\')
+            j++;
+        goto parse_string;
+    }
+
+    while (i < n) {
+        switch (c = str[i]) {
+        case '-':
+            if (str[i + 1] == '-' && !haskell_is_symbol(str[i + 2])) {
+                SET_COLOR(str, i, n, HASKELL_COMMENT);
+                i = n;
+                continue;
+            }
+            goto parse_symbol;
+        case '{':
+            if (str[i + 1] == '-') {
+                state |= IN_COMMENT;
+                goto parse_comment;
+            }
+            /* FALL THRU */
+        case '}':
+        case '(':
+        case ')':
+        case '[':
+        case ']':
+        case ',':
+        case ';':
+        case '`':
+            /* special */
+            break;
+            
+        parse_comment:
+            level = state & IN_LEVEL;
+            for (j = i; j < n; j++) {
+                if (str[i] == '{' && str[i + 1] == '-') {
+                    level++;
+                    j++;
+                    continue;
+                }
+                if (str[i] == '-' && str[i + 1] == '}') {
+                    j++;
+                    level--;
+                    if (level == 0) {
+                        j++;
+                        state &= ~IN_COMMENT;
+                        break;
+                    }
+                }
+            }
+            state &= ~IN_COMMENT;
+            state |= level & IN_COMMENT;
+            SET_COLOR(str, i, j, HASKELL_COMMENT);
+            i = j;
+            continue;
+
+        case '\'':
+        case '"':
+            /* parse string const */
+            sep = str[i];
+            j = i + 1;
+        parse_string:
+            for (; j < n;) {
+                c = str[j++];
+                if (c == '\\') {
+                    if (j == n) {
+                        if (sep == '\"') {
+                            /* XXX: should ignore whitespace */
+                            state = IN_STRING;
+                        }
+                    } else
+                    if (str[j] == '^' && j + 1 < n && str[j + 1] != sep) {
+                        j += 2;
+                    } else {
+                        j += 1;
+                    }
+                } else
+                if (c == sep) {
+                    break;
+                }
+            }
+            SET_COLOR(str, i, j, HASKELL_STRING);
+            i = j;
+            continue;
+
+        default:
+            if (qe_isdigit(c)) {
+                j = i + 1;
+                if (c == '0' && qe_tolower(str[j]) == 'o') {
+                    /* octal numbers */
+                    for (j += 1; str[j] >= '0' && str[j] < '8'; j++)
+                        continue;
+                } else
+                if (c == '0' && qe_tolower(str[j]) == 'x') {
+                    /* hexadecimal numbers */
+                    for (j += 1; qe_isxdigit(str[j]); j++)
+                        continue;
+                } else {
+                    /* decimal numbers */
+                    for (j = i + 1; qe_isdigit(str[j]); j++)
+                        continue;
+                    if (str[j] == '.' && qe_isdigit(str[j + 1])) {
+                        /* decimal floats require a digit after the '.' */
+                        for (j = i + 2; qe_isdigit(str[j]); j++)
+                            continue;
+                        if (qe_tolower(str[j]) == 'e') {
+                            int k = j + 1;
+                            if (str[k] == '+' || str[k] == '-')
+                                k++;
+                            if (qe_isdigit(str[k])) {
+                                for (j = k + 1; qe_isdigit(str[j]); j++)
+                                    continue;
+                            }
+                        }
+                    }
+                }
+                /* XXX: should detect malformed number constants */
+                SET_COLOR(str, i, j, HASKELL_NUMBER);
+                i = j;
+                continue;
+            }
+            if (qe_isalpha_(c)) {
+                for (klen = 0, j = i + 1;
+                     qe_isalnum_(str[j]) || str[j] == '\'';
+                     j++) {
+                    if (klen < countof(kbuf) - 1)
+                        kbuf[klen++] = str[j];
+                }
+                kbuf[klen] = '\0';
+
+                if (strfind(haskell_keywords, kbuf)) {
+                    SET_COLOR(str, i, j, HASKELL_KEYWORD);
+                    i = j;
+                    continue;
+                }
+                while (qe_isblank(str[j]))
+                    j++;
+                if (str[j] == '(') {
+                    SET_COLOR(str, i, j, HASKELL_FUNCTION);
+                    i = j;
+                    continue;
+                }
+                i = j;
+                continue;
+            }
+        parse_symbol:
+            if (haskell_is_symbol(c)) {
+                for (j = i + 1; haskell_is_symbol(str[j]); j++)
+                    continue;
+                SET_COLOR(str, i, j, HASKELL_SYMBOL);
+                i = j;
+                continue;
+            }
+            break;
+        }
+        i++;
+        continue;
+    }
+    *statep = state;
+}
+
+#undef IN_COMMENT
+#undef IN_STRING
+#undef IN_STRING2
+#undef IN_LONGLIT
+#undef IN_LEVEL
+
+static int haskell_mode_probe(ModeDef *mode, ModeProbeData *p)
+{
+    if (match_extension(p->filename, mode->extensions))
+        return 80;
+
+    return 1;
+}
+
+static CmdDef haskell_commands[] = {
+    CMD_DEF_END,
+};
+
+static ModeDef haskell_mode;
+
+static int haskell_init(void)
+{
+    /* haskell mode is almost like the text mode, so we copy and patch it */
+    memcpy(&haskell_mode, &text_mode, sizeof(ModeDef));
+    haskell_mode.name = "Haskell";
+    haskell_mode.extensions = "hs|haskell";
+    haskell_mode.mode_probe = haskell_mode_probe;
+    haskell_mode.colorize_func = haskell_colorize_line;
+
+    qe_register_mode(&haskell_mode);
+    qe_register_cmd_table(haskell_commands, &haskell_mode);
+
+    return 0;
+}
+
 /*----------------*/
 
 static int extra_modes_init(void)
@@ -1136,6 +1376,7 @@
     ps_init();
     sql_init();
     lua_init();
+    haskell_init();
     return 0;
 }
 



reply via email to

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