<<< Date Index >>>     <<< Thread Index >>>

[PATCH] Add 'show' keyword



Hi,

the attached patch adds a 'show' keyword to display certain runtime information in paged menus.

Currently implemented are:

1) 'show attachments' to show current attachment configs (replaces 'attachments ?' which is kept for compatibility)

2) 'show config [regex]' to display all mutt options matching a regex (which is '.' if ommitted) by name

As this is a proof-of-concept only, docs are still totally missing...

A note: I tried to abstract the interface as much as possible so that (finally, maybe) the help menu (from which the paging code is borrowed) can be implemented this way, e.g.

- 'show help' gets the current help just as '?' does and '?' can be implemented using mutt_show() using the data pointer for passing the menu

- 'show help pager' gives you the help for pager no matter where you are currently (context sensitive help is nice, but having the choice is always better :)

I'm not quite sure yet about the curses issue: If there was a way to tell whether mutt is in curses mode or not, one could even use that output in scripts if it weren't directed to a tempfile but stdout... Or 'show help' could get flags 'bound' and 'unbound' to display only these items or... Please stop me if this far too much of feature. :)

  bye, Rocco
--
:wq!
diff --git a/Makefile.am b/Makefile.am
index d834012..21c5b1e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,7 +26,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \
        main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
        postpone.c query.c recvattach.c recvcmd.c \
        rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \
-       score.c send.c sendlib.c signal.c sort.c \
+       score.c send.c sendlib.c show.c signal.c sort.c \
        status.c system.c thread.c charset.c history.c lib.c \
        muttlib.c editmsg.c mbyte.c \
        url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
diff --git a/init.c b/init.c
index 46c1c22..ec87307 100644
--- a/init.c
+++ b/init.c
@@ -30,6 +30,8 @@
 #include "charset.h"
 #include "mutt_crypt.h"
 #include "mutt_idna.h"
+#include "pager.h"
+#include "show.h"
 
 #if defined(USE_SSL)
 #include "mutt_ssl.h"
@@ -1085,18 +1087,71 @@ static int parse_unattach_list (BUFFER *buf, BUFFER *s, 
LIST **ldata, BUFFER *er
   return 0;
 }
 
