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