diff --git a/configure b/configure index 819f9ce..ce5b211 100755 --- a/configure +++ b/configure @@ -695,6 +695,8 @@ CPP GREP EGREP LIBOBJS +COMPLETE_TRUE +COMPLETE_FALSE LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias @@ -1283,6 +1285,7 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors + --enable-default-complete Enable default completion handler. Some influential environment variables: CC C compiler command @@ -4970,6 +4973,35 @@ fi done +# Check whether --enable-complete was given. +if test "${enable_complete+set}" = set; then + enableval=$enable_complete; + case "${enableval}" in + yes) + complete=true + ;; + no) + complete=false + ;; + *) + { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-default-complete" >&5 +echo "$as_me: error: bad value ${enableval} for --enable-default-complete" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +else + complete=false +fi + + if test x$complete = xtrue; then + COMPLETE_TRUE= + COMPLETE_FALSE='#' +else + COMPLETE_TRUE='#' + COMPLETE_FALSE= +fi + + ac_config_files="$ac_config_files Makefile src/Makefile include/Makefile man/Makefile examples/Makefile" cat >confcache <<\_ACEOF @@ -5082,6 +5114,13 @@ echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${COMPLETE_TRUE}" && test -z "${COMPLETE_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"COMPLETE\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"COMPLETE\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files @@ -5698,10 +5737,12 @@ CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LIBOBJS!$LIBOBJS$ac_delim +COMPLETE_TRUE!$COMPLETE_TRUE$ac_delim +COMPLETE_FALSE!$COMPLETE_FALSE$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 81; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 83; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.ac b/configure.ac index 313704f..3764fdd 100644 --- a/configure.ac +++ b/configure.ac @@ -40,4 +40,19 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_STAT AC_CHECK_FUNCS([strchr strdup strrchr tcgetattr]) +AC_ARG_ENABLE([complete], + [ --enable-default-complete Enable default completion handler.],[ + case "${enableval}" in + yes) + complete=true + ;; + no) + complete=false + ;; + *) + AC_MSG_ERROR([bad value ${enableval} for --enable-default-complete]) + ;; + esac],[complete=false]) +AM_CONDITIONAL([COMPLETE], [test x$complete = xtrue]) + AC_OUTPUT(Makefile src/Makefile include/Makefile man/Makefile examples/Makefile) diff --git a/examples/Makefile.am b/examples/Makefile.am index 262abdb..f3bb128 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,10 +1,10 @@ AUTOMAKE_OPTIONS = foreign LDADD = $(top_builddir)/src/libedit.a -AM_CFLAGS = -I$(top_srcdir)/src +AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include # TODO: Port "fileman" example from BSD editline -noinst_PROGRAMS = testit +noinst_PROGRAMS = testit cli testit_SOURCES = testit.c #fileman_SOURCES = fileman.c diff --git a/examples/Makefile.in b/examples/Makefile.in index 28c6da0..70c362d 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -30,7 +30,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -noinst_PROGRAMS = testit$(EXEEXT) +noinst_PROGRAMS = testit$(EXEEXT) cli$(EXEEXT) subdir = examples DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -41,6 +41,10 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = PROGRAMS = $(noinst_PROGRAMS) +cli_SOURCES = cli.c +cli_OBJECTS = cli.$(OBJEXT) +cli_LDADD = $(LDADD) +cli_DEPENDENCIES = $(top_builddir)/src/libedit.a am_testit_OBJECTS = testit.$(OBJEXT) testit_OBJECTS = $(am_testit_OBJECTS) testit_LDADD = $(LDADD) @@ -52,8 +56,8 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(testit_SOURCES) -DIST_SOURCES = $(testit_SOURCES) +SOURCES = cli.c $(testit_SOURCES) +DIST_SOURCES = cli.c $(testit_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -144,7 +148,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign LDADD = $(top_builddir)/src/libedit.a -AM_CFLAGS = -I$(top_srcdir)/src +AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include testit_SOURCES = testit.c all: all-am @@ -182,6 +186,9 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +cli$(EXEEXT): $(cli_OBJECTS) $(cli_DEPENDENCIES) + @rm -f cli$(EXEEXT) + $(LINK) $(cli_OBJECTS) $(cli_LDADD) $(LIBS) testit$(EXEEXT): $(testit_OBJECTS) $(testit_DEPENDENCIES) @rm -f testit$(EXEEXT) $(LINK) $(testit_OBJECTS) $(testit_LDADD) $(LIBS) @@ -192,6 +199,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testit.Po@am__quote@ .c.o: diff --git a/examples/cli.c b/examples/cli.c new file mode 100644 index 0000000..9566667 --- /dev/null +++ b/examples/cli.c @@ -0,0 +1,78 @@ +/* The "testit" micro shell, now with command completion. + * To be able to run, don't "--enable-default-complete". + */ +#include "editline.h" +#include + +char *list[] = { + "foo ", "bar ", "bsd ", "cli ", "ls ", "cd ", "malloc ", "tee ", NULL +}; + +/* +** Attempt to complete the pathname, returning an allocated copy. +** Fill in *unique if we completed it, or set it to 0 if ambiguous. +*/ +char *rl_complete(char *token, int *match) +{ + int i; + int index = -1; + int matchlen = 0; + int count = 0; + + for (i = 0; list[i]; i++) + { + int partlen = strlen (token); /* Part of token */ + + if (!strncmp (list[i], token, partlen)) + { + index = i; + matchlen = partlen; + count ++; + } + } + + if (count == 1) + { + *match = 1; + return strdup (list[index] + matchlen); + } + + return NULL; +} + +/* +** Return all possible completions. +*/ +int rl_list_possib(char *token, char ***av) +{ + int i, num, total = 0; + char **copy; + + for (num = 0; list[num]; num++) + ; + copy = (char **) malloc (num * sizeof(char *)); + for (i = 0; i < num; i++) + { + if (!strncmp (list[i], token, strlen (token))) + { + copy[total] = strdup (list[i]); + total ++; + } + } + *av = copy; + + return total; +} + +int main(int ac, char *av[]) +{ + char *line; + char *prompt = "cli> "; + + while ((line = readline(prompt)) != NULL) { + (void)printf("\t\t\t|%s|\n", line); + free(line); + } + + return 0; +} diff --git a/src/Makefile.am b/src/Makefile.am index f95fdff..f3a02ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,5 +2,8 @@ AUTOMAKE_OPTIONS = foreign lib_LIBRARIES = libedit.a -libedit_a_SOURCES = editline.c editline.h complete.c sysunix.c unix.h - +libedit_a_SOURCES = editline.c editline.h sysunix.c unix.h +if COMPLETE +# Built-in completion handler. +libedit_a_SOURCES += complete.c +endif diff --git a/src/Makefile.in b/src/Makefile.in index 2caa929..f4cf1b0 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -30,6 +30,8 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : +# Built-in completion handler. +@COMPLETE_TRUE@am__append_1 = complete.c subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -52,8 +54,11 @@ AR = ar ARFLAGS = cru libedit_a_AR = $(AR) $(ARFLAGS) libedit_a_LIBADD = -am_libedit_a_OBJECTS = editline.$(OBJEXT) complete.$(OBJEXT) \ - sysunix.$(OBJEXT) +am__libedit_a_SOURCES_DIST = editline.c editline.h sysunix.c unix.h \ + complete.c +@COMPLETE_TRUE@am__objects_1 = complete.$(OBJEXT) +am_libedit_a_OBJECTS = editline.$(OBJEXT) sysunix.$(OBJEXT) \ + $(am__objects_1) libedit_a_OBJECTS = $(am_libedit_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -63,7 +68,7 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libedit_a_SOURCES) -DIST_SOURCES = $(libedit_a_SOURCES) +DIST_SOURCES = $(am__libedit_a_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -154,7 +159,8 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign lib_LIBRARIES = libedit.a -libedit_a_SOURCES = editline.c editline.h complete.c sysunix.c unix.h +libedit_a_SOURCES = editline.c editline.h sysunix.c unix.h \ + $(am__append_1) all: all-am .SUFFIXES: