qemacs-commit
[Top][All Lists]
Advanced

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

[Qemacs-commit] qemacs script.c extras.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs script.c extras.c
Date: Tue, 28 Mar 2017 02:33:29 -0400 (EDT)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        17/03/28 02:33:29

Modified files:
        .              : script.c extras.c 

Log message:
        shell-script-mode: 
        - renamed script-mode to shell-script-mode
        - merged patch by Hadrien Lacour
        - improve parsing, recognise names, keywords, meta-characters, 
substitutions...
        - add flexibility in forward-block (M-C-f) and backward-block (M-C-b) to
          match block delimiters with non default styles

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/script.c?cvsroot=qemacs&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/qemacs/extras.c?cvsroot=qemacs&r1=1.60&r2=1.61

Patches:
Index: script.c
===================================================================
RCS file: /sources/qemacs/qemacs/script.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- script.c    25 Mar 2017 18:15:00 -0000      1.20
+++ script.c    28 Mar 2017 06:33:29 -0000      1.21
@@ -23,89 +23,245 @@
 /*---------------- Shell script colors ----------------*/
 
 enum {
-    SCRIPT_STYLE_TEXT =       QE_STYLE_DEFAULT,
-    SCRIPT_STYLE_COMMENT =    QE_STYLE_COMMENT,
-    SCRIPT_STYLE_PREPROCESS = QE_STYLE_PREPROCESS,
-    SCRIPT_STYLE_COMMAND =    QE_STYLE_FUNCTION,
-    SCRIPT_STYLE_VARIABLE =   QE_STYLE_TYPE,
-    SCRIPT_STYLE_STRING =     QE_STYLE_STRING,
-    SCRIPT_STYLE_BACKTICK =   QE_STYLE_STRING_Q,
+    SHELL_SCRIPT_STYLE_TEXT =       QE_STYLE_DEFAULT,
+    SHELL_SCRIPT_STYLE_COMMENT =    QE_STYLE_COMMENT,
+    SHELL_SCRIPT_STYLE_PREPROCESS = QE_STYLE_PREPROCESS,
+    SHELL_SCRIPT_STYLE_COMMAND =    QE_STYLE_FUNCTION,
+    SHELL_SCRIPT_STYLE_VARIABLE =   QE_STYLE_TYPE,
+    SHELL_SCRIPT_STYLE_STRING =     QE_STYLE_STRING,
+    SHELL_SCRIPT_STYLE_OP =         QE_STYLE_KEYWORD,
+    SHELL_SCRIPT_STYLE_KEYWORD =    QE_STYLE_KEYWORD,
 };
 
