nmh-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nmh-commits] [SCM] The nmh Mail Handling System branch, master, updated


From: Ken Hornstein
Subject: [Nmh-commits] [SCM] The nmh Mail Handling System branch, master, updated. 3a85e0bc9c72935ca9d154b3aa3093c31ed1836e
Date: Wed, 21 Mar 2012 19:28:40 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The nmh Mail Handling System".

The branch, master has been updated
       via  3a85e0bc9c72935ca9d154b3aa3093c31ed1836e (commit)
      from  24ba06b111dbadb912fa97f74ec8595f71b04393 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/nmh.git/commit/?id=3a85e0bc9c72935ca9d154b3aa3093c31ed1836e


commit 3a85e0bc9c72935ca9d154b3aa3093c31ed1836e
Author: Ken Hornstein <address@hidden>
Date:   Wed Mar 21 15:27:15 2012 -0400

    Support for readline command history, editing, and completion at the
    WhatNow? prompt.  Based on work by Steve Rader.

diff --git a/Makefile.am b/Makefile.am
index 0727fea..14d1dd1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -230,11 +230,11 @@ uip_burst_SOURCES = uip/burst.c
 
 uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c 
\
                   uip/annosbr.c uip/distsbr.c
-uip_comp_LDADD = $(LDADD) $(ICONVLIB)
+uip_comp_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
 
 uip_dist_SOURCES = uip/dist.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c 
\
                   uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_dist_LDADD = $(LDADD) $(ICONVLIB)
+uip_dist_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
 
 uip_flist_SOURCES = uip/flist.c
 
@@ -242,7 +242,7 @@ uip_folder_SOURCES = uip/folder.c
 
 uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c 
\
                   uip/annosbr.c uip/distsbr.c uip/forwsbr.c
-uip_forw_LDADD = $(LDADD) $(ICONVLIB)
+uip_forw_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
 
 uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/termsbr.c \
                  uip/popsbr.c
@@ -302,7 +302,7 @@ uip_refile_SOURCES = uip/refile.c
 
 uip_repl_SOURCES = uip/repl.c uip/replsbr.c uip/whatnowproc.c \
                   uip/whatnowsbr.c uip/sendsbr.c uip/annosbr.c uip/distsbr.c
-uip_repl_LDADD = $(LDADD) $(ICONVLIB)
+uip_repl_LDADD = $(LDADD) $(ICONVLIB) $(READLINELIB)
 
 uip_rmf_SOURCES = uip/rmf.c
 
@@ -320,6 +320,7 @@ uip_sortm_SOURCES = uip/sortm.c
 
 uip_whatnow_SOURCES = uip/whatnow.c uip/whatnowsbr.c uip/sendsbr.c \
                      uip/annosbr.c uip/distsbr.c
+uip_whatnow_LDADD = $(LDADD) $(READLINELIB)
 
 uip_whom_SOURCES = uip/whom.c uip/distsbr.c
 
@@ -476,7 +477,8 @@ sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr/ambigsw.c 
sbr/atooi.c sbr/brkstring.c \
                      sbr/snprintb.c sbr/ssequal.c sbr/strcasecmp.c \
                      sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \
                      sbr/fmt_def.c sbr/m_msgdef.c sbr/mf.c sbr/utils.c \
-                     sbr/m_mktemp.c config/config.c config/version.c
+                     sbr/m_mktemp.c sbr/getansreadline.c config/config.c \
+                     config/version.c
 
 sbr_libmh_a_CPPFLAGS = -I./sbr -DNMHETCDIR='"$(sysconfdir)"' \
                -DMAILSPOOL='"$(mailspool)"' \
diff --git a/configure.ac b/configure.ac
index 0b512b3..480c8be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,6 +113,8 @@ AS_IF([test x"$with_mts" = x"smtp"], [MTS="smtp"],
       [MTS="smtp"])
 AC_SUBST([MTS])dnl
 
+NMH_READLINE
+
 dnl What should be the default pager?
 AC_ARG_WITH([pager],
   AS_HELP_STRING([--with-pager=PAGER],[specify the default pager]))
diff --git a/docs/pending-release-notes b/docs/pending-release-notes
index a867299..fa8147c 100644
--- a/docs/pending-release-notes
+++ b/docs/pending-release-notes
@@ -57,3 +57,5 @@ Things to add to the release notes for the next full release:
   obsolete/deprecated:  -noatfile will become the default in the next
   nmh release.  If there are no requests to maintain -atfile, it will
   be removed in the future.
