diff --git a/Makefile b/Makefile index ff20acf..9b4f409 100644 --- a/Makefile +++ b/Makefile @@ -237,7 +237,7 @@ $(OBJS_DIR)/charsetjis.o: charsetjis.c charsetjis.def $(OBJS_DIR)/fbfrender.o: fbfrender.c fbfrender.h libfbf.h $(OBJS_DIR)/qe.o: qe.c parser.c qeconfig.h qfribidi.h variables.h $(OBJS_DIR)/qfribidi.o: qfribidi.c qfribidi.h -$(OBJS_DIR)/clang.o: clang.c rust.c swift.c +$(OBJS_DIR)/clang.o: clang.c rust.c swift.c icon.c $(TOBJS_DIR)/cfb.o: cfb.c cfb.h fbfrender.h $(TOBJS_DIR)/charsetjis.o: charsetjis.c charsetjis.def @@ -439,20 +439,19 @@ force: # # tar archive for distribution # -FILES:=COPYING Changelog Makefile README TODO.org VERSION \ - arabic.c bufed.c buffer.c cfb.c cfb.h charset.c charsetjis.c \ - charsetjis.def charsetmore.c clang.c config.eg config.h \ - configure cptoqe.c cutils.c cutils.h dired.c display.c \ - display.h docbook.c extras.c fbffonts.c fbfrender.c \ - fbfrender.h fbftoqe.c haiku.cpp haiku-pe2qe.sh hex.c html.c \ - html2png.c htmlsrc.c lisp.c \ - image.c indic.c input.c jistoqe.c kmap.c kmaptoqe.c \ - latex-mode.c libfbf.c libfbf.h ligtoqe.c list.c makemode.c \ - mpeg.c perl.c qe-doc.html qe-doc.texi qe.1 qe.c qe.h qe.tcc \ - qeconfig.h qeend.c qemacs.spec qestyles.h qfribidi.c \ - qfribidi.h script.c shell.c tty.c unicode_join.c unihex.c \ - unix.c util.c variables.c variables.h video.c win32.c x11.c \ - xml.c +FILES:= .cvsignore COPYING Changelog Makefile README TODO.org VERSION \ + arabic.c archive.c arm.c bufed.c buffer.c cfb.c cfb.h charset.c \ + charsetjis.c charsetjis.def charsetmore.c clang.c cobol.c config.eg \ + configure cptoqe.c cutils.c cutils.h dired.c display.c display.h \ + docbook.c ebnf.c extra-modes.c extras.c fbfrender.c fbfrender.h \ + fbftoqe.c forth.c haiku-pe2qe.sh haiku.cpp hex.c html.c html2png.c \ + htmlsrc.c icon.c image.c indic.c input.c jistoqe.c kmap.c kmaptoqe.c \ + latex-mode.c libfbf.c libfbf.h ligtoqe.c lisp.c list.c makemode.c \ + markdown.c mpeg.c orgmode.c parser.c perl.c qe-doc.html qe-doc.texi \ + qe.1 qe.c qe.h qe.tcc qeconfig.h qeend.c qemacs.spec qestyles.h \ + qfribidi.c qfribidi.h rlang.c rust.c script.c shell.c swift.c tty.c \ + unicode_join.c unifont.lig unihex.c unix.c util.c variables.c \ + variables.h video.c win32.c x11.c xml.c FILES+=plugins/Makefile plugins/my_plugin.c diff --git a/clang.c b/clang.c index 49660c9..ce26dca 100644 --- a/clang.c +++ b/clang.c @@ -59,6 +59,7 @@ enum { CLANG_SCILAB, CLANG_RUST, CLANG_SWIFT, + CLANG_ICON, CLANG_FLAVOR = 0x3F, }; @@ -2104,6 +2105,7 @@ ModeDef scilab_mode = { #include "rust.c" #include "swift.c" +#include "icon.c" static int c_init(void) { @@ -2153,6 +2155,7 @@ static int c_init(void) qe_register_mode(&scilab_mode, MODEF_SYNTAX); rust_init(); swift_init(); + icon_init(); return 0; } diff --git a/icon.c b/icon.c new file mode 100644 index 0000000..ef93d7d --- /dev/null +++ b/icon.c @@ -0,0 +1,220 @@ +/* + * Icon mode for QEmacs. + * + * Copyright (c) 2015 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 + */ + +static const char icon_keywords[] = { + "break|by|case|create|default|do|else|end|every|fail|global|" + "if|initial|invocable|link|local|next|not|of|procedure|" + "record|repeat|return|static|suspend|then|to|until|while" +}; + +static const char icon_types[] = { + "string|co-expression|table|integer|cset|procedure|set|" + "real|list|" +}; + +static const char icon_directives[] = { + "ifdef|ifndef|else|endif|include|define|undef|line|error|" +}; + +enum { + ICON_STYLE_DEFAULT = 0, + ICON_STYLE_PREPROCESS = QE_STYLE_PREPROCESS, + ICON_STYLE_COMMENT = QE_STYLE_COMMENT, + ICON_STYLE_STRING = QE_STYLE_STRING, + ICON_STYLE_STRING_Q = QE_STYLE_STRING_Q, + ICON_STYLE_NUMBER = QE_STYLE_NUMBER, + ICON_STYLE_KEYWORD = QE_STYLE_KEYWORD, + ICON_STYLE_TYPE = QE_STYLE_TYPE, + ICON_STYLE_FUNCTION = QE_STYLE_FUNCTION, +}; + +/* icon-mode colorization states */ +enum { + IN_ICON_STRING = 0x04, /* double-quoted string */ + IN_ICON_STRING_Q = 0x08, /* single-quoted string */ +}; + +static void icon_colorize_line(QEColorizeContext *cp, + unsigned int *str, int n, ModeDef *syn) +{ + int i, start, i1, indent, c, state, style, klen, delim; + char kbuf[32]; + + for (i = 0; qe_isspace(str[i]); i++) + continue; + + state = cp->colorize_state; + + indent = i; + start = i; + c = 0; + style = ICON_STYLE_DEFAULT; + + if (i >= n) + goto the_end; + + if (state) { + /* if already in a state, go directly in the code parsing it */ + if (state & IN_ICON_STRING) + goto parse_string; + if (state & IN_ICON_STRING_Q) + goto parse_string_q; + } + + while (i < n) { + start = i; + c = str[i++]; + switch (c) { + case '#': /* preprocessor */ + if ((i == 1 && str[i] == '!') + || ustrstart(str + i, "line", &klen)) { + i = n; + style = ICON_STYLE_PREPROCESS; + break; + } + i = n; + style = ICON_STYLE_COMMENT; + break; + + case '\'': /* character constant */ + parse_string_q: + state |= IN_ICON_STRING_Q; + style = ICON_STYLE_STRING_Q; + delim = '\''; + goto string; + + case '\"': /* string literal */ + parse_string: + state |= IN_ICON_STRING; + style = ICON_STYLE_STRING; + delim = '\"'; + string: + while (i < n) { + c = str[i++]; + if (c == '\\') { + if (i >= n) + break; + i++; + } else + if (c == delim) { + state &= ~(IN_ICON_STRING | IN_ICON_STRING_Q); + break; + } + } + break; + + case '.': + c = '0'; + i--; + /* fall thru */ + + default: + if (qe_isdigit(c)) { + int real = 0; + + while (qe_isdigit(str[i])) + i++; + if (str[i] == '.') { + i++; + real = 1; + while (qe_isdigit(str[i])) + i++; + } + if (str[i] == 'e' || str[i] == 'E') { + i++; + real = 1; + if (str[i] == '+' || str[i] == '-') + i++; + while (qe_isdigit(str[i])) + i++; + } + if (!real && (str[i] == 'r' || str[i] == 'R')) { + /* radix numbers */ + while (qe_isalnum(str[i])) + i++; + } + style = ICON_STYLE_NUMBER; + break; + } + if (qe_isalpha_(c) || (c == '$' && qe_isalnum_(str[i]))) { + klen = 0; + kbuf[klen++] = c; + while (qe_isalnum_(c = str[i])) { + if (klen < countof(kbuf) - 1) + kbuf[klen++] = c; + i++; + } + kbuf[klen] = '\0'; + + if (start == indent && kbuf[0] == '$' + && strfind(icon_directives, kbuf + 1)) { + style = ICON_STYLE_PREPROCESS; + break; + } + if (strfind(syn->keywords, kbuf)) { + style = ICON_STYLE_KEYWORD; + break; + } + + i1 = i; + while (qe_isblank(str[i1])) + i1++; + + if (str[i1] == '(') { + /* function call */ + /* XXX: different styles for call and definition */ + style = ICON_STYLE_FUNCTION; + break; + } + break; + } + continue; + } + if (style) { + SET_COLOR(str, start, i, style); + style = 0; + } + } + the_end: + /* set style on eol char */ + SET_COLOR1(str, n, style); + + cp->colorize_state = state; +} + +ModeDef icon_mode = { + .name = "Icon", + .extensions = "icn", + .shell_handlers = "iconc", + .colorize_func = icon_colorize_line, + .colorize_flags = CLANG_ICON, + .keywords = icon_keywords, + .types = icon_types, + .indent_func = c_indent_line, + .auto_indent = 1, + .fallback = &c_mode, +}; + +static int icon_init(void) +{ + qe_register_mode(&icon_mode, MODEF_SYNTAX); + + return 0; +}