Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match multiple previous commands & more configuration #621

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ For more info, read the Character Highlighting section of the zsh manual: `man z

For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.

#### When `ZSH_AUTOSUGGEST_STRATEGY` contains `match_prev_cmd`:

- `ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS`: The previous commands are only looked at of a number of the most recent commands that match the current prefix. This sets the maximum number of commands to consider. Set it to -1 to always use all matches.
- `ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS`: Number of previous commands that should match. Setting this to a value below 1 results in the strategy `history` to be simulated (with extra steps).

### Widget Mapping

Expand Down
9 changes: 9 additions & 0 deletions src/config.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
ZSH_AUTOSUGGEST_STRATEGY=(history)
}

# Maximum number of commands to consider for match_prev_cmd strategy
# Set to -1 to always use all matches
(( ! ${+ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS} )) &&
typeset -g ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS=200

# Number of previous commands that should match.
(( ! ${+ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS} )) &&
typeset -g ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS=1

# Widgets that clear the suggestion
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
Expand Down
36 changes: 26 additions & 10 deletions src/strategies/match_prev_cmd.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
#--------------------------------------------------------------------#
# Match Previous Command Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix and whose preceding history item also matches the most
# recently executed command.
# Suggests the most recent history item that all_match the given
# prefix and whose preceding history items also all_match the most
# recently executed commands.
#
# For example, suppose your history has the following entries:
# - pwd
Expand All @@ -16,6 +16,9 @@
# will be 'ls foo' rather than 'ls bar' because your most recently
# executed command (pwd) was previously followed by 'ls foo'.
#
# You can customize how many commands have to match by setting
# `ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS`.
#
# Note that this strategy won't work as expected with ZSH options that don't
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
# `HIST_EXPIRE_DUPS_FIRST`.
Expand Down Expand Up @@ -45,17 +48,30 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
# By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}"

# Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Get the previously executed commands
local -a prev_cmds
local i
for ((i = 1; i <= $ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS; i++)); do
prev_cmds+="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-i))]}")"
done

# Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do
# Iterate over the most recent history event numbers that match $prefix.
local key all_match
for key in "${(@)history_match_keys[1,$ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS]}"; do
# Stop if we ran out of history
[[ $key -gt 1 ]] || break

# See if the history entry preceding the suggestion matches the
# previous command, and use it if it does
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
# See if the history entries preceding the suggestion match the previous
# commands, and use it if they do
all_match=1
for ((i = 1; i <= $ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS; i++)); do
if [[ "${history[$((key - i))]}" != "$prev_cmds[i]" ]]; then
all_match=0
break
fi
done

if (( all_match )); then
histkey="$key"
break
fi
Expand Down
45 changes: 35 additions & 10 deletions zsh-autosuggestions.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
ZSH_AUTOSUGGEST_STRATEGY=(history)
}

# Maximum number of commands to consider for match_prev_cmd strategy
# Set to -1 to always use all matches
(( ! ${+ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS} )) &&
typeset -g ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS=200

# Number of previous commands that should match.
(( ! ${+ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS} )) &&
typeset -g ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS=1

# Widgets that clear the suggestion
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
Expand Down Expand Up @@ -664,9 +673,9 @@ _zsh_autosuggest_strategy_history() {
#--------------------------------------------------------------------#
# Match Previous Command Suggestion Strategy #
#--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given
# prefix and whose preceding history item also matches the most
# recently executed command.
# Suggests the most recent history item that all_match the given
# prefix and whose preceding history items also all_match the most
# recently executed commands.
#
# For example, suppose your history has the following entries:
# - pwd
Expand All @@ -678,6 +687,9 @@ _zsh_autosuggest_strategy_history() {
# will be 'ls foo' rather than 'ls bar' because your most recently
# executed command (pwd) was previously followed by 'ls foo'.
#
# You can customize how many commands have to match by setting
# `ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS`.
#
# Note that this strategy won't work as expected with ZSH options that don't
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
# `HIST_EXPIRE_DUPS_FIRST`.
Expand Down Expand Up @@ -707,17 +719,30 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
# By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}"

# Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Get the previously executed commands
local -a prev_cmds
local i
for ((i = 1; i <= $ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS; i++)); do
prev_cmds+="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-i))]}")"
done

# Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do
# Iterate over the most recent history event numbers that match $prefix.
local key all_match
for key in "${(@)history_match_keys[1,$ZSH_AUTOSUGGEST_MATCH_PREV_MAX_CMDS]}"; do
# Stop if we ran out of history
[[ $key -gt 1 ]] || break

# See if the history entry preceding the suggestion matches the
# previous command, and use it if it does
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
# See if the history entries preceding the suggestion match the previous
# commands, and use it if they do
all_match=1
for ((i = 1; i <= $ZSH_AUTOSUGGEST_MATCH_NUM_PREV_CMDS; i++)); do
if [[ "${history[$((key - i))]}" != "$prev_cmds[i]" ]]; then
all_match=0
break
fi
done

if (( all_match )); then
histkey="$key"
break
fi
Expand Down