+- Added support for readline editing and command/filename completion at
+  the WhatNow? prompt
diff --git a/h/prototypes.h b/h/prototypes.h
index 935c593..38357a8 100644
--- a/h/prototypes.h
+++ b/h/prototypes.h
@@ -57,6 +57,9 @@ struct msgs *folder_read (char *);
 struct msgs *folder_realloc (struct msgs *, int, int);
 int gans (char *, struct swit *);
 char **getans (char *, struct swit *);
+#ifdef READLINE_SUPPORT
+char **getans_via_readline (char *, struct swit *);
+#endif /* READLINE_SUPPORT */
 int getanswer (char *);
 char **getarguments (char *, int, char **, int);
 char *get_charset(void);
diff --git a/m4/readline.m4 b/m4/readline.m4
new file mode 100644
index 0000000..7a2710d
--- /dev/null
+++ b/m4/readline.m4
@@ -0,0 +1,25 @@
+dnl
+dnl Our readline heuristic.  If we haven't been asked about readline, then
+dnl try to compile with it.  If we've been asked for it, then we fail
+dnl if we cannot use it.  If we were explicitly NOT asked for it, then
+dnl don't even try to use it.
+dnl
+
+AC_DEFUN([NMH_READLINE],
+[AC_ARG_WITH([readline],
+       AS_HELP_STRING([--with-readline],
+                      [enable readline editing for whatnow (default=maybe)]),
+       [], [with_readline=maybe])
+AS_IF([test x"$with_readline" = xyes -o x"$with_readline" = xmaybe],
+    [save_LIBS="$LIBS"
+    LIBS=
+    AC_SEARCH_LIBS([readline], [readline editline],
+                  [READLINELIB="$LIBS"
+                  AC_DEFINE([READLINE_SUPPORT], [1],
+                            [Support for using readline() in whatnow])],
+                  [AS_IF([test x"$with_readline" = xyes],
+                         [AC_MSG_ERROR([Unable to find a readline library])])])
+    LIBS="$save_LIBS"])
+])
+
+AC_SUBST([READLINELIB])
diff --git a/sbr/getansreadline.c b/sbr/getansreadline.c
new file mode 100644
index 0000000..0daaa49
--- /dev/null
+++ b/sbr/getansreadline.c
@@ -0,0 +1,212 @@
+
+/*
+ * getansreadline.c -- get an answer from the user, with readline
+ *
+ * This code is Copyright (c) 2012, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/signals.h>
+#include <h/m_setjmp.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef READLINE_SUPPORT
+#include <readline/readline.h>
+#include <readline/history.h>
+
+static struct swit *rl_cmds;
+
+static char *nmh_command_generator(const char *, int);
+static char **nmh_completion(const char *, int, int);
+static void initialize_readline(void);
+
+static char ansbuf[BUFSIZ];
+static sigjmp_buf sigenv;
+
+#if 0
+/*
+ * static prototypes
+ */
+static void intrser (int);
+
+
+char **
+getans (char *prompt, struct swit *ansp)
+{
+    int i;
+    SIGNAL_HANDLER istat = NULL;
+    char *cp, **cpp;
+
+    if (!(sigsetjmp(sigenv, 1))) {
+       istat = SIGNAL (SIGINT, intrser);
+    } else {
+       SIGNAL (SIGINT, istat);
+       return NULL;
+    }
+
+    for (;;) {
+       printf ("%s", prompt);
+       fflush (stdout);
+       cp = ansbuf;
+       while ((i = getchar ()) != '\n') {
+           if (i == EOF) {
+               /*
+                * If we get an EOF, return
+                */
+               if (feof(stdin))
+                   siglongjmp (sigenv, 1);
+
+               /*
+                * For errors, if we get an EINTR that means that we got
+                * a signal and we should retry.  If we get another error,
+                * then just return.
+                */
+
+               else if (ferror(stdin)) {
+                   if (errno == EINTR) {
+                       clearerr(stdin);
+                       continue;
+                   }
+                   fprintf(stderr, "\nError %s during read\n",
+                           strerror(errno));
+                   siglongjmp (sigenv, 1);
+               } else {
+                   /*
+                    * Just for completeness's sake ...
+                    */
+
+                   fprintf(stderr, "\nUnknown problem in getchar()\n");
+                   siglongjmp (sigenv, 1);
+               }
+           }
+           if (cp < &ansbuf[sizeof ansbuf - 1])
+               *cp++ = i;
+       }
+       *cp = '\0';
+       if (ansbuf[0] == '?' || cp == ansbuf) {
+           printf ("Options are:\n");
+           print_sw (ALL, ansp, "", stdout);
+           continue;
+       }
+       cpp = brkstring (ansbuf, " ", NULL);
+       switch (smatch (*cpp, ansp)) {
+           case AMBIGSW: 
+               ambigsw (*cpp, ansp);
+               continue;
+           case UNKWNSW: 
+               printf (" -%s unknown. Hit <CR> for help.\n", *cpp);
+               continue;
+           default: 
+               SIGNAL (SIGINT, istat);
+               return cpp;
+       }
+    }
+}
+
+
+static void
+intrser (int i)
+{
+    NMH_UNUSED (i);
+
+    /*
+     * should this be siglongjmp?
+     */
+    siglongjmp (sigenv, 1);
+}
+#endif
+
+/*
+ * getans, but with readline support
+ */
+
+char **
+getans_via_readline(char *prompt, struct swit *ansp)
+{
+    char *ans, **cpp;
+
+    initialize_readline();
+    rl_cmds = ansp;
+
+    for (;;) {
+       ans = readline(prompt);
+       /*
+        * If we get an EOF, return
+        */
+
+       if (ans == NULL)
+           return NULL;
+
+       if (ans[0] == '?' || ans[0] == '\0') {
+           printf("Options are:\n");
+           print_sw(ALL, ansp, "", stdout);
+           free(ans);
+           continue;
+       }
+       add_history(ans);
+       strncpy(ansbuf, ans, sizeof(ansbuf));
+       ansbuf[sizeof(ansbuf) - 1] = '\0';
+       cpp = brkstring(ansbuf, " ", NULL);
+       switch (smatch(*cpp, ansp)) {
+           case AMBIGSW:
+               ambigsw(*cpp, ansp);
+               continue;
+           case UNKWNSW:
+               printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
+               continue;
+           default:
+               free(ans);
+               return cpp;
+       }
+       free(ans);
+    }
+}
+
+static void
+initialize_readline(void)
+{
+    rl_readline_name = "Nmh";
+    rl_attempted_completion_function = nmh_completion;
+}
+
+static char **
+nmh_completion(const char *text, int start, int end)
+{
+    char **matches;
+
+    matches = (char **) NULL;
+
+    if (start == 0)
+       matches = rl_completion_matches(text, nmh_command_generator);
+
+    return matches;
+}
+
+static char *
+nmh_command_generator(const char *text, int state)
+{
+    static int list_index, len;
+    char *name, *p;
+    char buf[256];
+
+    if (!state) {
+       list_index = 0;
+       len = strlen(text);
+    }
+
+    while (name = rl_cmds[list_index].sw) {
+       list_index++;
+       strncpy(buf, name, sizeof(buf));
+       buf[sizeof(buf) - 1] = '\0';
+       p = *brkstring(buf, " ", NULL);
+       if (strncmp(p, text, len) == 0)
+       return strdup(p);
+    }
+
+    return NULL;
+}
+#endif /* READLINE_SUPPORT */
+
diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c
index 7b63762..6830bfb 100644
--- a/uip/whatnowsbr.c
+++ b/uip/whatnowsbr.c
@@ -249,7 +249,11 @@ WhatNow (int argc, char **argv)
 
     snprintf (prompt, sizeof(prompt), myprompt, invo_name);
     for (;;) {
+#ifdef READLINE_SUPPORT
+       if (!(argp = getans_via_readline (prompt, aleqs))) {
+#else /* ! READLINE_SUPPORT */
        if (!(argp = getans (prompt, aleqs))) {
+#endif /* READLINE_SUPPORT */
            unlink (LINK);
            done (1);
        }

-----------------------------------------------------------------------

Summary of changes:
 Makefile.am                |   12 ++-
 configure.ac               |    2 +
 docs/pending-release-notes |    2 +
 h/prototypes.h             |    3 +
 m4/readline.m4             |   25 +++++
 sbr/getansreadline.c       |  212 ++++++++++++++++++++++++++++++++++++++++++++
 uip/whatnowsbr.c           |    4 +
 7 files changed, 255 insertions(+), 5 deletions(-)
 create mode 100644 m4/readline.m4
 create mode 100644 sbr/getansreadline.c


hooks/post-receive
-- 
The nmh Mail Handling System



reply via email to

[Prev in Thread] Current Thread [Next in Thread]