about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Doc/Zsh/contrib.yo19
-rw-r--r--Doc/Zsh/zle.yo5
-rw-r--r--Functions/Zle/.distfiles2
-rw-r--r--Functions/Zle/history-pattern-search81
-rw-r--r--Src/Zle/zle_hist.c2
-rw-r--r--Src/Zle/zle_params.c13
7 files changed, 124 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index b9dfe083c..26fa66509 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2004-07-29  Peter Stephenson  <pws@csr.com>
 
+	* 20219: Doc/Zsh/contrib.yo, Doc/Zsh/zle.yo,
+	Functions/Zle/.distfiles, Functions/Zle/history-pattern-search,
+	Src/Zle/zle_hist.c, Src/Zle/zle_params.c: make zle parameter
+	HISTNO writeable, add history-pattern-search sample to use it.
+
 	* 20208: Src/prompt.c, Doc/Zsh/prompt.yo: ternary code character C
 	etc. treat / as path with zero elements.
 
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index d205cce93..71867be2e 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -591,6 +591,25 @@ zle -N history-beginning-search-forward-end \
 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))(
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index f2067d14f..fe6ef04a6 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -634,7 +634,10 @@ string which the next yank would insert in the line.
 )
 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))(
diff --git a/Functions/Zle/.distfiles b/Functions/Zle/.distfiles
index 4b2da07a1..b00da2f41 100644
--- a/Functions/Zle/.distfiles
+++ b/Functions/Zle/.distfiles
@@ -13,5 +13,5 @@ down-case-word-match forward-word-match kill-word-match
 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
 '
diff --git a/Functions/Zle/history-pattern-search b/Functions/Zle/history-pattern-search
new file mode 100644
index 000000000..02f85a2fb
--- /dev/null
+++ b/Functions/Zle/history-pattern-search
@@ -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
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index 70d8699c0..c6fb7acdb 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -715,6 +715,8 @@ void
 free_isrch_spots(void)
 {
     zfree(isrch_spots, max_spot * sizeof(*isrch_spots));
+    max_spot = 0;
+    isrch_spots = NULL;
 }
 
 /**/
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index f2eaea723..f0f1cde95 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -75,7 +75,7 @@ static struct zleparam {
         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 @@ unset_numeric(Param pm, int exp)
 }
 
 /**/
+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))
 {