[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 */