]> granicus.if.org Git - neomutt/commitdiff
feature: status-color
authorDavid Sterba <dsterba@suse.cz>
Sat, 30 Jan 2016 16:53:57 +0000 (16:53 +0000)
committerRichard Russon <rich@flatcap.org>
Sun, 6 Mar 2016 02:35:03 +0000 (02:35 +0000)
Custom rules for theming the status bar

color.c
curs_main.c
mutt_curses.h
pager.c
protos.h

diff --git a/color.c b/color.c
index 64a46dc692ca4e00ef86bd84a43a00e5533243a4..c14499d60cf3ee1ebd18cbb75178c17bd7b6f3ae 100644 (file)
--- a/color.c
+++ b/color.c
@@ -34,6 +34,7 @@ int ColorQuoteUsed;
 int ColorDefs[MT_COLOR_MAX];
 COLOR_LINE *ColorHdrList = NULL;
 COLOR_LINE *ColorBodyList = NULL;
+COLOR_LINE *ColorStatusList = NULL;
 COLOR_LINE *ColorIndexList = NULL;
 
 /* local to this file */
@@ -476,7 +477,7 @@ static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data,
 static int 
 add_pattern (COLOR_LINE **top, const char *s, int sensitive,
             int fg, int bg, int attr, BUFFER *err,
-            int is_index)
+            int is_index, int match)
 {
 
   /* is_index used to store compiled pattern
@@ -547,6 +548,7 @@ add_pattern (COLOR_LINE **top, const char *s, int sensitive,
     }
     tmp->next = *top;
     tmp->pattern = safe_strdup (s);
+    tmp->match = match;
 #ifdef HAVE_COLOR
     if(fg != -1 && bg != -1)
     {
@@ -689,7 +691,7 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
                   parser_callback_t callback, short dry_run)
 {
   int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0;
-  int r = 0;
+  int r = 0, match = 0;
 
   if(parse_object(buf, s, &object, &q_level, err) == -1)
     return -1;
@@ -697,8 +699,6 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
   if(callback(buf, s, &fg, &bg, &attr, err) == -1)
     return -1;
 
-  /* extract a regular expression if needed */
-  
   if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == MT_COLOR_INDEX)
   {
     if (!MoreArgs (s))
@@ -710,7 +710,7 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
     mutt_extract_token (buf, s, 0);
   }
    
-  if (MoreArgs (s))
+  if (MoreArgs (s) && object != MT_COLOR_STATUS)
   {
     strfcpy (err->data, _("too many arguments"), err->dsize);
     return (-1);
@@ -735,12 +735,39 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
 #endif
   
   if (object == MT_COLOR_HEADER)
-    r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err,0);
+    r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err, 0, match);
   else if (object == MT_COLOR_BODY)
-    r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0);
+    r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0, match);
+  else if (object == MT_COLOR_STATUS && MoreArgs(s))
+  {
+    /* 'color status fg bg' can have upto 2 arguments:
+     * 0 arguments: sets the default status color (handled below by else part)
+     * 1 argument : colorize pattern on match
+     * 2 arguments: colorize nth submatch of pattern
+     */
+    mutt_extract_token (buf, s, 0);
+
+    if (MoreArgs(s)) {
+      BUFFER temporary;
+      memset(&temporary, 0, sizeof(BUFFER));
+      mutt_extract_token(&temporary, s, 0);
+      match = atoi(temporary.data);
+      FREE(&temporary.data);
+    }
+
+    if (MoreArgs(s))
+    {
+      strfcpy (err->data, _("too many arguments"), err->dsize);
+      return (-1);
+    }
+  
+    r = add_pattern (&ColorStatusList, buf->data, 1,
+                   fg, bg, attr, err, 0, match);
+  }
   else if (object == MT_COLOR_INDEX)
   {
-    r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1);
+    r = add_pattern (&ColorIndexList, buf->data, 1,
+                   fg, bg, attr, err, 1, match);
     set_option (OPTFORCEREDRAWINDEX);
   }
   else if (object == MT_COLOR_QUOTED)
index 8553102457bc96794c8f13cd2d580f9be0c692c4..24f6566c68a8553e05c4305692757f3714f0b696 100644 (file)
@@ -478,6 +478,118 @@ static void resort_index (MUTTMENU *menu)
   menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
 }
 
