]> 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>
Thu, 18 Aug 2016 15:15:36 +0000 (16:15 +0100)
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 c33d41ebc2250cb42219911a87a0b79ed59c4eae..76839431bd46c5adf0bc226a1e7c4e257222ab0f 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 */
@@ -506,7 +507,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
@@ -577,6 +578,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)
     {
@@ -719,7 +721,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;
@@ -727,8 +729,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))
@@ -740,7 +740,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);
@@ -765,12 +765,37 @@ _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 8e0f52ad837eadbee37601851c2626956f4e9e01..621f1b2b2158a48b50c98a1e015aa7c5082fcea0 100644 (file)
@@ -482,6 +482,127 @@ static void resort_index (MUTTMENU *menu)
   menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
 }
 
+/**
+ * mutt_draw_statusline - Draw a highlighted status bar
+ * @cols:  Maximum number of screen columns
+ * @buf:   Message to be displayed
+ *
+ * Users configure the highlighting of the status bar, e.g.
+ *     color status red default "[0-9][0-9]:[0-9][0-9]"
+ *
+ * Where regexes overlap, the one nearest the start will be used.
+ * If two regexes start at the same place, the longer match will be used.
+ */
+void
+mutt_draw_statusline (int cols, const char *buf, int buflen)
+{
+       int i      = 0;
+       int offset = 0;
+       int found  = 0;
+       int chunks = 0;
+       int len    = 0;
+
+       struct syntax_t {
+               int color;
+               int first;
+               int last;
+       } *syntax = NULL;
+
+       if (!buf)
+               return;
+
+       do {
+               COLOR_LINE *cl;
+               found = 0;
+
+               if (!buf[offset])
+                       break;
+
+               /* loop through each "color status regex" */
+               for (cl = ColorStatusList; cl; cl = cl->next) {
+                       regmatch_t pmatch[cl->match + 1];
+
+                       if (regexec (&cl->rx, buf + offset, cl->match + 1, pmatch, 0) != 0)
+                               continue;       /* regex doesn't match the status bar */
+
+                       int first = pmatch[cl->match].rm_so + offset;
+                       int last  = pmatch[cl->match].rm_eo + offset;
+
+                       if (first == last)
+                               continue;       /* ignore an empty regex */
+
+                       if (!found) {
+                               chunks++;
+                               safe_realloc (&syntax, chunks * sizeof (struct syntax_t));
+                       }
+
+                       i = chunks - 1;
+                       if (!found || (first < syntax[i].first) || ((first == syntax[i].first) && (last > syntax[i].last))) {
+                               syntax[i].color = cl->pair;
+                               syntax[i].first = first;
+                               syntax[i].last  = last;
+                       }
+                       found = 1;
+               }
+
+               if (syntax) {
+                       offset = syntax[i].last;
+               }
+       } while (found);
+
+       /* Only 'len' bytes will fit into 'cols' screen columns */
+       len = mutt_wstr_trunc (buf, buflen, cols, NULL);
+
+       offset = 0;
+
+       if ((chunks > 0) && (syntax[0].first > 0)) {
+               /* Text before the first highlight */
+               addnstr (buf, MIN(len, syntax[0].first));
+               attrset (ColorDefs[MT_COLOR_STATUS]);
+               if (len <= syntax[0].first)
+                       goto dsl_finish;        /* no more room */
+
+               offset = syntax[0].first;
+       }
+
+       for (i = 0; i < chunks; i++) {
+               /* Highlighted text */
+               attrset (syntax[i].color);
+               addnstr (buf + offset, MIN(len, syntax[i].last) - offset);
+               if (len <= syntax[i].last)
+                       goto dsl_finish;        /* no more room */
+
+               int next;
+               if ((i + 1) == chunks) {
+                       next = len;
+               } else {
+                       next = MIN (len, syntax[i+1].first);
+               }
+
+               attrset (ColorDefs[MT_COLOR_STATUS]);
+               offset = syntax[i].last;
+               addnstr (buf + offset, next - offset);
+
+               offset = next;
+               if (offset >= len)
+                       goto dsl_finish;        /* no more room */
+       }
+
+       attrset (ColorDefs[MT_COLOR_STATUS]);
+       if (offset < len) {
+               /* Text after the last highlight */
+               addnstr (buf + offset, len - offset);
+       }
+
+       int width = mutt_strwidth (buf);
+       if (width < cols) {
+               /* Pad the rest of the line with whitespace */
+               mutt_paddstr (cols - width, "");
+       }
+dsl_finish:
+       FREE(&syntax);
+}
+
 static const struct mapping_t IndexHelp[] = {
   { N_("Quit"),  OP_QUIT },
   { N_("Del"),   OP_DELETE },
@@ -647,7 +768,7 @@ int mutt_index_menu (void)
        menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
         mutt_window_move (MuttStatusWindow, 0, 0);
        SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (MuttStatusWindow->cols, buf);
+       mutt_draw_statusline (MuttStatusWindow->cols, buf, sizeof (buf));
        NORMAL_COLOR;
        menu->redraw &= ~REDRAW_STATUS;
        if (option(OPTTSENABLED) && TSSupported)
index 62004491fcb44f0cec4574dd8c881f5492989303..ba8aa5279c01e70010ebb13c46879ef31bbf30a0 100644 (file)
@@ -137,6 +137,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 */
@@ -212,6 +213,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 d7674eb30cb92cc31cfcf59ca39096e1f7624378..f9b9bbbe43e71af85ea782176be7f79893ebf85a 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -1860,13 +1860,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, pager_status_window->cols, NONULL (PagerFmt), &hfi, MUTT_FORMAT_MAKEPRINT);
-       mutt_paddstr (pager_status_window->cols, buffer);
+       mutt_draw_statusline (pager_status_window->cols, buffer, l2);
       }
       else
       {
        char bn[STRING];
        snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
-       mutt_paddstr (pager_status_window->cols, bn);
+       mutt_draw_statusline (pager_status_window->cols, bn, sizeof (bn));
       }
       NORMAL_COLOR;
       if (option(OPTTSENABLED) && TSSupported)
index 19d640032ae1da433f17215d5b46439a66c7781d..ced7f2fb3c64185ccfa7c624c17e0d0b7793bf0e 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -182,6 +182,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 cols, const char *buf, int buflen);
 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);