On Thu, 30 Nov 2006, Otto Moerbeek wrote: > On Thu, 30 Nov 2006, Alexander Farber wrote: > > > Hello, > > > > I'm trying to switch to ksh as my login shell. > > > > It seems to me, that the vi mode is more capable > > than emacs-mode in ksh and so I've switched to it > > ("set -o vi" in my ~/.kshrc) and I do know that I can hit ESC, > > then / and type a part of my command to search for it. > > > > However I just can't find (yes, I've read "man ksh") > > a way for searching for a partially typed command. > > > > In tcsh I was typing "ll /var/w" and then ESC-p(revious) > > and ESC-n(ext) to search for the matching commands. > > > > I also was having: > > > > bindkey -k up history-search-backward > > bindkey -k down history-search-forward > > > > for mapping the same functions to the arrow keys > > but that's probably to much to ask for... > > > > So what do you do in ksh, when you start to > > type a command and then realize, that it must > > be somewhere there in the history already? > > > > Thank you > > Alex > > There was a diff posted to tech@ for that... > > I never took time to review and test it,...
I turns out the diff has whitespace problems. I would be nice if sombody could clean it up. I don't have time right now. > > -Otto > > > >From [EMAIL PROTECTED] Wed Mar 22 16:06:56 2006 > Date: Wed, 22 Mar 2006 14:32:06 +0100 > From: Martin Hedenfalk <[EMAIL PROTECTED]> > To: [EMAIL PROTECTED] > Subject: Patch to ksh adding history-search-backward/forward > > Here is a patch adding a history-search-backward and -forward function to > ksh that many bash-users might be accustomed to. It's an implicitly anchored > version of "search-history" using the prefix of the current line up to the > cursor as search pattern, discarding duplicate matches. Can be bound to > up/down arrow. > > The patch is also available at http://hedenfalk.se/patches/ksh-history.patch > in case it gets messed up in the mail. > > I've been using this patch for a week now. It seems to be stable. > > /Martin > > Index: emacs.c > =================================================================== > RCS file: /cvs/src/bin/ksh/emacs.c,v > retrieving revision 1.39 > diff -u -d -r1.39 emacs.c > --- emacs.c 26 Sep 2005 19:25:22 -0000 1.39 > +++ emacs.c 16 Mar 2006 07:10:31 -0000 > @@ -106,6 +106,7 @@ > static int x_curprefix; > static char *macroptr; > static int prompt_skip; > +static char x_search_hist_pattern [256+1]; > > static int x_ins(char *); > static void x_delete(int, int); > @@ -119,6 +120,8 @@ > static void x_zotc(int); > static void x_load_hist(char **); > static int x_search(char *, int, int); > +static int x_search_delta(char *, int, int, int); > +static int x_search_delta_distinct(char *, int, int, int); > static int x_match(char *, char *); > static void x_redraw(int); > static void x_push(int); > @@ -190,6 +193,8 @@ > { x_search_char_forw, "search-character-forward", XF_ARG }, > { x_search_char_back, "search-character-backward", XF_ARG }, > { x_search_hist, "search-history", 0 }, > + { x_search_hist_backward, "history-search-backward", 0 }, > + { x_search_hist_forward, "history-search-forward", 0 }, > { x_set_mark, "set-mark-command", 0 }, > { x_stuff, "stuff", 0 }, > { x_stuffreset, "stuff-reset", 0 }, > @@ -860,9 +865,7 @@ > if ((c = x_e_getc()) < 0) > return KSTD; > f = x_tab[0][c&CHARMASK]; > - if (c == CTRL('[')) > - break; > - else if (f == XFUNC_search_hist) > + if (f == XFUNC_search_hist) > offset = x_search(pat, 0, offset); > else if (f == XFUNC_del_back) { > if (p == pat) { > @@ -904,14 +907,90 @@ > return KSTD; > } > > -/* search backward from current line */ > +/* determine if prefix history searching should be performed, or plain > + * up/down history traversing */ > static int > -x_search(char *pat, int sameline, int offset) > +x_search_hist_has_prefix(void) > +{ > + size_t pat_len; > + > + /* skip prefix history search if at beginning of line */ > + if (xcp == xbuf) > + return 0; > + > + /* prepare the prefix search pattern */ > + pat_len = xcp - xbuf; > + x_search_hist_pattern[0] = '^'; > + if (pat_len > 256) > + pat_len = 256; > + strlcpy(x_search_hist_pattern + 1, xbuf, pat_len + 1); > + return 1; > +} > + > +/* a modal version of (up|down)-history, necessary in order not to > + * confuse with prefix history searches */ > +static void > +x_search_hist_modal(int delta) > +{ > + int c; > + u_char f; > + > + x_load_hist(x_histp + delta); > + > + while(1) { > + x_flush(); > + if ((c = x_e_getc()) < 0) > + break; > + f = x_tab[x_curprefix][c&CHARMASK]; > + if (f == XFUNC_search_hist_backward) { > + x_load_hist(x_histp - 1); > + x_curprefix = 0; > + } else if (f == XFUNC_search_hist_forward) { > + x_load_hist(x_histp + 1); > + x_curprefix = 0; > + } else if (f == XFUNC_meta1) > + x_meta1(0); > + else if (f == XFUNC_meta2) > + x_meta2(0); > + else { > + x_e_ungetc(c); > + break; > + } > + } > +} > + > +/* search history backwards for line with same prefix */ > +static int > +x_search_hist_backward(int c) > +{ > + if (x_search_hist_has_prefix()) > + x_search_delta_distinct(x_search_hist_pattern, 0, 0, -1); > + else > + x_search_hist_modal(-1); > + return KSTD; > +} > + > +/* search history forwards for line with same prefix */ > +static int > +x_search_hist_forward(int c) > +{ > + if (x_search_hist_has_prefix()) > + x_search_delta_distinct(x_search_hist_pattern, 0, 0, +1); > + else > + x_search_hist_modal(+1); > + return KSTD; > +} > + > +/* search backward or forward from current line depending on delta */ > +static int > +x_search_delta(char *pat, int sameline, int offset, int delta) > { > char **hp; > int i; > > - for (hp = x_histp - (sameline ? 0 : 1) ; hp >= history; --hp) { > + for (hp = x_histp + (sameline ? 0 : delta) ; > + hp >= history && hp <= histptr ; > + hp += delta) { > i = x_match(*hp, pat); > if (i >= 0) { > if (offset < 0) > @@ -924,6 +1003,31 @@ > x_e_putc(BEL); > x_histp = histptr; > return -1; > +} > + > +/* just as x_search_delta, but skips duplicate matches */ > +static int > +x_search_delta_distinct(char *pat, int sameline, int offset, int delta) > +{ > + char *orig_xbuf; > + int rc; > + > + orig_xbuf = strdup(xbuf); > + > + while(1) { > + rc = x_search_delta(pat, sameline, offset, delta); > + if(rc < 0 || strcmp(orig_xbuf, *x_histp) != 0) > + break; > + } > + free(orig_xbuf); > + return rc; > +} > + > +/* search backward from current line */ > +static int > +x_search(char *pat, int sameline, int offset) > +{ > + return x_search_delta(pat, sameline, offset, -1); > } > > /* return position of first match of pattern in string, else -1 */ > Index: ksh.1 > =================================================================== > RCS file: /cvs/src/bin/ksh/ksh.1,v > retrieving revision 1.110 > diff -u -d -r1.110 ksh.1 > --- ksh.1 7 Mar 2006 09:31:02 -0000 1.110 > +++ ksh.1 16 Mar 2006 07:10:31 -0000 > @@ -4837,6 +4837,14 @@ > .Xc > Goes to history number > .Ar n . > +.It history-search-backward: > +Search the internal history list backwards for a line beginning with the > +current content of the input buffer up to the cursor. Duplicate matches > +are skipped. > +.It history-search-forward: > +Search the internal history list forwards for a line beginning with the > +current content of the input buffer up to the cursor. Duplicate matches > +are skipped. > .It kill-line: KILL > Deletes the entire input line. > .It kill-region: ^W