-static int script_var(const unsigned int *str, int j, int n)
+static const char shell_script_keywords[] = {
+    /* reserved words */
+    "if|then|elif|else|fi|case|esac|for|while|until|do|done|shift|"
+    "function|return|export|alias|in|select|time|"
+    /* internal commands */
+    //"cd|echo|umask|"
+};
+
+static int shell_script_get_var(char *buf, int buf_size,
+                                unsigned int *str, int j, int n)
 {
-    for (; j < n; j++) {
-        if (qe_isalnum_(str[j]) || str[j] == '-')
-            continue;
-        break;
+    int i = 0, c;
+
+    while (j < n && qe_isalnum_(c = str[j])) {
+        if (i < buf_size - 1) {
+            buf[i++] = c;
+        }
+        j++;
+    }
+    if (i < buf_size) {
+        buf[i] = '\0';
     }
     return j;
 }
 
-static void script_colorize_line(QEColorizeContext *cp,
+static int shell_script_string(unsigned int *str, int i, int n,
+                               int sep, int escape, int dollar)
+{
+    while (i < n) {
+        int c = str[i++];
+        if (c == '\\' && escape && i < n) {
+            i++;
+        } else
+        if (c == '$' && dollar && i < n) {
+            /* XXX: should highlight variable substitutions */ 
+            i++;
+        } else
+        if (c == sep) {
+            break;
+        }
+    }
+    return i;
+}
+
+static void shell_script_colorize_line(QEColorizeContext *cp,
                                  unsigned int *str, int n, ModeDef *syn)
 {
-    int i = 0, j, c, start, style;
+    int i = 0, j, c, start, style, bits = 0;
 
-    style = SCRIPT_STYLE_COMMAND;
+start_cmd:
+    style = SHELL_SCRIPT_STYLE_COMMAND;
+    while (i < n  && qe_isblank(str[i])) {
+        i++;
+    }
 
     while (i < n) {
         start = i;
-        switch (str[i]) {
+        switch (c = str[i++]) {
         case '#':
-            if (i > 0 && str[i - 1] == '$')
-                break;
-            style = SCRIPT_STYLE_COMMENT;
-            if (str[i + 1] == '!')
-                style = SCRIPT_STYLE_PREPROCESS;
+            style = SHELL_SCRIPT_STYLE_COMMENT;
+            if (start == 0 && str[i] == '!') {
+                /* use special style for sh-bang line */
+                style = SHELL_SCRIPT_STYLE_PREPROCESS;
+            }
             i = n;
-            SET_COLOR(str, start, i, style);
-            continue;
+            break;
         case '`':
-            style = SCRIPT_STYLE_BACKTICK;
-            goto has_string;
+            /* XXX: should be a state */
+            SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+            goto start_cmd;
         case '\'':
+            i = shell_script_string(str, i, n, c, 0, 0);
+            SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_STRING);
+            /* XXX: should support multi-line strings? */
+            continue;
         case '"':
-            style = SCRIPT_STYLE_STRING;
-        has_string:
-            /* parse string const */
-            for (i++; i < n;) {
-                c = str[i++];
-                if (c == '\\' && i < n && str[start] == '"')
+            i = shell_script_string(str, i, n, c, 1, 1);
+            SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_STRING);
+            /* XXX: should support multi-line strings? */
+            continue;
+        case '\\':
+            if (i >= n) {
+                /* Should keep state for next line */
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                continue;
+            }
+            /* Do not interpret the next character */
                     i++;
-                else
-                if ((unsigned int)c == str[start])
+            break;
+        case '$':
+            if (i == n || qe_findchar(" \t'\"", str[i]))
+                break;
+            SET_COLOR1(str, start++, SHELL_SCRIPT_STYLE_OP);
+                       switch (c = str[i++]) {
+            case '\'':
+                i = shell_script_string(str, i, n, c, 1, 0);
+                SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_STRING);
+                continue;
+            case '(':  /* expand command output */
+                bits = (bits << 2) | 1;
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                goto start_cmd;
+            case '[':  /* expression */
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                for (j = i; i < n; i++) {
+                    if (str[i] == ']')
                     break;
             }
-            SET_COLOR(str, start, i, style);
-            if (i < n)
-                style = SCRIPT_STYLE_TEXT;
+                SET_COLOR(str, j, i, SHELL_SCRIPT_STYLE_TEXT);
+                if (i < n) {
+                    i++;
+                    SET_COLOR(str, i - 1, i, SHELL_SCRIPT_STYLE_OP);
+                }
+                continue;
+            case '{':  /* variable name */
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                /* XXX: should parse variable name or single char */
+                /* XXX: should support % syntax with regex */
+                for (j = i; i < n; i++) {
+                    if (str[i] == '}')
+                        break;
+                }
+                SET_COLOR(str, j, i, SHELL_SCRIPT_STYLE_VARIABLE);
+                if (i < n) {
+                    i++;
+                    SET_COLOR(str, i - 1, i, SHELL_SCRIPT_STYLE_OP);
+                }
+                continue;
+            case '$':
+            case '?':
+            case '#':
+            default:
+                if (qe_isalpha_(c)) {
+                    i = shell_script_get_var(NULL, 0, str, i, n);
+                    SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_VARIABLE);
+                } else {
+                    SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                }
+                continue;
+            }
             continue;
         case ' ':
         case '\t':
+                       style = SHELL_SCRIPT_STYLE_TEXT;
+            break;
+        case '{':  /* compound command */
+        case '}':
+            /* XXX: should support numeric enumerations */
+            if (i == n || qe_isblank(str[i])) {
+                SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_OP);
+                goto start_cmd;
+            }
+                       style = SHELL_SCRIPT_STYLE_TEXT;
             break;
+        case '>':
+        case '<':
+            // XXX: Should support other punctuation syntaxes
+            if (str[i] == (unsigned int)c) {  /* handle >> and << */
+                i++;
+            }
+            SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_OP);
+            // XXX: Should support << syntax
+                       style = SHELL_SCRIPT_STYLE_TEXT;
+            continue;
+        case '|':
+        case '&':
+            if (str[i] == (unsigned int)c) {  /* handle || and && */
+                i++;
+            }
+            SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_OP);
+            goto start_cmd;
+        case ';':
+            SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+            goto start_cmd;
+        case '(':
+            bits = (bits << 2) | 2;
+            SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+            goto start_cmd;
+        case ')':
+            bits = (bits >> 2);
+            SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+            goto start_cmd;
+        case '[':
+            if (style == SHELL_SCRIPT_STYLE_COMMAND) {
+                bits = (bits << 2) | 3;
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                style = SHELL_SCRIPT_STYLE_TEXT;
+                continue;
+            }
+            break;
+        case ']':
+            if ((bits & 3) == 3) {
+                bits = (bits >> 2);
+                SET_COLOR1(str, start, SHELL_SCRIPT_STYLE_OP);
+                style = SHELL_SCRIPT_STYLE_TEXT;
+                continue;
+            }
+            break;
+
         default:
