evil-qemacs/script.c
2015-08-27 23:03:39 +00:00

141 lines
4 KiB
C

/*
* Shell script mode for QEmacs.
*
* Copyright (c) 2000-2014 Charlie Gordon.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "qe.h"
/*---------------- 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,
};
static int script_var(const unsigned int *str, int j, int n)
{
for (; j < n; j++) {
if (qe_isalnum_(str[j]) || str[j] == '-')
continue;
break;
}
return j;
}
static void script_colorize_line(QEColorizeContext *cp,
unsigned int *str, int n, ModeDef *syn)
{
int i = 0, j, c, start, style;
style = SCRIPT_STYLE_COMMAND;
while (i < n) {
start = i;
switch (str[i]) {
case '#':
if (i > 0 && str[i - 1] == '$')
break;
style = SCRIPT_STYLE_COMMENT;
if (str[i + 1] == '!')
style = SCRIPT_STYLE_PREPROCESS;
i = n;
SET_COLOR(str, start, i, style);
continue;
case '`':
style = SCRIPT_STYLE_BACKTICK;
goto has_string;
case '\'':
case '"':
style = SCRIPT_STYLE_STRING;
has_string:
/* parse string const */
for (i++; i < n;) {
c = str[i++];
if (c == '\\' && i < n && str[start] == '"')
i++;
else
if ((unsigned int)c == str[start])
break;
}
SET_COLOR(str, start, i, style);
if (i < n)
style = SCRIPT_STYLE_TEXT;
continue;
case ' ':
case '\t':
break;
default:
i = script_var(str, i, n);
if (i > start) {
j = i;
while (qe_isblank(str[j]))
j++;
if (str[j] == '=')
style = SCRIPT_STYLE_VARIABLE;
SET_COLOR(str, start, i, style);
style = SCRIPT_STYLE_TEXT;
continue;
}
// Should support << syntax
// Should support $ syntax
style = SCRIPT_STYLE_TEXT;
break;
}
i++;
}
}
static int script_mode_probe(ModeDef *mode, ModeProbeData *p)
{
if (match_extension(p->filename, mode->extensions)
|| match_shell_handler(cs8(p->buf), mode->shell_handlers)
|| stristart(p->filename, ".bash", NULL)
|| stristart(p->filename, ".profile", NULL)) {
return 80;
}
if (p->buf[0] == '#') {
if (p->buf[1] == '!')
return 60;
if (p->buf[1] == ' ')
return 25;
}
return 1;
}
static ModeDef 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,
};
static int script_init(void)
{
qe_register_mode(&script_mode, MODEF_SYNTAX);
return 0;
}
qe_module_init(script_init);