+void
+mutt_draw_statusline(int cols, char *inbuf)
+{
+  int i          = 0;
+  int cnt        = 0;
+  int last_color = 0;
+  int color      = 0;
+  int offset     = 0;
+  int found = 0;
+  int null_rx = 0;
+  char buf[2048];
+
+  struct line_t {
+         short chunks;
+         struct syntax_t {
+                 int color;
+                 int first;
+                 int last;
+         } *syntax;
+  } lineInfo = { 0, 0 };
+
+  mutt_format_string(buf, sizeof(buf), cols, cols, 0, ' ', inbuf,
+                    mutt_strlen(inbuf), 0);
+  
+  lineInfo.syntax = safe_malloc(sizeof(struct syntax_t));
+  lineInfo.syntax[0].first = -1;
+  lineInfo.syntax[0].last  = -1;
+  lineInfo.syntax[0].color = ColorDefs[MT_COLOR_STATUS];
+  lineInfo.chunks = 1;
+
+    do
+    {
+      found = 0;
+      null_rx = 0;
+      COLOR_LINE *color_line = ColorStatusList;
+
+      if (!buf[offset])
+       break;
+
+      while (color_line)
+      {
+        regmatch_t pmatch[color_line->match + 1];
+
+       if (regexec (&color_line->rx, buf + offset, color_line->match + 1, pmatch,
+                    (offset ? REG_NOTBOL : 0)) == 0)
+       {
+         if (pmatch[color_line->match].rm_eo != pmatch[color_line->match].rm_so)
+         {
+           if (!found)
+           {
+             if (++(lineInfo.chunks) > 1)
+               safe_realloc (&(lineInfo.syntax), 
+                             (lineInfo.chunks) * sizeof (struct syntax_t));
+           }
+           i = lineInfo.chunks - 1;
+           pmatch[color_line->match].rm_so += offset;
+           pmatch[color_line->match].rm_eo += offset;
+           if (!found ||
+               pmatch[color_line->match].rm_so < (lineInfo.syntax)[i].first ||
+               (pmatch[color_line->match].rm_so == (lineInfo.syntax)[i].first &&
+                pmatch[color_line->match].rm_eo > (lineInfo.syntax)[i].last))
+           {
+             (lineInfo.syntax)[i].color = color_line->pair;
+             (lineInfo.syntax)[i].first = pmatch[color_line->match].rm_so;
+             (lineInfo.syntax)[i].last = pmatch[color_line->match].rm_eo;
+           }
+           found = 1;
+           null_rx = 0;
+         }
+         else
+           null_rx = 1; /* empty regexp; don't add it, but keep looking */
+       }
+       color_line = color_line->next;
+      }
+
+      if (null_rx)
+       offset++; /* avoid degenerate cases */
+      else
+       offset = (lineInfo.syntax)[i].last;
+    } while (found || null_rx);
+
+    for (cnt = 0; cnt < mutt_strlen(buf); cnt++) {
+           color = lineInfo.syntax[0].color;
+           for (i = 0; i < lineInfo.chunks; i++) {
+                   /* we assume the chunks are sorted */
+                   if (cnt > (lineInfo.syntax)[i].last)
+                           continue;
+                   if (cnt < (lineInfo.syntax)[i].first)
+                           break;
+                   if (cnt != (lineInfo.syntax)[i].last) {
+                           color = (lineInfo.syntax)[i].color;
+                           break;
+                   }
+                   /* don't break here, as cnt might be 
+                    * in the next chunk as well */
+           }
+           if (color != last_color) {
+                   attrset (color);
+                   last_color = color;
+           }
+           /* XXX more than one char at a time? */
+           addch ((unsigned char)buf[cnt]);
+#if 0
+           waddnstr(stdscr, tgbuf, 10);
+           SETCOLOR (MT_COLOR_NORMAL);
+           waddnstr(stdscr, tgbuf + 10, -1);
+#endif
+    }
+
+    safe_free(&lineInfo.syntax);
+}
+
 static const struct mapping_t IndexHelp[] = {
   { N_("Quit"),  OP_QUIT },
   { N_("Del"),   OP_DELETE },
@@ -634,7 +746,7 @@ int mutt_index_menu (void)
        menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
        move (option (OPTSTATUSONTOP) ? 0 : LINES-2, 0);
        SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (COLS, buf);
+       mutt_draw_statusline(COLS, buf);
        NORMAL_COLOR;
        menu->redraw &= ~REDRAW_STATUS;
        if (option(OPTTSENABLED) && TSSupported)
index f8bc47cc440fde40aff115b56bd98f39af514f88..6c716f31dcd4f6648ac38a3ab46141bc45a4b1ac 100644 (file)
@@ -127,6 +127,7 @@ enum
 typedef struct color_line
 {
   regex_t rx;
+  int match; /* which substringmap 0 for old behaviour */
   char *pattern;
   pattern_t *color_pattern; /* compiled pattern to speed up index color
                                calculation */
@@ -173,6 +174,7 @@ extern int ColorQuoteUsed;
 extern int ColorDefs[];
 extern COLOR_LINE *ColorHdrList;
 extern COLOR_LINE *ColorBodyList;
+extern COLOR_LINE *ColorStatusList;
 extern COLOR_LINE *ColorIndexList;
 
 void ci_init_color (void);
diff --git a/pager.c b/pager.c
index 4f7e7beeb86efbbd90af38862d089310910c8538..882d94dc966bd7623f946d0571c165456491e515 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -1803,13 +1803,13 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
        size_t l2 = sizeof (buffer);
        hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr;
        mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT);
-       mutt_paddstr (COLS, buffer);
+       mutt_draw_statusline (COLS, buffer);
       }
       else
       {
        char bn[STRING];
        snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
-       mutt_paddstr (COLS, bn);
+       mutt_draw_statusline (COLS, bn);
       }
       NORMAL_COLOR;
       if (option(OPTTSENABLED) && TSSupported)
index 2ba4d1d571c374b703d253af31a1aa5d55d93399..ef5b54a405150bd8a9a7c25abc064c97fbb72175 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -180,6 +180,7 @@ void mutt_decode_base64 (STATE *s, long len, int istext, iconv_t cd);
 void mutt_default_save (char *, size_t, HEADER *);
 void mutt_display_address (ENVELOPE *);
 void mutt_display_sanitize (char *);
+void mutt_draw_statusline(int n, char *);
 void mutt_edit_content_type (HEADER *, BODY *, FILE *);
 void mutt_edit_file (const char *, const char *);
 void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);