> 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