mirror of
https://github.com/zsh-users/zsh-history-substring-search
synced 2024-09-20 16:19:04 +02:00
feat: add fuzzy search
This commit is contained in:
parent
563c88c4ca
commit
fd27842cad
|
@ -117,6 +117,11 @@ default values only after having loaded this script into your ZSH session.
|
||||||
Flags" section in the zshexpn(1) man page to learn about the kinds of
|
Flags" section in the zshexpn(1) man page to learn about the kinds of
|
||||||
values you may assign to this variable.
|
values you may assign to this variable.
|
||||||
|
|
||||||
|
* `HISTORY_SUBSTRING_SEARCH_FUZZY` is a global variable that defines
|
||||||
|
how the command history will be searched for your query. If set to a non-empty
|
||||||
|
value, causes this script to perform a fuzzy search by words, matching in
|
||||||
|
given order e.g. `ab c` will match `*ab*c*`
|
||||||
|
|
||||||
* `HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE` is a global variable that defines
|
* `HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE` is a global variable that defines
|
||||||
whether all search results returned are _unique_. If set to a non-empty
|
whether all search results returned are _unique_. If set to a non-empty
|
||||||
value, then only unique search results are presented. This behaviour is off
|
value, then only unique search results are presented. This behaviour is off
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
# Copyright (c) 2011 Sorin Ionescu
|
# Copyright (c) 2011 Sorin Ionescu
|
||||||
# Copyright (c) 2011 Vincent Guerci
|
# Copyright (c) 2011 Vincent Guerci
|
||||||
# Copyright (c) 2016 Geza Lore
|
# Copyright (c) 2016 Geza Lore
|
||||||
|
# Copyright (c) 2017 Bengt Brodersen
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -51,6 +52,7 @@ typeset -g _history_substring_search_refresh_display
|
||||||
typeset -g _history_substring_search_query_highlight
|
typeset -g _history_substring_search_query_highlight
|
||||||
typeset -g _history_substring_search_result
|
typeset -g _history_substring_search_result
|
||||||
typeset -g _history_substring_search_query
|
typeset -g _history_substring_search_query
|
||||||
|
typeset -g -a _history_substring_search_query_parts
|
||||||
typeset -g -A _history_substring_search_raw_matches
|
typeset -g -A _history_substring_search_raw_matches
|
||||||
typeset -g -i _history_substring_search_raw_match_index
|
typeset -g -i _history_substring_search_raw_match_index
|
||||||
typeset -g -A _history_substring_search_matches
|
typeset -g -A _history_substring_search_matches
|
||||||
|
@ -65,6 +67,7 @@ typeset -g HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold'
|
||||||
typeset -g HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold'
|
typeset -g HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold'
|
||||||
typeset -g HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i'
|
typeset -g HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i'
|
||||||
typeset -g HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE=''
|
typeset -g HISTORY_SUBSTRING_SEARCH_ENSURE_UNIQUE=''
|
||||||
|
typeset -g HISTORY_SUBSTRING_SEARCH_FUZZY=''
|
||||||
typeset -g _history_substring_search_{refresh_display,query_highlight,result,query,match_index,raw_match_index}
|
typeset -g _history_substring_search_{refresh_display,query_highlight,result,query,match_index,raw_match_index}
|
||||||
typeset -ga _history_substring_search{,_raw}_matches
|
typeset -ga _history_substring_search{,_raw}_matches
|
||||||
|
|
||||||
|
@ -223,6 +226,7 @@ _history-substring-search-begin() {
|
||||||
# speed things up a little.
|
# speed things up a little.
|
||||||
#
|
#
|
||||||
_history_substring_search_query=
|
_history_substring_search_query=
|
||||||
|
_history_substring_search_query_parts=()
|
||||||
_history_substring_search_raw_matches=()
|
_history_substring_search_raw_matches=()
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -233,20 +237,31 @@ _history-substring-search-begin() {
|
||||||
_history_substring_search_query=$BUFFER
|
_history_substring_search_query=$BUFFER
|
||||||
|
|
||||||
#
|
#
|
||||||
# $BUFFER contains the text that is in the command-line currently.
|
# compose search pattern
|
||||||
# we put an extra "\\" before meta characters such as "\(" and "\)",
|
|
||||||
# so that they become "\\\(" and "\\\)".
|
|
||||||
#
|
#
|
||||||
local escaped_query=${BUFFER//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
|
if [[ -n $HISTORY_SUBSTRING_SEARCH_FUZZY ]]; then
|
||||||
|
#
|
||||||
|
# `=` split string in arguments
|
||||||
|
#
|
||||||
|
_history_substring_search_query_parts=(${=_history_substring_search_query})
|
||||||
|
else
|
||||||
|
_history_substring_search_query_parts=(${_history_substring_search_query})
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Find all occurrences of the search query in the history file.
|
# 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}*"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Find all occurrences of the search pattern in the history file.
|
||||||
#
|
#
|
||||||
# (k) returns the "keys" (history index numbers) instead of the values
|
# (k) returns the "keys" (history index numbers) instead of the values
|
||||||
# (R) returns values in reverse older, so the index of the youngest
|
# (R) returns values in reverse older, so the index of the youngest
|
||||||
# matching history entry is at the head of the list.
|
# matching history entry is at the head of the list.
|
||||||
#
|
#
|
||||||
_history_substring_search_raw_matches=(${(k)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)*${escaped_query}*]})
|
_history_substring_search_raw_matches=(${(k)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${search_pattern}]})
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -309,16 +324,20 @@ _history-substring-search-end() {
|
||||||
_zsh_highlight
|
_zsh_highlight
|
||||||
|
|
||||||
# highlight the search query inside the command line
|
# highlight the search query inside the command line
|
||||||
if [[ -n $_history_substring_search_query_highlight && -n $_history_substring_search_query ]]; then
|
if [[ -n $_history_substring_search_query_highlight ]]; then
|
||||||
#
|
# highlight first matching query parts
|
||||||
# The following expression yields a variable $MBEGIN, which
|
local highlight_start_index=0
|
||||||
# indicates the begin position + 1 of the first occurrence
|
local highlight_end_index=0
|
||||||
# of _history_substring_search_query in $BUFFER.
|
for query_part in $_history_substring_search_query_parts; do
|
||||||
#
|
local escaped_query_part=${query_part//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
|
||||||
: ${(S)BUFFER##(#m$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)($_history_substring_search_query##)}
|
# (i) get index of pattern
|
||||||
local begin=$(( MBEGIN - 1 ))
|
local query_part_match_index=${${BUFFER:$highlight_start_index}[(i)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)${escaped_query_part}]}
|
||||||
local end=$(( begin + $#_history_substring_search_query ))
|
if [[ $query_part_match_index -le ${#BUFFER:$highlight_start_index} ]]; then
|
||||||
region_highlight+=("$begin $end $_history_substring_search_query_highlight")
|
highlight_start_index=$(( $highlight_start_index + $query_part_match_index ))
|
||||||
|
highlight_end_index=$(( $highlight_start_index + ${#query_part} ))
|
||||||
|
region_highlight+=("$(($highlight_start_index - 1)) $(($highlight_end_index - 1)) $_history_substring_search_query_highlight")
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For debugging purposes:
|
# For debugging purposes:
|
||||||
|
|
Loading…
Reference in a new issue