Index: bin/sh/eval.h =================================================================== --- bin/sh/eval.h +++ bin/sh/eval.h @@ -52,6 +52,7 @@ #define EV_EXIT 01 /* exit after evaluating tree */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #define EV_BACKCMD 04 /* command executing within back quotes */ +#define EV_INTER 010 /* interactive, prompt */ void evalstring(const char *, int); union node; /* BLETCH for ansi C */ Index: bin/sh/eval.c =================================================================== --- bin/sh/eval.c +++ bin/sh/eval.c @@ -152,15 +152,16 @@ { union node *n; struct stackmark smark; - int flags_exit; + int flags_exit, inter; int any; flags_exit = flags & EV_EXIT; + inter = (flags & EV_INTER) != 0; flags &= ~EV_EXIT; any = 0; setstackmark(&smark); setinputstring(s, 1); - while ((n = parsecmd(0)) != NEOF) { + while ((n = parsecmd(inter)) != NEOF) { if (n != NULL && !nflag) { if (flags_exit && preadateof()) evaltree(n, flags | EV_EXIT); Index: bin/sh/histedit.c =================================================================== --- bin/sh/histedit.c +++ bin/sh/histedit.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -80,6 +81,7 @@ static int comparator(const void *, const void *, void *); static char **sh_matches(const char *, int, int); static unsigned char sh_complete(EditLine *, int); +static unsigned char fcempty(EditLine *, int); static const char * get_histfile(void) @@ -191,6 +193,10 @@ el_set(el, EL_ADDFN, "sh-complete", "Filename completion", sh_complete); + el_set(el, EL_ADDFN, + "edit-and-execute-command", + "Use $EDITOR to provide a command", + fcempty); } else { bad: out2fmt_flush("sh: can't initialize editing\n"); @@ -208,6 +214,8 @@ else if (Eflag) { el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_BIND, "^R", "em-inc-search-prev", NULL); + el_set(el, EL_BIND, "^X^E", + "edit-and-execute-command", NULL); } el_set(el, EL_BIND, "^I", "sh-complete", NULL); el_source(el, NULL); @@ -251,14 +259,13 @@ } int -histcmd(int argc, char **argv __unused) +histcmd(int argc __unused, char **argv __unused) { int ch; const char *editor = NULL; HistEvent he; int lflg = 0, nflg = 0, rflg = 0, sflg = 0; int i, retval; - const char *firststr, *laststr; int first, last, direction; char *pat = NULL, *repl = NULL; static int active = 0; @@ -269,12 +276,6 @@ FILE *efp = NULL; int oldhistnum; - if (hist == NULL) - error("history not active"); - - if (argc == 1) - error("missing history argument"); - while (not_fcnumber(*argptr) && (ch = nextopt("e:lnrs")) != '\0') switch ((char)ch) { case 'e': @@ -346,21 +347,15 @@ * determine [first] and [last] */ if (*argptr == NULL) { - firststr = lflg ? "-16" : "-1"; - laststr = "-1"; + /* not used */ } else if (argptr[1] == NULL) { - firststr = argptr[0]; - laststr = lflg ? "-1" : argptr[0]; + first = str_to_event(argptr[0], 0); + last = str_to_event(lflg ? "-1" : argptr[0], 1); } else if (argptr[2] == NULL) { - firststr = argptr[0]; - laststr = argptr[1]; + first = str_to_event(argptr[0], 0); + last = str_to_event(argptr[1], 1); } else error("too many arguments"); - /* - * Turn into event numbers. - */ - first = str_to_event(firststr, 0); - last = str_to_event(laststr, 1); if (rflg) { i = last; @@ -390,6 +385,8 @@ } } + if (*argptr == NULL || hist == NULL) + goto empty; /* * Loop through selected history events. If listing or executing, * do it now. Otherwise, put into temp file and call the editor @@ -440,15 +437,24 @@ if (he.num == last) break; } + +empty: if (editor) { char *editcmd; + void *m = mmap(NULL, 1024, PROT_READ, MAP_SHARED, fileno(efp), 0); fclose(efp); - INTON; editcmd = stalloc(strlen(editor) + strlen(editfile) + 2); sprintf(editcmd, "%s %s", editor, editfile); evalstring(editcmd, 0); /* XXX - should use no JC command */ - readcmdfile(editfile); /* XXX - should read back - quick tst */ + out2str(m); + flushout(out2); + evalstring(m, EV_INTER); + if (hist) + history(hist, &he, H_ENTER, m); + munmap(m, 1024); + fclose(efp); + INTON; unlink(editfile); } @@ -709,6 +715,19 @@ NULL, &((int) {0}), NULL, NULL, FN_QUOTE_MATCH); } +unsigned char +fcempty(EditLine *sel __unused, int ch __unused) +{ + char *args[] = {(char[]){"fc"}, NULL}; + + argptr = args + 1; + out2c('\n'); + histcmd(1, args); + out2str(getprompt(NULL)); + flushout(out2); + return (0); +} + #else #include "error.h"