Discussion:
Patch to ksh adding history-search-backward/forward
Martin Hedenfalk
2006-03-22 13:32:06 UTC
Permalink
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
Martin Hedenfalk
2006-09-01 07:57:28 UTC
Permalink
Sorry for bumping and replying to myself, but I'd like to know what I
did wrong with this patch. Was the feature just not wanted, was it a
bad patch or was there some other reason it was so totally ignored?

An updated patch against -current is available at
http://bzero.se/patches/ksh-history.patch.
Any comment?

/Martin
Post by Martin Hedenfalk
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 .
+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.
+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
Otto Moerbeek
2006-09-01 09:09:51 UTC
Permalink
Post by Martin Hedenfalk
Sorry for bumping and replying to myself, but I'd like to know what I
did wrong with this patch. Was the feature just not wanted, was it a
bad patch or was there some other reason it was so totally ignored?
Nobody found the feauture interesting enough, it seems.

-Otto
Post by Martin Hedenfalk
An updated patch against -current is available at
http://bzero.se/patches/ksh-history.patch.
Any comment?
/Martin
Post by Martin Hedenfalk
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 .
+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.
+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
Marco Peereboom
2006-09-01 13:26:58 UTC
Permalink
I actually think this might be useful. The one thing that irritates me about
ksh is that when you use persistent history the search in history is for
everything that user has typed instead of what was typed on the current
terminal followed by the complete history (hope that sentence makes sense).

Removing dups from searches is also very nice.

FWIW,
/marco
Post by Otto Moerbeek
Post by Martin Hedenfalk
Sorry for bumping and replying to myself, but I'd like to know what I
did wrong with this patch. Was the feature just not wanted, was it a
bad patch or was there some other reason it was so totally ignored?
Nobody found the feauture interesting enough, it seems.
-Otto
Post by Martin Hedenfalk
An updated patch against -current is available at
http://bzero.se/patches/ksh-history.patch.
Any comment?
/Martin
Post by Martin Hedenfalk
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 .
+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.
+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
Martin Hedenfalk
2006-09-02 13:19:14 UTC
Permalink
Post by Marco Peereboom
I actually think this might be useful. The one thing that irritates me about
ksh is that when you use persistent history the search in history is for
everything that user has typed instead of what was typed on the current
terminal followed by the complete history (hope that sentence makes sense).
Eh... not sure I'm following you there. All I want to do is start
typing a command, remembering I've done it before, then press up arrow
(or meta-p) and have it recalled from history.

/martin
Post by Marco Peereboom
Removing dups from searches is also very nice.
FWIW,
/marco
Post by Otto Moerbeek
Post by Martin Hedenfalk
Sorry for bumping and replying to myself, but I'd like to know what I
did wrong with this patch. Was the feature just not wanted, was it a
bad patch or was there some other reason it was so totally ignored?
Nobody found the feauture interesting enough, it seems.
-Otto
Post by Martin Hedenfalk
An updated patch against -current is available at
http://bzero.se/patches/ksh-history.patch.
Any comment?
/Martin
Post by Martin Hedenfalk
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
Loading...