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,...

        -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

Reply via email to