Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: set history line in zle



I'm still thinking about incremental search, but as I was looking at
the code yesterday I noted the aribtrary restriction that you can't set
the history line (HISTNO).  There's already code to do this for
searches.  Allowing this makes ordinary searches easier in shell
functions with $history, which uses history line numbers as keys.

I've supplied an example widget history-pattern-search.

One other chunk makes freeing the isearch history more consistent.
Currently it doesn't matter since it's only done when zle is unloaded,
but doing it instead when zleread() returns might be sensible.  I
haven't changed anything other than the free code itself yet.

Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.35
diff -u -r1.35 contrib.yo
--- Doc/Zsh/contrib.yo	26 Jul 2004 16:59:55 -0000	1.35
+++ Doc/Zsh/contrib.yo	29 Jul 2004 13:09:09 -0000
@@ -591,6 +591,25 @@
 bindkey '\e^P' history-beginning-search-backward-end
 bindkey '\e^N' history-beginning-search-forward-end)
 )
+tindex(history-pattern-search)
+tindex(history-pattern-search-backward)
+tindex(history-pattern-search-forward)
+item(tt(history-pattern-search))(
+The function tt(history-pattern-search) implements widgets which prompt
+for a pattern with which to search the history backwards or forwards.  The
+pattern is in the usual zsh format, however the first character may be
+tt(^) to anchor the search to the start of the line, and the last character
+may be tt($) to anchor the search to the end of the line.  If the
+search was not anchored to the end of the line the cursor is positioned
+just after the pattern found.
+
+The commands to create bindable widgets are similar to those in the
+example immediately above:
+
+example(autoload -U history-pattern-search
+zle -N history-pattern-search-backward history-pattern-search
+zle -N history-pattern-search-forward history-pattern-search)
+)
 tindex(up-line-or-beginning-search)
 tindex(down-line-or-beginning-search)
 item(tt(up-line-or-beginning-search), tt(down-line-or-beginning-search))(
Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.38
diff -u -r1.38 zle.yo
--- Doc/Zsh/zle.yo	11 Jul 2004 22:53:03 -0000	1.38
+++ Doc/Zsh/zle.yo	29 Jul 2004 13:09:11 -0000
@@ -634,7 +634,10 @@
 )
 vindex(HISTNO)
 item(tt(HISTNO) (integer))(
-The current history number; read-only.
+The current history number.  Setting this has the same effect as
+moving up or down in the history to the corresponding history line.
+An attempt to set it is ignored if the line is not stored in the
+history.
 )
 vindex(KEYMAP)
 item(tt(KEYMAP) (scalar))(
Index: Functions/Zle/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/.distfiles,v
retrieving revision 1.13
diff -u -r1.13 .distfiles
--- Functions/Zle/.distfiles	26 Jun 2004 17:54:32 -0000	1.13
+++ Functions/Zle/.distfiles	29 Jul 2004 13:09:11 -0000
@@ -13,5 +13,5 @@
 match-words-by-style select-word-style transpose-words-match
 up-case-word-match
 delete-whole-word-match quote-and-complete-word url-quote-magic
-zed-set-file-name
+zed-set-file-name history-pattern-search
 '
Index: Functions/Zle/history-pattern-search
===================================================================
RCS file: Functions/Zle/history-pattern-search
diff -N Functions/Zle/history-pattern-search
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Functions/Zle/history-pattern-search	29 Jul 2004 13:09:11 -0000
@@ -0,0 +1,81 @@
+# Prompt for an search in the history for a pattern.
+# Patterns to search are standard zsh patterns, but may include
+# ^ at the start or $ at the end to anchor the pattern to the
+# start or end of the history entry respectively.
+#
+# To search backwards, create a widget history-pattern-search-backward:
+#   zle -N history-pattern-search-backward history-pattern-search
+# and to search forwards, create history-pattern-search-forward
+#   zle -N history-pattern-search-forward history-pattern-search
+
+# Use extended globbing by default.
+emulate -L zsh
+setopt extendedglob
+
+# Load required features.
+autoload -U read-from-minibuffer
+zmodload -i zsh/parameter
+
+local REPLY dir new
+integer i
+local -a found match mbegin mend
+
+# Decide if we are searching backwards or forwards.
+if [[ $WIDGET = *forward* ]]; then
+  dir="forw"
+else
+  dir="rev"
+fi
+
+# Read pattern.  Prompt could be made customisable.
+read-from-minibuffer "pat ($dir): "
+
+# Abort if bad status or nothing entered
+[[ $? -ne 0 || -z $REPLY ]] && return 0
+
+# Handle start-of-line anchor.
+if [[ $REPLY = \^* ]]; then
+  REPLY=$REPLY[2,-1]
+else
+  REPLY="*$REPLY"
+fi
+
+# Handle end-of-line anchor.
+if [[ $REPLY = *\$ ]]; then
+  REPLY=$REPLY[1,-2]
+else
+  REPLY="$REPLY*"
+fi
+
+# Search history for pattern.
+# As $history is an associative array we can get all matches.
+found=(${(kon)history[(R)$REPLY]})
+
+if [[ $dir = forw ]]; then
+  # Searching forward.  Look back through matches until we
+  # get back to the current history number.
+  for (( i = ${#found}; i >= 1; i-- )); do
+    (( $found[$i] <= HISTNO )) && break
+    new=$found[$i]
+  done
+else
+  # Searching backward.  Look forward through matches until we
+  # reach the current history number.
+  for (( i = 1; i <= ${#found}; i++ )); do
+    (( $found[$i] >= HISTNO )) && break
+    new=$found[$i]
+  done
+fi
+
+if [[ -n $new ]]; then
+  # Match found.  Move to line.
+  HISTNO=$new
+  if [[ $REPLY = *\* && $history[$new] = (#b)(${~REPLY[1,-2]})* ]]; then
+    # If not anchored to the end, move to the end of the pattern
+    # we were searching for.
+    CURSOR=$mend[1]
+  fi
+  return 0
+else
+  return 1
+fi
Index: Src/Zle/zle_hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_hist.c,v
retrieving revision 1.13
diff -u -r1.13 zle_hist.c
--- Src/Zle/zle_hist.c	2 Jun 2004 22:15:01 -0000	1.13
+++ Src/Zle/zle_hist.c	29 Jul 2004 13:09:11 -0000
@@ -715,6 +715,8 @@
 free_isrch_spots(void)
 {
     zfree(isrch_spots, max_spot * sizeof(*isrch_spots));
+    max_spot = 0;
+    isrch_spots = NULL;
 }
 
 /**/
Index: Src/Zle/zle_params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v
retrieving revision 1.15
diff -u -r1.15 zle_params.c
--- Src/Zle/zle_params.c	2 Jun 2004 22:15:02 -0000	1.15
+++ Src/Zle/zle_params.c	29 Jul 2004 13:09:11 -0000
@@ -75,7 +75,7 @@
         zleunsetfn, NULL },
     { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric),
         unset_numeric, NULL },
-    { "HISTNO", PM_INTEGER | PM_READONLY, NULL, FN(get_histno),
+    { "HISTNO", PM_INTEGER, FN(set_histno), FN(get_histno),
         zleunsetfn, NULL },
     { "BUFFERLINES", PM_INTEGER | PM_READONLY, NULL, FN(get_bufferlines),
         zleunsetfn, NULL },
@@ -326,6 +326,17 @@
 }
 
 /**/
+static void
+set_histno(UNUSED(Param pm), zlong x)
+{
+    Histent he;
+
+    if (!(he = quietgethist((int)x)))
+	return;
+    zle_setline(he);
+}
+
+/**/
 static zlong
 get_histno(UNUSED(Param pm))
 {

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************



Messages sorted by: Reverse Date, Date, Thread, Author