> Date: Tue, 21 Dec 2010 09:38:45 CST
 > To: Peter Maydell <[email protected]>, [email protected]
 > From: [email protected]
 > Subject: Re: [Nmh-workers] GNU readline whatnowproc (was tab completion)
 >
 > I like everything you've said.  I'll send along a better patch for
 > consideration soon.

364 days later... here's a patch that I think correctly adds readline
support to whatnowproc... some advice please...

(1) Is it really safe to wedge this in everywhere like Peter Maydell
asked for back on 12/21/2010??  

(2) What's the nmh native way to do...
  char *dupstr (char *s) {
    char *r;
    r = xmalloc (strlen (s) + 1);
    strcpy (r, s);
    return (r);
  }
?

(3) I'm not exactly sure why there are parens in some of the option syntax
listings like "(de)tach [-n]".  I suspect they're indicating "de" is acceptable
(in a non-readline-world), and thus this code (in a readlin eworld) should
remove the parens?

(4) I'm not motivated to also auto-complete switches.  Perhaps that's okay.
Perhaps someone else can add that.

steve
--
diff --git a/configure.in b/configure.in
index e93e173..476397b 100644
--- a/configure.in
+++ b/configure.in
@@ -201,6 +201,22 @@ else
 fi
 AC_SUBST(smtpservers)dnl
 
+dnl Do you want whatnow to use readline()?
+dnl (e.g. enable tab completion and editor support)
+AC_ARG_WITH([readline],
+  [AS_HELP_STRING([--with-readline],
+    [enable line-editing when using whatnow])],
+  [],
+  [with_readline=yes])
+if test x"$with_readline" = x"yes"; then
+  AC_DEFINE(HAVE_LIBREADLINE, 1,
+    [Define if you have libreadline.])dnl
+  LIBREADLINE="-lreadline -lncurses"
+else
+  LIBREADLINE=
+fi
+AC_SUBST(LIBREADLINE)dnl
+
 dnl ----------------------------------------------------
 dnl Default location is /usr/local/nmh/{bin,etc,lib,man}
 dnl ----------------------------------------------------
diff --git a/sbr/getans.c b/sbr/getans.c
index 3229eb5..b8c4df1 100644
--- a/sbr/getans.c
+++ b/sbr/getans.c
@@ -12,6 +12,18 @@
 #include <setjmp.h>
 #include <signal.h>
 
+#if HAVE_LIBREADLINE
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+static struct swit *rl_cmds;
+
+char *nmh_command_generator PARAMS((const char *, int));
+char **nmh_completion PARAMS((const char *, int, int));
+
+#endif
+
 static char ansbuf[BUFSIZ];
 static jmp_buf sigenv;
 
@@ -20,7 +32,6 @@ static jmp_buf sigenv;
  */
 static RETSIGTYPE intrser (int);
 
-
 char **
 getans (char *prompt, struct swit *ansp)
 {
@@ -66,6 +77,97 @@ getans (char *prompt, struct swit *ansp)
     }
 }
 
+#if HAVE_LIBREADLINE
+
+char **
+getans_via_readline (char *prompt, struct swit *ansp)
+{
+    char *ans, **cpp;
+
+    initialize_readline (); 
+    rl_cmds = ansp;
+
+    for (;;) {
+        ans = readline (prompt);
+        if (ans == NULL || ans[0] == '?' || ans[0] == 0 ) {
+            printf ("Options are:\n");
+            print_sw (ALL, ansp, "", stdout);
+            free(ans);
+           continue;
+        }
+        strcpy (ansbuf,ans);
+        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);
+    }
+}
+
+// HERE use the mh equiv...
+char *
+dupstr (char *s)
+{
+  char *r;
+  r = xmalloc (strlen (s) + 1);
+  strcpy (r, s);
+  return (r);
+}
+// ...HERE
+
+void
+initialize_readline ()
+{
+  rl_readline_name = "Nmh";
+  rl_attempted_completion_function = nmh_completion;
+}
+
+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);
+}
+
+char *
+nmh_command_generator (const char *text, int state)
+{
+  static int list_index, len;
+  char *name;
+  char buf[256];
+  char *p;
+
+  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 (dupstr(p));
+  }
+
+  return ((char *)NULL);
+}
+
+#endif
 
 static RETSIGTYPE
 intrser (int i)
diff --git a/uip/Makefile.in b/uip/Makefile.in
index 370fc15..91a320d 100644
--- a/uip/Makefile.in
+++ b/uip/Makefile.in
@@ -23,8 +23,9 @@ LDFLAGS  = @LDFLAGS@
 LIBS     = @LIBS@
 MTSLIB   = ../mts/libmts.a
 NDBM_LIBS = @NDBM_LIBS@
+READLINE_LIBS = @LIBREADLINE@
 LOCALLIBS = ../config/version.o ../config/config.o $(MTSLIB) ../sbr/libmh.a
-LINKLIBS = $(LOCALLIBS) $(LIBS)
+LINKLIBS = $(READLINE_LIBS) $(LOCALLIBS) $(LIBS)
 
 LINT   = @LINT@
 LINTFLAGS = @LINTFLAGS@
diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c
index 6541b42..3aff4b8 100644
--- a/uip/whatnowsbr.c
+++ b/uip/whatnowsbr.c
@@ -245,7 +245,11 @@ WhatNow (int argc, char **argv)
 
     snprintf (prompt, sizeof(prompt), myprompt, invo_name);
     for (;;) {
+#ifndef HAVE_LIBREADLINE
        if (!(argp = getans (prompt, aleqs))) {
+#else
+       if (!(argp = getans_via_readline (prompt, aleqs))) {
+#endif
            unlink (LINK);
            done (1);
        }
_______________________________________________
Nmh-workers mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/nmh-workers

Reply via email to