From fda88cdb4255cdcc497368b5991b8d042a8ef293 Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Sun, 18 Apr 2021 21:03:45 +0200 Subject: [PATCH] Miscellaneous fixes, add Salmon mode * more todos * add Salmon programming language * disable -Wno-unused-result on OpenBSD --- Makefile | 3 + TODO.md | 5 + indic.c | 6 +- lang/clang.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ lang/clang.h | 1 + qfribidi.c | 1 + tty.c | 1 - 7 files changed, 310 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 8c8b988..de96fab 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA DEPTH=. +OSNAME:=$(shell uname -s) include $(DEPTH)/config.mak @@ -42,8 +43,10 @@ endif ifdef CONFIG_DARWIN CFLAGS += -Wno-string-plus-int else +ifneq ($(OSNAME),OpenBSD) CFLAGS += -Wno-unused-result endif +endif ifdef TARGET_GPROF CFLAGS += -p diff --git a/TODO.md b/TODO.md index 4917fd4..86e750e 100644 --- a/TODO.md +++ b/TODO.md @@ -8,6 +8,11 @@ ## Changes for Github publication +* fix filename completion bug at directory start +* show current directory for shell buffers in buffer list view +* full ls display in file completion window +* incremental search: increase max repeat count +* undo: allow file save when undo clears file modified flag * files: check file date to detect asynchronous modifications on disk * files: reload modified file upon change if untouched since load * improve **README.md** diff --git a/indic.c b/indic.c index 59bedc0..47c3687 100644 --- a/indic.c +++ b/indic.c @@ -36,18 +36,18 @@ #define RA_DEAD (RA + DEAD_CONSONANT_OFFSET) #if 0 -static int is_vowel_sign (unsigned int i) +static int is_vowel_sign(unsigned int i) { return (i >= 0x93E && i <= 0x94c) || (i >= 0x962 && i <= 0x963); } #endif -static int is_consonant (unsigned int i) +static int is_consonant(unsigned int i) { return (i >= 0x915 && i <= 0x939) || (i >= 0x958 && i <= 0x95f); } -static int is_ind_vowel (unsigned int i) +static int is_ind_vowel(unsigned int i) { return (i >= 0x905 && i <= 0x914); } diff --git a/lang/clang.c b/lang/clang.c index e0c197c..2af2b6f 100644 --- a/lang/clang.c +++ b/lang/clang.c @@ -3355,6 +3355,302 @@ static ModeDef odin_mode = { .fallback = &c_mode, }; +/*---------------- Salmon programming language ----------------*/ + +static const char salmon_keywords[] = { + "single|routine|function|procedure|class|variable|" + "immutable|tagalong|lepton|quark|lock|static|" + "virtual|pure|construct|type|arguments|this|break" + "continue|forall|exists|" +}; + +static const char salmon_types[] = { + "|" +}; + +static int get_salmon_identifier(char *dest, int size, int c, + const unsigned int *str, int i, int n) +{ + int pos = 0, j; + + for (j = i;; j++) { + if (pos < size - 1) { + dest[pos++] = c; + } + if (j >= n) + break; + c = str[j]; + if (!qe_isalnum_(c)) + break; + } + if (pos < size) { + dest[pos] = '\0'; + } + return j - i; +} + +static void salmon_colorize_line(QEColorizeContext *cp, + unsigned int *str, int n, ModeDef *syn) +{ + int i = 0, start, i1, indent; + int c, style, delim, tag, level; + char kbuf[64]; + int mode_flags = syn->colorize_flags; + int state = cp->colorize_state; + //int type_decl; /* unused */ + + indent = 0; + //for (; qe_isblank(str[indent]); indent++) continue; + tag = !qe_isblank(str[0]) && (cp->s->mode == syn || cp->s->mode == &htmlsrc_mode); + + start = i; + //type_decl = 0; + c = 0; + style = 0; + + if (i >= n) + goto the_end; + + if (state) { + /* if already in a state, go directly in the code parsing it */ + if (state & IN_C_COMMENT2) + goto parse_comment2; + if (state & IN_C_STRING) + goto parse_string; + if (state & IN_C_STRING_Q) + goto parse_string_q; + if (state & IN_C_STRING_BQ) + goto parse_string_bq; + if (state & IN_C_REGEX) { + goto parse_regex; + } + } + + while (i < n) { + start = i; + c = str[i++]; + + switch (c) { + case '/': + if (str[i] == '*') { + /* C style multi-line comment */ + i++; + state |= IN_C_COMMENT2; + parse_comment2: + style = C_STYLE_COMMENT; + level = (state & IN_C_COMMENT_LEVEL) >> IN_C_COMMENT_SHIFT; + while (i < n) { + if (str[i] == '/' && str[i + 1] == '*' && (mode_flags & CLANG_NEST_COMMENTS)) { + i += 2; + level++; + } else + if (str[i] == '*' && str[i + 1] == '/') { + i += 2; + if (level == 0) { + state &= ~IN_C_COMMENT2; + break; + } + level--; + } else { + i++; + } + } + state = (state & ~IN_C_COMMENT_LEVEL) | + (min(level, 7) << IN_C_COMMENT_SHIFT); + break; + } else + if (str[i] == '/') { + /* line comment */ + state |= IN_C_COMMENT1; + style = C_STYLE_COMMENT; + i = n; + break; + } + continue; + case '#': /* preprocessor */ + if (start == 0 && str[i] == '!') { + /* recognize a shebang comment line */ + style = C_STYLE_PREPROCESS; + i = n; + break; + } + style = C_STYLE_COMMENT; + i = n; + break; + case '`': /* ECMA 6 template strings */ + parse_string_bq: + state |= IN_C_STRING_BQ; + style = C_STYLE_STRING_BQ; + while (i < n) { + c = str[i++]; + if (c == '`') { + state &= ~IN_C_STRING_BQ; + break; + } + } + break; + + case '@': /* regular expression literal */ + parse_regex: + state |= IN_C_REGEX; + style = C_STYLE_REGEX; + delim = '@'; + while (i < n) { + c = str[i++]; + if (c == '\\') { + if (i < n) { + i += 1; + } + } else + if (state & IN_C_CHARCLASS) { + if (c == ']') { + state &= ~IN_C_CHARCLASS; + } + } else { + if (c == '[') { + state |= IN_C_CHARCLASS; + } else + if (c == delim) { + while (qe_isalnum_(str[i])) { + i++; + } + state &= ~IN_C_REGEX; + break; + } + } + } + break; + case '\'': /* character constant */ + parse_string_q: + state |= IN_C_STRING_Q; + style = C_STYLE_STRING_Q; + delim = '\''; + goto string; + + case '\"': /* string literal */ + parse_string: + state |= IN_C_STRING; + style = C_STYLE_STRING; + delim = '\"'; + string: + while (i < n) { + c = str[i++]; + if (c == '\\') { + if (i >= n) + break; + i++; + } else + if (c == delim) { + state &= ~(IN_C_STRING | IN_C_STRING_Q | IN_C_REGEX); + break; + } + } + break; + case '=': + /* exit type declaration */ + /* does not handle this: int i = 1, j = 2; */ + //type_decl = 0; + continue; + case '(': + case '{': + tag = 0; + continue; + default: + if (qe_isdigit(c)) { + /* XXX: should parse actual number syntax */ + /* decimal, binary, octal and hexadecimal literals: + * 1 0b1 0o1 0x1, case insensitive. 01 is a syntax error */ + /* maybe ignore '_' in integers */ + /* XXX: should parse decimal and hex floating point syntaxes */ + while (qe_isalnum_(str[i]) || (str[i] == '.' && str[i + 1] != '.')) { + i++; + } + style = C_STYLE_NUMBER; + break; + } + if (qe_isalpha_(c)) { + i += get_salmon_identifier(kbuf, countof(kbuf), c, str, i, n); + if (cp->state_only && !tag) + continue; + + /* keywords used as object property tags are regular identifiers */ + if (strfind(syn->keywords, kbuf) && + // XXX: this is incorrect for `default` inside a switch statement */ + str[i] != ':' && (start == 0 || str[start - 1] != '.')) { + style = C_STYLE_KEYWORD; + break; + } + + i1 = i; + while (qe_isblank(str[i1])) + i1++; + + if (str[i1] == '(') { + /* function call or definition */ + style = C_STYLE_FUNCTION; + if (tag) { + /* tag function definition */ + eb_add_property(cp->b, cp->offset + start, + QE_PROP_TAG, qe_strdup(kbuf)); + tag = 0; + } + break; + } else + if (tag && qe_findchar("(,;=", str[i1])) { + /* tag variable definition */ + eb_add_property(cp->b, cp->offset + start, + QE_PROP_TAG, qe_strdup(kbuf)); + } + + if ((start == 0 || str[start - 1] != '.') + && !qe_findchar(".(:", str[i]) + && strfind(syn->types, kbuf)) { + /* if not cast, assume type declaration */ + //type_decl = 1; + style = C_STYLE_TYPE; + break; + } + if (qe_isupper((unsigned char)kbuf[0]) + && (start >= 2 && str[start - 1] == ' ' && str[start - 2] == ':')) { + /* if type annotation and capitalized assume type name */ + style = C_STYLE_TYPE; + break; + } + continue; + } + continue; + } + if (style) { + if (!cp->state_only) { + SET_COLOR(str, start, i, style); + } + style = 0; + } + } + the_end: + if (state & (IN_C_COMMENT | IN_C_STRING | IN_C_STRING_Q)) { + /* set style on eol char */ + SET_COLOR1(str, n, style); + if ((state & IN_C_COMMENT) == IN_C_COMMENT1) + state &= ~IN_C_COMMENT1; + } + cp->colorize_state = state; +} + +ModeDef salmon_mode = { + .name = "Salmon", + //.alt_name = "js", + .extensions = "salm", + .shell_handlers = "salmoneye", + .colorize_func = salmon_colorize_line, + .colorize_flags = CLANG_SALMON | CLANG_REGEX | CLANG_NEST_COMMENTS, + .keywords = salmon_keywords, + .types = salmon_types, + .indent_func = c_indent_line, + .auto_indent = 1, + .fallback = &c_mode, +}; + /*---------------- Common initialization code ----------------*/ static int c_init(void) @@ -3420,6 +3716,7 @@ static int c_init(void) qe_register_mode(&v_mode, MODEF_SYNTAX); qe_register_mode(&protobuf_mode, MODEF_SYNTAX); qe_register_mode(&odin_mode, MODEF_SYNTAX); + qe_register_mode(&salmon_mode, MODEF_SYNTAX); return 0; } diff --git a/lang/clang.h b/lang/clang.h index 6350952..a46472d 100644 --- a/lang/clang.h +++ b/lang/clang.h @@ -78,6 +78,7 @@ enum { CLANG_V, CLANG_PROTOBUF, CLANG_ODIN, + CLANG_SALMON, CLANG_FLAVOR = 0x3F, }; diff --git a/qfribidi.c b/qfribidi.c index 8b8e800..5178819 100644 --- a/qfribidi.c +++ b/qfribidi.c @@ -21,6 +21,7 @@ * 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 #include #include "qfribidi.h" diff --git a/tty.c b/tty.c index 446d5c2..9c840f0 100644 --- a/tty.c +++ b/tty.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include