-            i = script_var(str, i, n);
-            if (i > start) {
-                j = i;
-                while (qe_isblank(str[j]))
+            if (style == SHELL_SCRIPT_STYLE_COMMAND && qe_isalpha_(c)) {
+                char kbuf[64];
+
+                i = shell_script_get_var(kbuf, sizeof kbuf, str, i - 1, n);
+                if (strfind(syn->keywords, kbuf)) {
+                    SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_KEYWORD);
+                    if (strfind("function|export|alias|if|elif|while", kbuf))
+                        goto start_cmd;
+                    else
+                        continue;
+                }
+                for (j = i; qe_isblank(str[j]); j++)
+                    continue;
+                if (str[j] == '=') {
                     j++;
-                if (str[j] == '=')
-                    style = SCRIPT_STYLE_VARIABLE;
-                SET_COLOR(str, start, i, style);
-                style = SCRIPT_STYLE_TEXT;
+                    SET_COLOR(str, start, i, SHELL_SCRIPT_STYLE_VARIABLE);
+                    SET_COLOR(str, i, j, SHELL_SCRIPT_STYLE_OP);
+                    i = j;
+                    style = SHELL_SCRIPT_STYLE_TEXT;
                 continue;
             }
-            // Should support << syntax
-            // Should support $ syntax
-            style = SCRIPT_STYLE_TEXT;
+            }
             break;
         }
-        i++;
+        SET_COLOR(str, start, i, style);
     }
 }
 
-static int script_mode_probe(ModeDef *mode, ModeProbeData *p)
+static int shell_script_mode_probe(ModeDef *mode, ModeProbeData *p)
 {
     if (match_extension(p->filename, mode->extensions)
     ||  match_shell_handler(cs8(p->buf), mode->shell_handlers)
@@ -123,19 +279,21 @@
     return 1;
 }
 
-static ModeDef script_mode = {
+/* XXX: should have shell specific variations */
+static ModeDef shell_script_mode = {
     .name = "Shell-script",
     .extensions = "sh|bash|csh|ksh|zsh",
     .shell_handlers = "sh|bash|csh|ksh|zsh",
-    .mode_probe = script_mode_probe,
-    .colorize_func = script_colorize_line,
+    .mode_probe = shell_script_mode_probe,
+    .colorize_func = shell_script_colorize_line,
+    .keywords = shell_script_keywords,
 };
 
-static int script_init(void)
+static int shell_script_init(void)
 {
-    qe_register_mode(&script_mode, MODEF_SYNTAX);
+    qe_register_mode(&shell_script_mode, MODEF_SYNTAX);
 
     return 0;
 }
 
-qe_module_init(script_init);
+qe_module_init(shell_script_init);

Index: extras.c
===================================================================
RCS file: /sources/qemacs/qemacs/extras.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -b -r1.60 -r1.61
--- extras.c    26 Mar 2017 15:57:24 -0000      1.60
+++ extras.c    28 Mar 2017 06:33:29 -0000      1.61
@@ -550,7 +550,7 @@
             if (pos >= 0 && pos < len) {
                 style = buf[pos] >> STYLE_SHIFT;
             }
-            if (style != style0) {
+            if (style != style0 && style != QE_STYLE_KEYWORD && style != 
QE_STYLE_FUNCTION) {
                 if (style0 == 0)
                     continue;
                 style0 = 0;
@@ -627,7 +627,7 @@
                 style = buf[pos] >> STYLE_SHIFT;
             }
             pos++;
-            if (style0 != style) {
+            if (style0 != style && style != QE_STYLE_KEYWORD && style != 
QE_STYLE_FUNCTION) {
                 if (style0 == 0)
                     continue;
                 style0 = 0;



reply via email to

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