diff options
| -rw-r--r-- | config.def.h | 140 | ||||
| -rw-r--r-- | syntax.h | 12 | ||||
| -rw-r--r-- | window.c | 78 |
3 files changed, 122 insertions, 108 deletions
diff --git a/config.def.h b/config.def.h index 6e235a0..0f7cd4a 100644 --- a/config.def.h +++ b/config.def.h @@ -751,13 +751,14 @@ enum { COLOR_SYNTAX6, COLOR_SYNTAX7, COLOR_KEYWORD = COLOR_SYNTAX1, - COLOR_CONSTANTS = COLOR_SYNTAX1, + COLOR_CONSTANT = COLOR_SYNTAX4, COLOR_DATATYPE = COLOR_SYNTAX2, COLOR_CONTROL = COLOR_SYNTAX3, COLOR_PREPROCESSOR = COLOR_SYNTAX4, COLOR_KEYWORD2 = COLOR_SYNTAX4, COLOR_BRACKETS = COLOR_SYNTAX5, COLOR_STRING = COLOR_SYNTAX6, + COLOR_LITERAL = COLOR_SYNTAX6, COLOR_VARIABLE = COLOR_SYNTAX6, COLOR_TARGET = COLOR_SYNTAX5, COLOR_COMMENT = COLOR_SYNTAX7, @@ -775,38 +776,71 @@ static Color colors[] = { { /* empty last element, array terminator */ } }; -/* Syntax color definition, you can define up to TODO SYNTAX_REGEX_RULES - * number of regex rules per file type. Each rule is requires a regular - * expression and corresponding compilation flags as well as a color. +/* Syntax color definitions per file type. Each rule consists of a regular + * expression, a color to apply in case of a match and boolean flag inidcating + * whether it is a multiline rule. * - * The array of syntax definition must be terminated with an empty element. + * The syntax rules where initially imported from the sandy editor, written by + * Rafael Garcia <rafael.garcia.gallego@gmail.com> */ #define B "\\b" /* Use this if \b is not in your libc's regex implementation */ -// #define B "^| |\t|\\(|\\)|\\[|\\]|\\{|\\}|\\||$ +// #define B "^| |\t|\\(|\\)|\\[|\\]|\\{|\\}|\\||$" + +/* common rules, used by multiple languages */ + +#define SYNTAX_MULTILINE_COMMENT { \ + "(/\\*([^*]|\\*[^/])*\\*/)", \ + &colors[COLOR_COMMENT], \ + true, /* multiline */ \ +} + +#define SYNTAX_SINGLE_LINE_COMMENT { \ + "(//.*)", \ + &colors[COLOR_COMMENT], \ +} + +#define SYNTAX_LITERAL { \ + "('(\\\\.|.)')|(0x[0-9A-Fa-f]+|[0-9]+)", \ + &colors[COLOR_LITERAL], \ +} + +#define SYNTAX_STRING { \ + "(\"(\\\\.|[^\"])*\")", \ + &colors[COLOR_STRING], \ + true, /* multiline */ \ +} + +#define SYNTAX_CONSTANT { \ + B"[A-Z_][0-9A-Z_]+"B, \ + &colors[COLOR_CONSTANT], \ +} + +#define SYNTAX_BRACKET { \ + "(\\(|\\)|\\{|\\}|\\[|\\])", \ + &colors[COLOR_BRACKETS], \ +} /* these rules are applied top to bottom, first match wins. Therefore more 'greedy' - * rules such as for comments should be the first entries + * rules such as for comments should be the first entries. * - * These rules where initially imported from the sandy editor, written by - * Rafael Garcia <rafael.garcia.gallego@gmail.com> */ + * The array of syntax definition must be terminated with an empty element. + */ static Syntax syntaxes[] = {{ .name = "c", .file = "\\.(c(pp|xx)?|h(pp|xx)?|cc)$", - .rules = {{ - "(/\\*([^*]|\\*[^/])*\\*/|/\\*([^*]|\\*[^/])*$|^([^/]|/[^*])*\\*/)", - &colors[COLOR_COMMENT], - true, /* multiline */ - },{ - "(//.*)", - &colors[COLOR_COMMENT], - },{ - "(\"(\\\\.|[^\"])*\")", - //"([\"<](\\\\.|[^ \">])*[\">])", + .rules = { + SYNTAX_MULTILINE_COMMENT, + SYNTAX_SINGLE_LINE_COMMENT, + SYNTAX_LITERAL, + SYNTAX_STRING, + SYNTAX_CONSTANT, + SYNTAX_BRACKET, + { + "<[a-zA-Z0-9\\.-_]+>", &colors[COLOR_STRING], },{ - "(^#[\\t ]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma))|" - B"[A-Z_][0-9A-Z_]+"B"", + "(^#[\\t ]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma))", &colors[COLOR_PREPROCESSOR], },{ B"(for|if|while|do|else|case|default|switch|try|throw|catch|operator|new|delete)"B, @@ -820,9 +854,6 @@ static Syntax syntaxes[] = {{ },{ B"(goto|continue|break|return)"B, &colors[COLOR_CONTROL], - },{ - "(\\(|\\)|\\{|\\}|\\[|\\])", - &colors[COLOR_BRACKETS], }} },{ .name = "sh", @@ -830,16 +861,15 @@ static Syntax syntaxes[] = {{ .rules = {{ "#.*$", &colors[COLOR_COMMENT], - },{ + }, + SYNTAX_STRING, + { "^[0-9A-Z_]+\\(\\)", - &colors[COLOR_CONSTANTS], + &colors[COLOR_CONSTANT], },{ "\\$\\{?[0-9A-Z_!@#$*?-]+\\}?", &colors[COLOR_VARIABLE], },{ - "\"(\\\\.|[^\"])*\"", - &colors[COLOR_STRING], - },{ B"(case|do|done|elif|else|esac|exit|fi|for|function|if|in|local|read|return|select|shift|then|time|until|while)"B, &colors[COLOR_KEYWORD], },{ @@ -890,21 +920,14 @@ static Syntax syntaxes[] = {{ },{ .name = "vala", .file = "\\.(vapi|vala)$", - .rules = {{ - "(/\\*([^*]|\\*[^/])*\\*/|/\\*([^*]|\\*[^/])*$|^([^/]|/[^*])*\\*/)", - &colors[COLOR_COMMENT], - true, /* multiline */ - },{ - "(//.*)", - &colors[COLOR_COMMENT], - },{ - "\"(\\\\.|[^\"])*\"", - &colors[COLOR_STRING], - true, /* multiline */ - },{ - B"[A-Z_][0-9A-Z_]+"B, - &colors[COLOR_CONSTANTS], - },{ + .rules = { + SYNTAX_MULTILINE_COMMENT, + SYNTAX_SINGLE_LINE_COMMENT, + SYNTAX_LITERAL, + SYNTAX_STRING, + SYNTAX_CONSTANT, + SYNTAX_BRACKET, + { B"(for|if|while|do|else|case|default|switch|get|set|value|out|ref|enum)"B, &colors[COLOR_KEYWORD], },{ @@ -916,28 +939,18 @@ static Syntax syntaxes[] = {{ },{ B"(abstract|class|final|implements|import|instanceof|interface|using|private|public|static|strictfp|super|throws)"B, &colors[COLOR_KEYWORD2], - },{ - "(\\(|\\)|\\{|\\}|\\[|\\])", - &colors[COLOR_BRACKETS], }} },{ .name = "java", .file = "\\.java$", - .rules = {{ - "(/\\*([^*]|\\*[^/])*\\*/|/\\*([^*]|\\*[^/])*$|^([^/]|/[^*])*\\*/)", - &colors[COLOR_COMMENT], - true, /* multiline */ - },{ - "(//.*)", - &colors[COLOR_COMMENT], - },{ - "\"(\\\\.|[^\"])*\"", - &colors[COLOR_STRING], - true, /* multiline */ - },{ - B"[A-Z_][0-9A-Z_]+"B, - &colors[COLOR_CONSTANTS], - },{ + .rules = { + SYNTAX_MULTILINE_COMMENT, + SYNTAX_SINGLE_LINE_COMMENT, + SYNTAX_LITERAL, + SYNTAX_STRING, + SYNTAX_CONSTANT, + SYNTAX_BRACKET, + { B"(for|if|while|do|else|case|default|switch)"B, &colors[COLOR_KEYWORD], },{ @@ -949,9 +962,6 @@ static Syntax syntaxes[] = {{ },{ B"(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|this|super|synchronized|throws|volatile)"B, &colors[COLOR_KEYWORD2], - },{ - "(\\(|\\)|\\{|\\}|\\[|\\])", - &colors[COLOR_BRACKETS], }} },{ .name = "ruby", @@ -3,8 +3,6 @@ #include <regex.h> -#define SYNTAX_RULES 10 /* maximal number of syntax rules per file type */ - typedef struct { short fg, bg; /* fore and background color */ int attr; /* curses attributes */ @@ -18,11 +16,11 @@ typedef struct { } SyntaxRule; typedef struct Syntax Syntax; -struct Syntax { /* a syntax definition */ - char *name; /* syntax name */ - char *file; /* apply to files matching this regex */ - regex_t file_regex; /* compiled file name regex */ - SyntaxRule rules[SYNTAX_RULES]; /* all rules for this file type */ +struct Syntax { /* a syntax definition */ + char *name; /* syntax name */ + char *file; /* apply to files matching this regex */ + regex_t file_regex; /* compiled file name regex */ + SyntaxRule rules[12]; /* all rules for this file type */ }; #endif @@ -337,7 +337,6 @@ void window_draw(Win *win) { /* current absolute file position */ size_t pos = win->start; /* number of bytes to read in one go */ - // TODO read smaller junks size_t text_len = win->width * win->height; /* current buffer to work with */ char text[text_len+1]; @@ -354,48 +353,55 @@ void window_draw(Win *win) { /* syntax definition to use */ Syntax *syntax = win->syntax; /* matched tokens for each syntax rule */ - regmatch_t match[syntax ? LENGTH(syntax->rules) : 1][1]; - if (syntax) { - for (int i = 0; i < LENGTH(syntax->rules); i++) { - SyntaxRule *rule = &syntax->rules[i]; - if (!rule->rule) - break; - if (regexec(&rule->regex, cur, 1, match[i], 0) || - match[i][0].rm_so == match[i][0].rm_eo) { - match[i][0].rm_so = -1; - match[i][0].rm_eo = -1; - } - } - } + regmatch_t match[syntax ? LENGTH(syntax->rules) : 1][1], *matched = NULL; + memset(match, 0, sizeof match); + /* default and current curses attributes to use */ + int default_attrs = COLOR_PAIR(0) | A_NORMAL, attrs = default_attrs; while (rem > 0) { - int attrs = COLOR_PAIR(0) | A_NORMAL; - if (syntax) { - size_t off = cur - text; /* number of already processed bytes */ - for (int i = 0; i < LENGTH(syntax->rules); i++) { - SyntaxRule *rule = &syntax->rules[i]; - if (!rule->rule) - break; - if (match[i][0].rm_so == -1) - continue; /* no match on whole text */ - if (off >= (size_t)match[i][0].rm_eo) { - /* past match, continue search from current position */ - if (regexec(&rule->regex, cur, 1, match[i], 0) || - match[i][0].rm_so == match[i][0].rm_eo) { - match[i][0].rm_so = -1; - match[i][0].rm_eo = -1; - continue; + if (matched && cur >= text + matched->rm_eo) { + /* end of current match */ + matched = NULL; + attrs = default_attrs; + for (int i = 0; i < LENGTH(syntax->rules); i++) { + if (match[i][0].rm_so == -1) + continue; /* no match on whole text */ + /* reset matches which overlap with matched */ + if (text + match[i][0].rm_so <= cur && cur < text + match[i][0].rm_eo) { + match[i][0].rm_so = 0; + match[i][0].rm_eo = 0; } - match[i][0].rm_so += off; - match[i][0].rm_eo += off; } + } + + if (!matched) { + size_t off = cur - text; /* number of already processed bytes */ + for (int i = 0; i < LENGTH(syntax->rules); i++) { + SyntaxRule *rule = &syntax->rules[i]; + if (!rule->rule) + break; + if (match[i][0].rm_so == -1) + continue; /* no match on whole text */ + if (off >= (size_t)match[i][0].rm_eo) { + /* past match, continue search from current position */ + if (regexec(&rule->regex, cur, 1, match[i], 0) || + match[i][0].rm_so == match[i][0].rm_eo) { + match[i][0].rm_so = -1; + match[i][0].rm_eo = -1; + continue; + } + match[i][0].rm_so += off; + match[i][0].rm_eo += off; + } - if (text + match[i][0].rm_so <= cur && cur < text + match[i][0].rm_eo) { - /* within matched expression */ - attrs = rule->color->attr; - break; /* first match wins */ + if (text + match[i][0].rm_so <= cur && cur < text + match[i][0].rm_eo) { + /* within matched expression */ + matched = &match[i][0]; + attrs = rule->color->attr; + break; /* first match wins */ + } } } } |
