diff options
author | Vikas Kushwaha <dev@vikas.rocks> | 2025-01-24 10:35:59 +0530 |
---|---|---|
committer | Vikas Kushwaha <dev@vikas.rocks> | 2025-01-24 10:35:59 +0530 |
commit | 18507fd21b7a7709133d8f3049c683e1abffcda2 (patch) | |
tree | d43bc141b2e588300e639bdb4f004ad6945e6081 /.config/zsh/plugins/zsh-autosuggestions.zsh | |
parent | e02304f014645a01ef6cdd40276997dea58504d9 (diff) |
jupyter update
Diffstat (limited to '.config/zsh/plugins/zsh-autosuggestions.zsh')
-rw-r--r-- | .config/zsh/plugins/zsh-autosuggestions.zsh | 864 |
1 files changed, 0 insertions, 864 deletions
diff --git a/.config/zsh/plugins/zsh-autosuggestions.zsh b/.config/zsh/plugins/zsh-autosuggestions.zsh deleted file mode 100644 index b19cac7..0000000 --- a/.config/zsh/plugins/zsh-autosuggestions.zsh +++ /dev/null @@ -1,864 +0,0 @@ -# Fish-like fast/unobtrusive autosuggestions for zsh. -# https://github.com/zsh-users/zsh-autosuggestions -# v0.7.0 -# Copyright (c) 2013 Thiago de Arruda -# Copyright (c) 2016-2021 Eric Freese -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. - -#--------------------------------------------------------------------# -# Global Configuration Variables # -#--------------------------------------------------------------------# - -# Color to use when highlighting suggestion -# Uses format of `region_highlight` -# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets -(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) && -typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8' - -# Prefix to use when saving original versions of bound widgets -(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) && -typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig- - -# Strategies to use to fetch a suggestion -# Will try each strategy in order until a suggestion is returned -(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && { - typeset -ga ZSH_AUTOSUGGEST_STRATEGY - ZSH_AUTOSUGGEST_STRATEGY=(history) -} - -# Widgets that clear the suggestion -(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && { - typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS - ZSH_AUTOSUGGEST_CLEAR_WIDGETS=( - history-search-forward - history-search-backward - history-beginning-search-forward - history-beginning-search-backward - history-substring-search-up - history-substring-search-down - up-line-or-beginning-search - down-line-or-beginning-search - up-line-or-history - down-line-or-history - accept-line - copy-earlier-word - ) -} - -# Widgets that accept the entire suggestion -(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && { - typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS - ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=( - forward-char - end-of-line - vi-forward-char - vi-end-of-line - vi-add-eol - ) -} - -# Widgets that accept the entire suggestion and execute it -(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && { - typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS - ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=( - ) -} - -# Widgets that accept the suggestion as far as the cursor moves -(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && { - typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS - ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=( - forward-word - emacs-forward-word - vi-forward-word - vi-forward-word-end - vi-forward-blank-word - vi-forward-blank-word-end - vi-find-next-char - vi-find-next-char-skip - ) -} - -# Widgets that should be ignored (globbing supported but must be escaped) -(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && { - typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS - ZSH_AUTOSUGGEST_IGNORE_WIDGETS=( - orig-\* - beep - run-help - set-local-history - which-command - yank - yank-pop - zle-\* - ) -} - -# Pty name for capturing completions for completion suggestion strategy -(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) && -typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty - -#--------------------------------------------------------------------# -# Utility Functions # -#--------------------------------------------------------------------# - -_zsh_autosuggest_escape_command() { - setopt localoptions EXTENDED_GLOB - - # Escape special chars in the string (requires EXTENDED_GLOB) - echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}" -} - -#--------------------------------------------------------------------# -# Widget Helpers # -#--------------------------------------------------------------------# - -_zsh_autosuggest_incr_bind_count() { - typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1)) - _ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count -} - -# Bind a single widget to an autosuggest widget, saving a reference to the original widget -_zsh_autosuggest_bind_widget() { - typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS - - local widget=$1 - local autosuggest_action=$2 - local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX - - local -i bind_count - - # Save a reference to the original widget - case $widgets[$widget] in - # Already bound - user:_zsh_autosuggest_(bound|orig)_*) - bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget])) - ;; - - # User-defined widget - user:*) - _zsh_autosuggest_incr_bind_count $widget - zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:} - ;; - - # Built-in widget - builtin) - _zsh_autosuggest_incr_bind_count $widget - eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }" - zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget - ;; - - # Completion widget - completion:*) - _zsh_autosuggest_incr_bind_count $widget - eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}" - ;; - esac - - # Pass the original widget's name explicitly into the autosuggest - # function. Use this passed in widget name to call the original - # widget instead of relying on the $WIDGET variable being set - # correctly. $WIDGET cannot be trusted because other plugins call - # zle without the `-w` flag (e.g. `zle self-insert` instead of - # `zle self-insert -w`). - eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() { - _zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@ - }" - - # Create the bound widget - zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget -} - -# Map all configured widgets to the right autosuggest widgets -_zsh_autosuggest_bind_widgets() { - emulate -L zsh - - local widget - local ignore_widgets - - ignore_widgets=( - .\* - _\* - ${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-} - $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\* - $ZSH_AUTOSUGGEST_IGNORE_WIDGETS - ) - - # Find every widget we might want to bind and bind it appropriately - for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do - if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then - _zsh_autosuggest_bind_widget $widget clear - elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then - _zsh_autosuggest_bind_widget $widget accept - elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then - _zsh_autosuggest_bind_widget $widget execute - elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then - _zsh_autosuggest_bind_widget $widget partial_accept - else - # Assume any unspecified widget might modify the buffer - _zsh_autosuggest_bind_widget $widget modify - fi - done -} - -# Given the name of an original widget and args, invoke it, if it exists -_zsh_autosuggest_invoke_original_widget() { - # Do nothing unless called with at least one arg - (( $# )) || return 0 - - local original_widget_name="$1" - - shift - - if (( ${+widgets[$original_widget_name]} )); then - zle $original_widget_name -- $@ - fi -} - -#--------------------------------------------------------------------# -# Highlighting # -#--------------------------------------------------------------------# - -# If there was a highlight, remove it -_zsh_autosuggest_highlight_reset() { - typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT - - if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then - region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}") - unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT - fi -} - -# If there's a suggestion, highlight it -_zsh_autosuggest_highlight_apply() { - typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT - - if (( $#POSTDISPLAY )); then - typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" - region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT") - else - unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT - fi -} - -#--------------------------------------------------------------------# -# Autosuggest Widget Implementations # -#--------------------------------------------------------------------# - -# Disable suggestions -_zsh_autosuggest_disable() { - typeset -g _ZSH_AUTOSUGGEST_DISABLED - _zsh_autosuggest_clear -} - -# Enable suggestions -_zsh_autosuggest_enable() { - unset _ZSH_AUTOSUGGEST_DISABLED - - if (( $#BUFFER )); then - _zsh_autosuggest_fetch - fi -} - -# Toggle suggestions (enable/disable) -_zsh_autosuggest_toggle() { - if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then - _zsh_autosuggest_enable - else - _zsh_autosuggest_disable - fi -} - -# Clear the suggestion -_zsh_autosuggest_clear() { - # Remove the suggestion - unset POSTDISPLAY - - _zsh_autosuggest_invoke_original_widget $@ -} - -# Modify the buffer and get a new suggestion -_zsh_autosuggest_modify() { - local -i retval - - # Only available in zsh >= 5.4 - local -i KEYS_QUEUED_COUNT - - # Save the contents of the buffer/postdisplay - local orig_buffer="$BUFFER" - local orig_postdisplay="$POSTDISPLAY" - - # Clear suggestion while waiting for next one - unset POSTDISPLAY - - # Original widget may modify the buffer - _zsh_autosuggest_invoke_original_widget $@ - retval=$? - - emulate -L zsh - - # Don't fetch a new suggestion if there's more input to be read immediately - if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then - POSTDISPLAY="$orig_postdisplay" - return $retval - fi - - # Optimize if manually typing in the suggestion or if buffer hasn't changed - if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then - POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" - return $retval - fi - - # Bail out if suggestions are disabled - if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then - return $? - fi - - # Get a new suggestion if the buffer is not empty after modification - if (( $#BUFFER > 0 )); then - if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then - _zsh_autosuggest_fetch - fi - fi - - return $retval -} - -# Fetch a new suggestion based on what's currently in the buffer -_zsh_autosuggest_fetch() { - if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then - _zsh_autosuggest_async_request "$BUFFER" - else - local suggestion - _zsh_autosuggest_fetch_suggestion "$BUFFER" - _zsh_autosuggest_suggest "$suggestion" - fi -} - -# Offer a suggestion -_zsh_autosuggest_suggest() { - emulate -L zsh - - local suggestion="$1" - - if [[ -n "$suggestion" ]] && (( $#BUFFER )); then - POSTDISPLAY="${suggestion#$BUFFER}" - else - unset POSTDISPLAY - fi -} - -# Accept the entire suggestion -_zsh_autosuggest_accept() { - local -i retval max_cursor_pos=$#BUFFER - - # When vicmd keymap is active, the cursor can't move all the way - # to the end of the buffer - if [[ "$KEYMAP" = "vicmd" ]]; then - max_cursor_pos=$((max_cursor_pos - 1)) - fi - - # If we're not in a valid state to accept a suggestion, just run the - # original widget and bail out - if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then - _zsh_autosuggest_invoke_original_widget $@ - return - fi - - # Only accept if the cursor is at the end of the buffer - # Add the suggestion to the buffer - BUFFER="$BUFFER$POSTDISPLAY" - - # Remove the suggestion - unset POSTDISPLAY - - # Run the original widget before manually moving the cursor so that the - # cursor movement doesn't make the widget do something unexpected - _zsh_autosuggest_invoke_original_widget $@ - retval=$? - - # Move the cursor to the end of the buffer - if [[ "$KEYMAP" = "vicmd" ]]; then - CURSOR=$(($#BUFFER - 1)) - else - CURSOR=$#BUFFER - fi - - return $retval -} - -# Accept the entire suggestion and execute it -_zsh_autosuggest_execute() { - # Add the suggestion to the buffer - BUFFER="$BUFFER$POSTDISPLAY" - - # Remove the suggestion - unset POSTDISPLAY - - # Call the original `accept-line` to handle syntax highlighting or - # other potential custom behavior - _zsh_autosuggest_invoke_original_widget "accept-line" -} - -# Partially accept the suggestion -_zsh_autosuggest_partial_accept() { - local -i retval cursor_loc - - # Save the contents of the buffer so we can restore later if needed - local original_buffer="$BUFFER" - - # Temporarily accept the suggestion. - BUFFER="$BUFFER$POSTDISPLAY" - - # Original widget moves the cursor - _zsh_autosuggest_invoke_original_widget $@ - retval=$? - - # Normalize cursor location across vi/emacs modes - cursor_loc=$CURSOR - if [[ "$KEYMAP" = "vicmd" ]]; then - cursor_loc=$((cursor_loc + 1)) - fi - - # If we've moved past the end of the original buffer - if (( $cursor_loc > $#original_buffer )); then - # Set POSTDISPLAY to text right of the cursor - POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}" - - # Clip the buffer at the cursor - BUFFER="${BUFFER[1,$cursor_loc]}" - else - # Restore the original buffer - BUFFER="$original_buffer" - fi - - return $retval -} - -() { - typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS - - _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=( - clear - fetch - suggest - accept - execute - enable - disable - toggle - ) - - local action - for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do - eval "_zsh_autosuggest_widget_$action() { - local -i retval - - _zsh_autosuggest_highlight_reset - - _zsh_autosuggest_$action \$@ - retval=\$? - - _zsh_autosuggest_highlight_apply - - zle -R - - return \$retval - }" - done - - for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do - zle -N autosuggest-$action _zsh_autosuggest_widget_$action - done -} - -#--------------------------------------------------------------------# -# Completion Suggestion Strategy # -#--------------------------------------------------------------------# -# Fetches a suggestion from the completion engine -# - -_zsh_autosuggest_capture_postcompletion() { - # Always insert the first completion into the buffer - compstate[insert]=1 - - # Don't list completions - unset 'compstate[list]' -} - -_zsh_autosuggest_capture_completion_widget() { - # Add a post-completion hook to be called after all completions have been - # gathered. The hook can modify compstate to affect what is done with the - # gathered completions. - local -a +h comppostfuncs - comppostfuncs=(_zsh_autosuggest_capture_postcompletion) - - # Only capture completions at the end of the buffer - CURSOR=$#BUFFER - - # Run the original widget wrapping `.complete-word` so we don't - # recursively try to fetch suggestions, since our pty is forked - # after autosuggestions is initialized. - zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]} - - if is-at-least 5.0.3; then - # Don't do any cr/lf transformations. We need to do this immediately before - # output because if we do it in setup, onlcr will be re-enabled when we enter - # vared in the async code path. There is a bug in zpty module in older versions - # where the tty is not properly attached to the pty slave, resulting in stty - # getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream - # commit f75904a38 - stty -onlcr -ocrnl -F /dev/tty - fi - - # The completion has been added, print the buffer as the suggestion - echo -nE - $'\0'$BUFFER$'\0' -} - -zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget - -_zsh_autosuggest_capture_setup() { - # There is a bug in zpty module in older zsh versions by which a - # zpty that exits will kill all zpty processes that were forked - # before it. Here we set up a zsh exit hook to SIGKILL the zpty - # process immediately, before it has a chance to kill any other - # zpty processes. - if ! is-at-least 5.4; then - zshexit() { - # The zsh builtin `kill` fails sometimes in older versions - # https://unix.stackexchange.com/a/477647/156673 - kill -KILL $$ 2>&- || command kill -KILL $$ - - # Block for long enough for the signal to come through - sleep 1 - } - fi - - # Try to avoid any suggestions that wouldn't match the prefix - zstyle ':completion:*' matcher-list '' - zstyle ':completion:*' path-completion false - zstyle ':completion:*' max-errors 0 not-numeric - - bindkey '^I' autosuggest-capture-completion -} - -_zsh_autosuggest_capture_completion_sync() { - _zsh_autosuggest_capture_setup - - zle autosuggest-capture-completion -} - -_zsh_autosuggest_capture_completion_async() { - _zsh_autosuggest_capture_setup - - zmodload zsh/parameter 2>/dev/null || return # For `$functions` - - # Make vared completion work as if for a normal command line - # https://stackoverflow.com/a/7057118/154703 - autoload +X _complete - functions[_original_complete]=$functions[_complete] - function _complete() { - unset 'compstate[vared]' - _original_complete "$@" - } - - # Open zle with buffer set so we can capture completions for it - vared 1 -} - -_zsh_autosuggest_strategy_completion() { - # Reset options to defaults and enable LOCAL_OPTIONS - emulate -L zsh - - # Enable extended glob for completion ignore pattern - setopt EXTENDED_GLOB - - typeset -g suggestion - local line REPLY - - # Exit if we don't have completions - whence compdef >/dev/null || return - - # Exit if we don't have zpty - zmodload zsh/zpty 2>/dev/null || return - - # Exit if our search string matches the ignore pattern - [[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return - - # Zle will be inactive if we are in async mode - if zle; then - zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync - else - zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1" - zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t' - fi - - { - # The completion result is surrounded by null bytes, so read the - # content between the first two null bytes. - zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0' - - # Extract the suggestion from between the null bytes. On older - # versions of zsh (older than 5.3), we sometimes get extra bytes after - # the second null byte, so trim those off the end. - # See http://www.zsh.org/mla/workers/2015/msg03290.html - suggestion="${${(@0)line}[2]}" - } always { - # Destroy the pty - zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME - } -} - -#--------------------------------------------------------------------# -# History Suggestion Strategy # -#--------------------------------------------------------------------# -# Suggests the most recent history item that matches the given -# prefix. -# - -_zsh_autosuggest_strategy_history() { - # Reset options to defaults and enable LOCAL_OPTIONS - emulate -L zsh - - # Enable globbing flags so that we can use (#m) and (x~y) glob operator - setopt EXTENDED_GLOB - - # Escape backslashes and all of the glob operators so we can use - # this string as a pattern to search the $history associative array. - # - (#m) globbing flag enables setting references for match data - # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 - local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" - - # Get the history items that match the prefix, excluding those that match - # the ignore pattern - local pattern="$prefix*" - if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then - pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" - fi - - # Give the first history item matching the pattern as the suggestion - # - (r) subscript flag makes the pattern match on values - typeset -g suggestion="${history[(r)$pattern]}" -} - -#--------------------------------------------------------------------# -# 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. -# -# For example, suppose your history has the following entries: -# - pwd -# - ls foo -# - ls bar -# - pwd -# -# Given the history list above, when you type 'ls', the suggestion -# will be 'ls foo' rather than 'ls bar' because your most recently -# executed command (pwd) was previously followed by 'ls foo'. -# -# 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`. - -_zsh_autosuggest_strategy_match_prev_cmd() { - # Reset options to defaults and enable LOCAL_OPTIONS - emulate -L zsh - - # Enable globbing flags so that we can use (#m) and (x~y) glob operator - setopt EXTENDED_GLOB - - # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 - local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" - - # Get the history items that match the prefix, excluding those that match - # the ignore pattern - local pattern="$prefix*" - if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then - pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" - fi - - # Get all history event numbers that correspond to history - # entries that match the pattern - local history_match_keys - history_match_keys=(${(k)history[(R)$~pattern]}) - - # 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))]}")" - - # Iterate up to the first 200 history event numbers that match $prefix - for key in "${(@)history_match_keys[1,200]}"; 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 - histkey="$key" - break - fi - done - - # Give back the matched history entry - typeset -g suggestion="$history[$histkey]" -} - -#--------------------------------------------------------------------# -# Fetch Suggestion # -#--------------------------------------------------------------------# -# Loops through all specified strategies and returns a suggestion -# from the first strategy to provide one. -# - -_zsh_autosuggest_fetch_suggestion() { - typeset -g suggestion - local -a strategies - local strategy - - # Ensure we are working with an array - strategies=(${=ZSH_AUTOSUGGEST_STRATEGY}) - - for strategy in $strategies; do - # Try to get a suggestion from this strategy - _zsh_autosuggest_strategy_$strategy "$1" - - # Ensure the suggestion matches the prefix - [[ "$suggestion" != "$1"* ]] && unset suggestion - - # Break once we've found a valid suggestion - [[ -n "$suggestion" ]] && break - done -} - -#--------------------------------------------------------------------# -# Async # -#--------------------------------------------------------------------# - -_zsh_autosuggest_async_request() { - zmodload zsh/system 2>/dev/null # For `$sysparams` - - typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID - - # If we've got a pending request, cancel it - if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then - # Close the file descriptor and remove the handler - exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- - zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD - - # We won't know the pid unless the user has zsh/system module installed - if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then - # Zsh will make a new process group for the child process only if job - # control is enabled (MONITOR option) - if [[ -o MONITOR ]]; then - # Send the signal to the process group to kill any processes that may - # have been forked by the suggestion strategy - kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null - else - # Kill just the child process since it wasn't placed in a new process - # group. If the suggestion strategy forked any child processes they may - # be orphaned and left behind. - kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null - fi - fi - fi - - # Fork a process to fetch a suggestion and open a pipe to read from it - exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( - # Tell parent process our pid - echo $sysparams[pid] - - # Fetch and print the suggestion - local suggestion - _zsh_autosuggest_fetch_suggestion "$1" - echo -nE "$suggestion" - ) - - # There's a weird bug here where ^C stops working unless we force a fork - # See https://github.com/zsh-users/zsh-autosuggestions/issues/364 - autoload -Uz is-at-least - is-at-least 5.8 || command true - - # Read the pid from the child process - read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD - - # When the fd is readable, call the response handler - zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response -} - -# Called when new data is ready to be read from the pipe -# First arg will be fd ready for reading -# Second arg will be passed in case of error -_zsh_autosuggest_async_response() { - emulate -L zsh - - local suggestion - - if [[ -z "$2" || "$2" == "hup" ]]; then - # Read everything from the fd and give it as a suggestion - IFS='' read -rd '' -u $1 suggestion - zle autosuggest-suggest -- "$suggestion" - - # Close the fd - exec {1}<&- - fi - - # Always remove the handler - zle -F "$1" -} - -#--------------------------------------------------------------------# -# Start # -#--------------------------------------------------------------------# - -# Start the autosuggestion widgets -_zsh_autosuggest_start() { - # By default we re-bind widgets on every precmd to ensure we wrap other - # wrappers. Specifically, highlighting breaks if our widgets are wrapped by - # zsh-syntax-highlighting widgets. This also allows modifications to the - # widget list variables to take effect on the next precmd. However this has - # a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND - # to disable the automatic re-binding. - if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then - add-zsh-hook -d precmd _zsh_autosuggest_start - fi - - _zsh_autosuggest_bind_widgets -} - -# Mark for auto-loading the functions that we use -autoload -Uz add-zsh-hook is-at-least - -# Automatically enable asynchronous mode in newer versions of zsh. Disable for -# older versions because there is a bug when using async mode where ^C does not -# work immediately after fetching a suggestion. -# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 -if is-at-least 5.0.8; then - typeset -g ZSH_AUTOSUGGEST_USE_ASYNC= -fi - -# Start the autosuggestion widgets on the next precmd -add-zsh-hook precmd _zsh_autosuggest_start |