From: Chris Allegretta Date: Thu, 29 Nov 2001 02:42:27 +0000 (+0000) Subject: Preliminary syntax highlighting support. New functions colortoint() and parse_color... X-Git-Tag: v1.1.4~12 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=08893e08e32b899b5109581f2121ef9d0e60d2ea;p=nano.git Preliminary syntax highlighting support. New functions colortoint() and parse_color() in rcfile.c, new code in edit_add() in winio.c to actually do the highlighting. It's not even close to pretty yet :P git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@910 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/ChangeLog b/ChangeLog index cb2ab5f0..34ae3afa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ CVS Code - +- General + - Preliminary syntax highlighting support. New functions + colortoint() and parse_color() in rcfile.c, new code in + edit_add() in winio.c to actually do the highlighting. It's + not even close to pretty yet :P - files.c: add_open_file() - Get rid of unsetting MARK_ISSET because otherwise writing diff --git a/color.c b/color.c index 855d44f4..f12156d5 100644 --- a/color.c +++ b/color.c @@ -98,14 +98,70 @@ void colorinit_one(int colortoset, short fg, short bg, int bold) int do_colorinit(void) { + int i, fg, bg; + colortype *tmpcolor = NULL; + colorstr *tmpstr = NULL; + int defok = 0; + if (has_colors()) { start_color(); /* Add in colors, if available */ + #ifdef HAVE_USE_DEFAULT_COLORS - /* Use if at all possible for transparent terminals =-) */ - use_default_colors(); + if (use_default_colors() != ERR) { + defok = 1; #endif - /* Some defaults values to play with */ + + i = 1; + for (tmpcolor = colorstrings; tmpcolor != NULL; + tmpcolor = tmpcolor->next) { + + if (tmpcolor->fg > 8) + fg = tmpcolor->fg - 8; + else + fg = tmpcolor->fg; + + if (tmpcolor->bg > 8) + bg = tmpcolor->bg - 8; + else + bg = tmpcolor->bg; + + if (defok && bg == -1) + init_pair(i, fg, -1); + else if (bg == -1) + init_pair(i, fg, COLOR_BLACK); + else /* They picked a fg and bg color */ + init_pair(i, fg, bg); + + fprintf(stderr, "Running init_pair with fg = %d and bg = %d\n", fg, bg); + + tmpcolor->pairnum = i; + i++; + } + } + +/* + if (use_default_colors() != ERR) { + init_pair(COLOR_BLACK, -1, -1); + init_pair(COLOR_GREEN, COLOR_GREEN, -1); + init_pair(COLOR_WHITE, COLOR_WHITE, -1); + init_pair(COLOR_RED, COLOR_RED, -1); + init_pair(COLOR_CYAN, COLOR_CYAN, -1); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1); + init_pair(COLOR_BLUE, COLOR_BLUE, -1); + init_pair(COLOR_YELLOW, COLOR_YELLOW, -1); + + } else { + init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); + init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK); + init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); + init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK); + init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); + init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK); + init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); + } +*/ /* Okay I'll be nice and comment these out for the commit =) colorinit_one(COLOR_TITLEBAR, COLOR_GREEN, COLOR_BLUE, 1); diff --git a/global.c b/global.c index 160d238d..815227db 100644 --- a/global.c +++ b/global.c @@ -100,6 +100,7 @@ shortcut browser_list[BROWSER_LIST_LEN]; #ifdef ENABLE_COLOR colorstruct colors[NUM_NCOLORS]; + colortype *colorstrings = NULL; #endif #if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP) diff --git a/nano.c b/nano.c index 6b80d767..81ef9cf1 100644 --- a/nano.c +++ b/nano.c @@ -2871,12 +2871,14 @@ int main(int argc, char *argv[]) fprintf(stderr, _("Main: set up windows\n")); #endif + window_init(); + mouse_init(); + #ifdef ENABLE_COLOR do_colorinit(); -#endif /* ENABLE_COLOR */ - window_init(); - mouse_init(); + fprintf(stderr, "COLORS = %d, COLOR_PAIRS = %d\n", COLORS, COLOR_PAIRS); +#endif /* ENABLE_COLOR */ #ifdef DEBUG fprintf(stderr, _("Main: bottom win\n")); diff --git a/nano.h b/nano.h index dc6d99f2..546ab870 100644 --- a/nano.h +++ b/nano.h @@ -117,6 +117,26 @@ typedef struct rcoption { #endif /* ENABLE_NANORC */ +#ifdef ENABLE_COLOR + +#define COLORSTRNUM 16 + +typedef struct colorstr { + char *val; + struct colorstr *next; +} colorstr; + +typedef struct colortype { + int fg; + int bg; + int pairnum; + colorstr *str; + struct colortype *next; +} colortype; + +#endif /* ENABLE_COLOR */ + + /* Bitwise flags so we can save space (or more correctly, not waste it) */ #define MODIFIED (1<<0) diff --git a/nanorc.sample b/nanorc.sample index 3fd1d49e..544a4122 100644 --- a/nanorc.sample +++ b/nanorc.sample @@ -55,3 +55,26 @@ # this to work # # set multibuffer + +# +# Color setup +# Format: color foreground,background regex [regex...] +# +# Legal colors are: white, black, red, blue, green, yellow, purple, cyan +# You may use the preefix "bright" to mean a stronger color hilight +# +# If your system supports transparency, not specifying a background +# color will use a transparent color. If you don't want this, be sure +# to set the background color to black or white. +# +#color brightred float\ char\ int\ void\ NULL [A-Z_]\{2,\} static +#color brightred [\ ]struct ^struct if\ while[\ \n\(] do[\ \n\(] else[\ \n] case\ switch\ break; +#color brightcyan #define #include #ifn*def #endif #elif #else + +# You will in general want your comments and strings to come last, becase +# syntax highlighting rules will be applied in the order they are read in + +#color brightyellow <.*> ".*" +#color brightblue /\*.**/ +# multi-line comment hack +#color brightblue /\*.* [^\/][^\*]*\*\/ ^.*\*+*\**$ ^\ *\*\{1,\}\/$ \/\/.* diff --git a/proto.h b/proto.h index 711de036..3b4230de 100644 --- a/proto.h +++ b/proto.h @@ -59,6 +59,10 @@ extern filestruct *cutbuffer, *mark_beginbuf; extern filestruct *open_files; #endif +#ifdef ENABLE_COLOR +colortype *colorstrings; +#endif + extern shortcut *shortcut_list; extern shortcut main_list[MAIN_LIST_LEN], whereis_list[WHEREIS_LIST_LEN]; extern shortcut replace_list[REPLACE_LIST_LEN], goto_list[GOTO_LIST_LEN]; @@ -245,3 +249,5 @@ filestruct *open_file_dup_search(int update); #ifndef DISABLE_HELP void help_init(void); #endif + + diff --git a/rcfile.c b/rcfile.c index 98f6867f..53efe008 100644 --- a/rcfile.c +++ b/rcfile.c @@ -107,18 +107,171 @@ void rcfile_msg(int *errors, char *msg, ...) /* Parse the next word from the string. Returns NULL if we hit EOL */ char *parse_next_word(char *ptr) { - while (*ptr != ' ' && *ptr != '\n' && ptr != '\0') + while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && ptr != '\0') ptr++; - if (*ptr == '\0') + if (*ptr == '\0' || *ptr == '\n') return NULL; - + /* Null terminate and advance ptr */ *ptr++ = 0; + while ((*ptr == ' ' || *ptr == '\t') && *ptr != '\0') + ptr++; + return ptr; } +int colortoint(char *colorname, char *filename, int *lineno) +{ + int mcolor = 0; + + if (colorname == NULL) + return -1; + + if (strcasestr(colorname, "bright")) { + mcolor += 8; + colorname += 6; + } + + if (!strcasecmp(colorname, "green")) + mcolor += COLOR_GREEN; + else if (!strcasecmp(colorname, "red")) + mcolor += COLOR_RED; + else if (!strcasecmp(colorname, "blue")) + mcolor += COLOR_BLUE; + else if (!strcasecmp(colorname, "white")) + mcolor += COLOR_WHITE; + else if (!strcasecmp(colorname, "yellow")) + mcolor += COLOR_YELLOW; + else if (!strcasecmp(colorname, "cyan")) + mcolor += COLOR_CYAN; + else if (!strcasecmp(colorname, "magenta")) + mcolor += COLOR_MAGENTA; + else if (!strcasecmp(colorname, "black")) + mcolor += COLOR_BLACK; + else { + printf("Error in %s on line %d: color %s not understood.\n", + filename, *lineno, colorname); + printf("Valid colors are \"green\", \"red\", \"blue\", " + "\"white\", \"yellow\", \"cyan\", \"magenta\" and " + "\"black\", with the optional prefix \"bright\".\n"); + exit(1); + } + + return mcolor; +} + + +#ifdef ENABLE_COLOR +/* Parse the color stuff into the colorstrings array */ +void parse_colors(FILE *rcstream, char *filename, int *lineno, char *buf, char *ptr) +{ + int i = 0, fg, bg; + char prev = '\\'; + char *tmp = NULL, *beginning, *fgstr, *bgstr; + colortype *tmpcolor = NULL; + colorstr *tmpstr = NULL; + + fgstr = ptr; + ptr = parse_next_word(ptr); + + if (ptr == NULL) { + printf("Error in %s on line %d: Missing color name.\n", + filename, *lineno); + exit(1); + } + + if (strstr(fgstr, ",")) { + strtok(fgstr, ","); + bgstr = strtok(NULL, ","); + } else + bgstr = NULL; + + fg = colortoint(fgstr, filename, lineno); + bg = colortoint(bgstr, filename, lineno); + + /* Now the fun part, start adding regexps to individual strings + in the colorstrings array, woo! */ + + i = 0; + beginning = ptr; + while (*ptr != '\0') { + switch (*ptr) { + case '\n': + *ptr = ' '; + i++; + case ' ': + if (prev != '\\') { + /* This is the end of the regex, uh I guess. + Add it to the colorstrings array for this color */ + + tmp = NULL; + tmp = charalloc(i + 1); + strncpy(tmp, beginning, i); + tmp[i] = '\0'; + + ptr = parse_next_word(ptr); + if (ptr == NULL) + return; + + if (colorstrings == NULL) { + colorstrings = nmalloc(sizeof(colortype)); + colorstrings->fg = fg; + colorstrings->bg = bg; + colorstrings->str = NULL; + colorstrings->str = nmalloc(sizeof(colorstr)); + colorstrings->str->val = tmp; + colorstrings->str->next = NULL; + colorstrings->next = NULL; + } else { + for (tmpcolor = colorstrings; + tmpcolor->next != NULL && !(tmpcolor->fg == fg + && tmpcolor->bg == bg); tmpcolor = tmpcolor->next) + ; + + /* An entry for this color pair already exists, add it + to the str list */ + if (tmpcolor->fg == fg && tmpcolor->bg == bg) { + for (tmpstr = tmpcolor->str; tmpstr->next != NULL; + tmpstr = tmpstr->next) + ; + + fprintf(stderr, "Adding to existing entry for fg %d bg %d\n", fg, bg); + + tmpstr->next = nmalloc (sizeof(colorstr)); + tmpstr->next->val = tmp; + tmpstr->next->next = NULL; + } else { + + fprintf(stderr, "Adding new entry for fg %d bg %d\n", fg, bg); + + tmpcolor->next = nmalloc(sizeof(colortype)); + tmpcolor->next->fg = fg; + tmpcolor->next->bg = bg; + tmpcolor->next->str = nmalloc(sizeof(colorstr)); + tmpcolor->next->str->val = tmp; + tmpcolor->next->str->next = NULL; + tmpcolor->next->next = NULL; + } + } + + i = 0; + beginning = ptr; + break; + } + /* Else drop through to the default case */ + default: + i++; + prev = *ptr; + ptr++; + break; + } + } + +} +#endif /* ENABLE_COLOR */ + /* Parse the RC file, once it has been opened successfully */ void parse_rcfile(FILE *rcstream, char *filename) { @@ -155,6 +308,10 @@ void parse_rcfile(FILE *rcstream, char *filename) set = 1; else if (!strcasecmp(keyword, "unset")) set = -1; +#ifdef ENABLE_COLOR + else if (!strcasecmp(keyword, "color")) + parse_colors(rcstream, filename, &lineno, buf, ptr); +#endif /* ENABLE_COLOR */ else { rcfile_msg(&errors, _("Error in %s on line %d: command %s not understood"), filename, lineno, keyword); @@ -248,6 +405,7 @@ void do_rcfile(void) struct stat fileinfo; FILE *rcstream; + if (getenv("HOME") == NULL) return; diff --git a/winio.c b/winio.c index b13b633d..332013ee 100644 --- a/winio.c +++ b/winio.c @@ -772,6 +772,7 @@ void add_marked_sameline(int begin, int end, filestruct * fileptr, int y, void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, int virt_mark_beginx, int this_page) { + #ifndef NANO_SMALL /* There are quite a few cases that could take place; we'll deal * with them each in turn */ @@ -940,6 +941,64 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, /* Just paint the string (no mark on this line) */ mvwaddnstr(edit, yval, 0, &fileptr->data[start], get_page_end_virtual(this_page) - start + 1); + +#ifdef ENABLE_COLOR + { + colortype *tmpcolor = NULL; + colorstr *tmpstr = NULL; + int k, paintlen; + + if (colorstrings != NULL) + for (tmpcolor = colorstrings; tmpcolor != NULL; tmpcolor = tmpcolor->next) { + for (tmpstr = tmpcolor->str; tmpstr != NULL; tmpstr = tmpstr->next) { + + k = start; + regcomp(&search_regexp, tmpstr->val, 0); + while (!regexec(&search_regexp, &fileptr->data[k], 1, + regmatches, 0)) { + +#ifdef DEBUG + fprintf(stderr, "Match! (%d chars) \"%s\"\n", + regmatches[0].rm_eo - regmatches[0].rm_so, + &fileptr->data[k + regmatches[0].rm_so]); +#endif + if (regmatches[0].rm_so < COLS - 1) { + if (tmpcolor->fg > 8 || tmpcolor->bg > 8) { + wattron(edit, A_BOLD); + wattron(edit, COLOR_PAIR(tmpcolor->pairnum)); + } + else + wattron(edit, COLOR_PAIR(tmpcolor->pairnum)); + + if (regmatches[0].rm_eo - regmatches[0].rm_so + + k <= COLS) + paintlen = regmatches[0].rm_eo - regmatches[0].rm_so; + else + paintlen = COLS - (regmatches[0].rm_eo + - regmatches[0].rm_so); + + mvwaddnstr(edit, yval, regmatches[0].rm_so + k, + &fileptr->data[k + regmatches[0].rm_so], + paintlen); + + + } + + if (tmpcolor->fg > 8 || tmpcolor->bg > 8) { + wattroff(edit, A_BOLD); + wattroff(edit, COLOR_PAIR(tmpcolor->pairnum)); + } + else + wattroff(edit, COLOR_PAIR(tmpcolor->pairnum)); + + k += regmatches[0].rm_eo; + } + } + } + } + +#endif + } /*