-static int print_attach_list (LIST *lp, char op, char *name)
+const char* mutt_show_config (FILE* dst, int width, const char *args, unsigned 
long data)
 {
-  while (lp) {
-    printf("attachments %c%s %s/%s\n", op, name,
-           ((ATTACH_MATCH *)lp->data)->major,
-           ((ATTACH_MATCH *)lp->data)->minor);
-    lp = lp->next;
+  int i, rc;
+  char errbuf[STRING];
+  char command[STRING];
+  BUFFER err, token;
+  regex_t rx;
+
+  memset (&err, 0, sizeof (err));
+  memset (&token, 0, sizeof (token));
+  memset (&rx, 0, sizeof (regex_t));
+
+  err.data = errbuf;
+  err.dsize = sizeof (errbuf);
+
+  if (!args || !*args)
+    args = ".";
+
+  if ((rc = REGCOMP (&rx, args, REG_ICASE)) != 0)
+  {
+    regerror (rc, &rx, errbuf, sizeof (errbuf));
+    regfree (&rx);
+    mutt_error (_("Error parsing config option regex: %s"), errbuf);
+    return NULL;
   }
 
-  return 0;
+  for (i = 0; MuttVars[i].option; i++)
+  {
+    if (MuttVars[i].type == DT_SYN)
+      continue;
+    if (regexec (&rx, MuttVars[i].option, (size_t) 0, (regmatch_t *) NULL, 
(int) 0) != 0)
+      continue;
+    snprintf (command, sizeof (command), "set ?%s\n", MuttVars[i].option);
+    if (mutt_parse_rc_line (command, &token, &err) == -1)
+    {
+      regfree (&rx);
+      mutt_error ("%s\n", err.data);
+      FREE (&token.data);
+      return NULL;
+    }
+    fprintf (dst, "%s\n", err.data);
+  }
+  regfree (&rx);
+  FREE (&token.data);
+  snprintf (command, sizeof (command), _("Current configuration [%s]"), args);
+  return safe_strdup (command);
 }
 
+static int parse_show (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
+{
+  int rc;
+
+  mutt_extract_token (buf, s, 0);
+  if (!buf->data || *buf->data == '\0') {
+    strfcpy(err->data, _("show: need a keyword"), err->dsize);
+    return -1;
+  }
+
+  rc = mutt_show (buf->data, s->dptr, 0);
+
+  /* mark all remaining data as parsed */
+  s->dptr = s->data + s->dsize;
+
+  return rc;
+}
 
 static int parse_attachments (BUFFER *buf, BUFFER *s, unsigned long data, 
BUFFER *err)
 {
@@ -1112,19 +1167,9 @@ static int parse_attachments (BUFFER *buf, BUFFER *s, 
unsigned long data, BUFFER
   category = buf->data;
   op = *category++;
 
-  if (op == '?') {
-    mutt_endwin (NULL);
-    fflush (stdout);
-    printf("\nCurrent attachments settings:\n\n");
-    print_attach_list(AttachAllow,   '+', "A");
-    print_attach_list(AttachExclude, '-', "A");
-    print_attach_list(InlineAllow,   '+', "I");
-    print_attach_list(InlineExclude, '-', "I");
-    set_option (OPTFORCEREDRAWINDEX);
-    set_option (OPTFORCEREDRAWPAGER);
-    mutt_any_key_to_continue (NULL);
-    return 0;
-  }
+  if (op == '?')
+    /* backwards compatibility */
+    return mutt_show ("attachments", NULL, 0);
 
   if (op != '+' && op != '-') {
     op = '+';
diff --git a/init.h b/init.h
index a3d4c78..53ad44f 100644
--- a/init.h
+++ b/init.h
@@ -3119,6 +3119,7 @@ static int parse_unalternates (BUFFER *, BUFFER *, 
unsigned long, BUFFER *);
 /* Parse -group arguments */
 static int parse_group_context (group_context_t **ctx, BUFFER *buf, BUFFER *s, 
unsigned long data, BUFFER *err);
 
+static int parse_show (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 
 struct command_t
 {
@@ -3176,6 +3177,7 @@ struct command_t Commands[] = {
   { "send-hook",       mutt_parse_hook,        M_SENDHOOK },
   { "send2-hook",      mutt_parse_hook,        M_SEND2HOOK },
   { "set",             parse_set,              0 },
+  { "show",            parse_show,             0 },
   { "source",          parse_source,           0 },
   { "spam",            parse_spam_list,        M_SPAM },
   { "nospam",          parse_spam_list,        M_NOSPAM },
diff --git a/protos.h b/protos.h
index 2b944e4..5a99381 100644
--- a/protos.h
+++ b/protos.h
@@ -386,6 +386,10 @@ int mutt_from_base64 (char*, const char*);
 /* utf8.c */
 int mutt_wctoutf8 (char *s, unsigned int c);
 
+/* 'show' handlers for show.[ch] */
+const char* mutt_show_attachments (FILE *, int, const char *, unsigned long);
+const char* mutt_show_config (FILE *, int, const char *, unsigned long);
+
 #ifdef LOCALES_HACK
 #define IsPrint(c) (isprint((unsigned char)(c)) || \
        ((unsigned char)(c) >= 0xa0))
diff --git a/show.c b/show.c
new file mode 100644
index 0000000..81d4397
--- /dev/null
+++ b/show.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 1996-2007 ?
+ * Copyright (C) 2007 Rocco Rutte <pdmef@xxxxxxx>
+ * 
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
02110-1301, USA.
+ */ 
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mutt.h"
+#include "pager.h"
+#include "mutt_curses.h"
+
+#define _SHOW_C         1
+#include "show.h"
+  
+static int print_attach_list (FILE *f, LIST *lp, char op, char *name)
+{
+  while (lp) {
+    fprintf(f, "attachments %c%s %s/%s\n", op, name,
+           ((ATTACH_MATCH *)lp->data)->major,
+           ((ATTACH_MATCH *)lp->data)->minor);
+    lp = lp->next;
+  }
+
+  return 0;
+}
+ 
+const char* mutt_show_attachments (FILE *dst, int width, const char *args, 
unsigned long data)
+{
+    print_attach_list(dst, AttachAllow,   '+', "A");
+    print_attach_list(dst, AttachExclude, '-', "A");
+    print_attach_list(dst, InlineAllow,   '+', "I");
+    print_attach_list(dst, InlineExclude, '-', "I");
+    return safe_strdup (_("Current attachment settings"));
+}
+
+int mutt_show (const char *keyword, const char *args, unsigned long data)
+{
+  int i, rc = 0;
+  static int running = 0;
+  const char *title = NULL;
+  char tmpfile[_POSIX_PATH_MAX];
+  FILE *f;
+
+  for (i = 0; ShowHandlers[i].key; i++)
+    if (ascii_strcasecmp (ShowHandlers[i].key, keyword) == 0)
+      break;
+
+  if (!ShowHandlers[i].key)
+  {
+    mutt_error (_("Unknown show menu '%s'"), keyword);
+    return -1;
+  }
+
+  if (running)
+  {
+    mutt_error _("Only one show menu allowed at a time.");
+    return -1;
+  }
+
+  do {
+    running = 1;
+    mutt_mktemp (tmpfile);
+    if ((f = safe_fopen (tmpfile, "w")) == NULL)
+    {
+      mutt_perror (tmpfile);
+      rc = -1;
+      break;
+    }
+    if (title && *title)
+      FREE(&title);
+    if ((title = ShowHandlers[i].fn (f, COLS, args, data)) == NULL)
+    {
+      rc = -1;
+      break;
+    }
+    fclose (f);
+  } while (mutt_do_pager (title, tmpfile,
+                          M_PAGER_RETWINCH | M_PAGER_MARKER | M_PAGER_NSKIP,
+                          NULL)
+           == OP_REFORMAT_WINCH);
+
+  if (title && *title)
+    FREE(&title);
+  if (f)
+    fclose (f);
+
+  set_option (OPTFORCEREDRAWINDEX);
+  set_option (OPTFORCEREDRAWPAGER);
+
+  running = 0;
+  return rc;
+}
diff --git a/show.h b/show.h
new file mode 100644
index 0000000..422a876
--- /dev/null
+++ b/show.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Rocco Rutte <pdmef@xxxxxxx>
+ * 
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
02110-1301, USA.
+ */ 
+
+#ifndef _SHOW_H
+#define _SHOW_H
+
+#ifdef _SHOW_C
+
+/*
+ * Callback for 'show' keyword, params
+ *   1) Destination file for output
+ *   2) Preferred width of output file
+ *   3) Additional arguments given
+ *   4) Any data passed down from mutt_show()
+ * Returns: strdup()'ed title or NULL in case of failure
+ */
+typedef const char*(*fmt_show_fn_t)(FILE *, int, const char *, unsigned long);
+
+static struct
+{
+  const char *key;
+  fmt_show_fn_t fn;
+}
+ShowHandlers[] =
+{
+  { "attachments",              mutt_show_attachments   },
+  { "config",                   mutt_show_config        },
+  /* last */
+  { NULL,                       NULL                    }
+};
+
+#endif /* !_SHOW_C */
+
+int mutt_show (const char *keyword, const char *args, unsigned long data);
+
+#endif /* !_SHOW_H */