]> git.wh0rd.org Git - nano.git/commitdiff
Preliminary syntax highlighting support. New functions colortoint() and parse_color...
authorChris Allegretta <chrisa@asty.org>
Thu, 29 Nov 2001 02:42:27 +0000 (02:42 +0000)
committerChris Allegretta <chrisa@asty.org>
Thu, 29 Nov 2001 02:42:27 +0000 (02:42 +0000)
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@910 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
color.c
global.c
nano.c
nano.h
nanorc.sample
proto.h
rcfile.c
winio.c

index cb2ab5f03c04ce981df569aaadbba41ecbc9b174..34ae3afa2b402099a044ccf8cd958b940e4bc8f7 100644 (file)
--- 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 855d44f4e4d504ae84e2ed28cd03b69fd5f9571a..f12156d5d476ed26d71f40ce9394168c4ca30994 100644 (file)
--- 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);
index 160d238d62a07a7e15eee6436a206f00c028e942..815227db58128cc9ff47e029d2f09b73e8347d34 100644 (file)
--- 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 6b80d767e41999c37e52010953c0e085287229fd..81ef9cf19de5a89fa6bab9ab3881ad59141ca088 100644 (file)
--- 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 dc6d99f20620c91c9c3e024b87f37e37f11db8f9..546ab87007491d3dd0e5da609c7fd3d6baa3a5f5 100644 (file)
--- 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)
index 3fd1d49eb960ea35b95013b8e37c27fab82c0e6d..544a41223cd0f317fda946af8dc89cfa31dc9584 100644 (file)
 # 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 711de036c46900ef06c5794dda96ad8a898e2c41..3b4230de2297a793bcce060bcbea4b220e9a622e 100644 (file)
--- 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
+
+
index 98f6867fd279fd0c1ccf58119c685b9ff5aae152..53efe008e92940c0b1ae689ba34dbc59a3ed3045 100644 (file)
--- 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 b13b633d617092594dc7dcfd2f08b8ffb9a2b7f6..332013ee116b2b2b224438f522f9b17c214e7321 100644 (file)
--- 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
+
 }
 
 /*