Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,27 @@ default values.
* `HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_TIMEOUT` is a global variable that
defines a timeout in seconds for clearing the search highlight.

* `HISTORY_SUBSTRING_SEARCH_MATCH_FUNCTION` is a global variable that defines
the name of a function for getting matches from custom history providers.

For example, to integrate with [`histdb`](https://github.com/larkery/zsh-histdb)
the following function could be used:

```bash
function _history-substring-get-raw-matches-histdb {
local SEP=$(printf $'\1') # column separator
local results=$(
histdb --sep ${SEP} ${_history_substring_search_query_parts[@]} |
tail -n +2 | # kill header
sed 's/\(.\+\)[^\x01]\x01/&\x00/' | # add \0 to separate records
cut -d ${SEP} -f 4 # get the command column
)
_history_substring_search_raw_matches=(${(ps:\0:)results})
_history_substring_search_raw_matches=(${_history_substring_search_raw_matches[@]%$'\n'})
}

HISTORY_SUBSTRING_SEARCH_MATCH_FUNCTION="_history-substring-get-raw-matches-histdb"
```

History
------------------------------------------------------------------------------
Expand Down
55 changes: 33 additions & 22 deletions zsh-history-substring-search.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
: ${HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE=''}
: ${HISTORY_SUBSTRING_SEARCH_FUZZY=''}
: ${HISTORY_SUBSTRING_SEARCH_PREFIXED=''}
: ${HISTORY_SUBSTRING_SEARCH_MATCH_FUNCTION=''}

#-----------------------------------------------------------------------------
# declare internal global variables
Expand Down Expand Up @@ -245,6 +246,30 @@ if [[ $+functions[_zsh_highlight] -eq 0 ]]; then
unfunction _history-substring-search-function-callable
fi

_history-substring-get-raw-matches() {
#
# Escape and join query parts with wildcard character '*' as separator
# `(j:CHAR:)` join array to string with CHAR as separator
#
local search_pattern="${(j:*:)_history_substring_search_query_parts[@]//(#m)[\][()|\\*?#<>~^]/\\$MATCH}*"

#
# Support anchoring history search to the beginning of the command
#
if [[ -z $HISTORY_SUBSTRING_SEARCH_PREFIXED ]]; then
search_pattern="*${search_pattern}"
fi

#
# Find all occurrences of the search pattern in the history file.
#
# (k) returns the "keys" (history index numbers) instead of the values
# (R) returns values in reverse older, so the index of the youngest
# matching history entry is at the head of the list.
#
_history_substring_search_raw_matches=(${(k)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${search_pattern}]})
}

_history-substring-search-begin() {
setopt localoptions extendedglob

Expand Down Expand Up @@ -294,27 +319,7 @@ _history-substring-search-begin() {
_history_substring_search_query_parts=(${==_history_substring_search_query})
fi

#
# Escape and join query parts with wildcard character '*' as seperator
# `(j:CHAR:)` join array to string with CHAR as seperator
#
local search_pattern="${(j:*:)_history_substring_search_query_parts[@]//(#m)[\][()|\\*?#<>~^]/\\$MATCH}*"

#
# Support anchoring history search to the beginning of the command
#
if [[ -z $HISTORY_SUBSTRING_SEARCH_PREFIXED ]]; then
search_pattern="*${search_pattern}"
fi

#
# Find all occurrences of the search pattern in the history file.
#
# (k) returns the "keys" (history index numbers) instead of the values
# (R) returns values in reverse older, so the index of the youngest
# matching history entry is at the head of the list.
#
_history_substring_search_raw_matches=(${(k)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${search_pattern}]})
${HISTORY_SUBSTRING_SEARCH_MATCH_FUNCTION:-_history-substring-get-raw-matches}
fi

#
Expand Down Expand Up @@ -655,7 +660,13 @@ _history-substring-search-found() {
# 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
# to highlight the current buffer.
#
BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]]
if [[ -n $HISTORY_SUBSTRING_SEARCH_MATCH_FUNCTION ]]; then
# Custom provider functions provide entries directly
BUFFER=$_history_substring_search_matches[$_history_substring_search_match_index]
else
# Builtin search provides the index to matching history entries
BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]]
fi
_history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
}

Expand Down