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

zoxide completion on "second cd argument" breaks Zsh autocomplete #766

Open
ssokolow opened this issue Mar 20, 2024 · 3 comments
Open

zoxide completion on "second cd argument" breaks Zsh autocomplete #766

ssokolow opened this issue Mar 20, 2024 · 3 comments

Comments

@ssokolow
Copy link

ssokolow commented Mar 20, 2024

Version: zoxide 0.9.4, freshly cargo install'd as of 2024-03-20 04:38 EDT

**Realistic Reproducer: Type (cd ~/incoming/Videos/something <Tab> by accident (note the unescaped space before the Tab key press) and try to backspace

Minimal Reproducer: Type cd egkpgeqko <Tab> and try to backspace (Again, note the unescaped space before the Tab key press)

Result: It's impossible to backspace beyond the newline zoxide's error message introduces and I'm forced to Ctrl+C to a fresh prompt and grab the mouse to copy-paste what I had typed into it.

Expected Result: Nothing is inserted if there are no matches, same as if I were using completion without zoxide.

I know it used to work this way in a previous version because I've made this mistake before but only started encountering this bug after reinstalling Kubuntu Linux for a clean 20.04 LTS to 22.04 LTS upgrade (preserving my existing $HOME), and re-running my cargo installs to clear out any "Error: Couldn't find older OpenSSL .so file" errors and the like.

Given that I use completion a LOT but I often forget I even have zoxide, I'll be temporarily disabling it as a workaround.

@ajeetdsouza
Copy link
Owner

Could you share your .zshrc file? I tried this on my machine, but I can't reproduce the issue.

@ssokolow
Copy link
Author

It's a bit... multi-part, so I'll share just the root .zshrc first, since that's where the ZSH completion configuration lives. If that's not enough, I'll figure out the least overwhelming way to share the rest.

# ssokolow's .zshrc
#
# {{{ Quick Reference:
# [elided: long reference documentation]
# }}}
# {{{ TODO:
# [elided: long TODO list]
# }}}

# {{{ Note the start time to detect slow starts due to disk contention

# (Use a prompt expansion modifier `(%s)` on a defaulting variable substitution
#  `:-` that contains a default but no variable so it can access `strftime`
#  without invoking a subshell to call `print -P`.)
local start_time="${(%):-"%D{%s}"}"

# }}}
# {{{ Options for profiling startup time

# Use zsh's high-level profiler
# (Run `zprof | less` after startup completes)
#zmodload zsh/zprof

# Generate more detailed xtrace script to further investigate startup time
# See https://github.com/raboof/zshprof for KCachegrind adapter
MAKE_XTRACE_DUMP=0
if [ "${MAKE_XTRACE_DUMP:-0}" = 1 ]; then
    local xtrace_path=/tmp/zshstart.$$.log
    PS4=$'\\\011%D{%s%6.}\011%x\011%I\011%N\011%e\011'
    exec 3>&2 2>$xtrace_path
    setopt xtrace prompt_subst
fi

# }}}
# {{{ Source all environment settings common to both zsh and bash
# ...and don't let /etc/zsh/zprofile override env
# (Don't run it twice like `. .zshenv` would be)
# See: https://shreevatsa.wordpress.com/2008/03/30/zshbash-startup-files-loading-order-bashrc-zshrc-etc/
source ~/.common_sh_init/env

# zsh-internal equivalent to "export SHELL=`which zsh`"
# So things like 'exec zsh' work as I intend.
export SHELL==zsh

# Not sure if I need this, but it can't hurt. Fix for rcp, scp, and sudo -s.
# See the copy in .bashrc for a full explanation of its purpose
if [[ $- != *i* ]] || [[ "$EUID" -eq 0 ]] ; then
        return
fi
# }}}
# {{{ Load Definitions Shared With Bash:

# Pull in the stuff common to both bash and zsh
source ~/.common_sh_init/aliases
source ~/.common_sh_init/misc

# Make sure there are no duplicate entries in PATH or PYTHONPATH
typeset -U PATH PYTHONPATH

# }}}

# Set up the on-action arrays for use
typeset -ga preexec_functions
typeset -ga precmd_functions
typeset -ga chpwd_functions

autoload -Uz zrecompile # Generate and cache compiled versions of initscripts
autoload -Uz run-help   # Enable Meta-H (Alt/Esc-h/H) to read the manpage for
                        # the current partially typed command

# My own functions
autoload -Uz anonsh audmv url-encode
autoload -Uz 457mv setprj
source ~/.zsh/zshrc.d/help-gnu.zsh
source ~/.zsh/zshrc.d/rg

# {{{ Completion:
# Note: Must come after common_sh_init defines any desired LS_COLORS

# Enable completion (case-insensitive, colorized, and tricked-out)
autoload -Uz compinit

# Only have compinit check the completion cache for staleness once per day
#  https://medium.com/@dannysmith/little-thing-2-speeding-up-zsh-f1860390f92
for dump in ~/.zcompdump(N.mh+24); do
  echo "Bringing completions up to date..."
  compinit
  touch "$dump"

  # Compile ~/.zcompdump (Takes compinit from 90% to ~60% of zprof)
  zcompile -U "$dump" &!
  echo "Done."
done

compinit -C

# Disabled to work around ajeetdsouza/zoxide#766
#eval "$(zoxide init zsh --cmd cd)"

zstyle ':completion::complete:*' use-cache 1
zstyle ':completion:*' cache-path ~/.zsh/cache
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' # Match lowercase letters case-insensitively but not uppercase ones

# Speed up completions by reducing the fuzziness of the matching
zstyle ':completion:*' accept-exact '*(N)'
# TODO: Forget fuzziness. It's too much hassle and too slow sometimes.

# Group completions by different object types for big result sets (eg. rsync)
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%B%F{green}%d%f%b'

# Colorize completions (Note: Must come after common_sh_init defines LS_COLORS)
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'

# Show arrow-navigable completions and, for "kill", do it even when unambiguous
# (https://bbs.archlinux.org/viewtopic.php?pid=987587#p987587)
zstyle ':completion:*' menu yes select
# TODO: Figure out how to get insert-unambiguous on the first keypress and menu
# on the second.
zstyle ':completion:*:kill:*' force-list always
zstyle ':completion:*:*:kill:*' verbose yes
# TODO: Use accept-and-menu-complete (or, if that doesn't work, try
#       accept-and-infer-next-history) to set up a keybind for accepting the
#       selected completion and then triggering more completion (like "descend
#       into directory" in vim's wildmenu)

# Set up some comfy completion exemptions
zstyle ':completion:*:functions' ignored-patterns '_*'                     # hide completion functions from the completer
zstyle ':completion:*:cd:*' ignored-patterns '(*/)#lost+found'             # hide the lost+found directory from cd
zstyle ':completion:*:complete:-command-::commands' ignored-patterns '*\~' # don't complete backup files as executables

# commands like kill don't want the same completion multiple times
# (Don't add things which take paths to this. It breaks ~/.vim<Tab> → ~/.vim/)
zstyle ':completion:*:(kill|killall|pgrep|pkill):*' ignore-line yes

# Exclude bytecode and temporary files from filename completion.
zstyle ':completion:*:*files' ignored-patterns '*?.o' '*?.pyc' '*?.pyo' '*?.class' '*?~' '*?.bak'
# TODO: Make this work
# Exclude bytecode and temporary files from completion for everything except rm.
#zstyle ':completion:*:*:(^rm):*:*files' ignored-patterns '*?.o' '*?.pyc' '*?.pyo' '*?~' '*?.bak'

# Complete PIDs and process names to any process owned by my user
# (Use "cut" as a workaround for kdeinit4 argv[0])
zstyle ':completion:*:processes' command 'ps x'     # Complete PIDs any process owned by my user
zstyle ':completion:*:processes-names' command 'ps x -o command | cut -d: -f1'

# Opt ssh and rsync out of /etc/hosts so my ad-blocking doesn't flood out
# useful completions (https://gist.github.com/4000350)
local _hosts
_hosts=(${${${(M)${(f)"$(<~/.ssh/config)"}:#Host*}#Host }:#*\**})
zstyle ':completion:*' hosts $_hosts

# Only complete users to non-system accounts (https://gist.github.com/4000615)
# Note: Only gives "root" on OSX because "getent passwd" returns an empty list
#       (Need to parse 'dscacheutil -q user' there, which has another format)
local _users
_users=(root)
getent passwd | while IFS=: read name passwd uid rest; do
    if [[ $uid = <1000-> ]]; then
        _users=($_users $name)
    fi
done
zstyle ':completion:*' users $_users

# TODO: Identify which "Shell Options" control completion and move them here
# TODO: Can I set up a keybind which means "If we're not already in an {a,b,c}
#      group, then move back to the nearest /, insert {, return, and add a ','"?
# TODO: Maybe I should further subdivide this section.

# }}}
# {{{ Keybindings:

# Adjust WORDCHARS so word-by-word basically means "until a space, slash,
# period, question mark, semicolon, or ampersand", so wordwise motions in URLs
# and shellscript one-liners is useful.
WORDCHARS='*+_-[]~=!#$%^(){}<>:@,\\'

# Use EMACS-style keybindings despite my having EDITOR set to vim
bindkey -e

# Make Home/End/Ins/Del work explicitly
bindkey '\e[1~'   beginning-of-line  # Linux console, PuTTY
bindkey '\e[7'    beginning-of-line  # urxvt
bindkey '\e[H'    beginning-of-line  # xterm
bindkey '\eOH'    beginning-of-line  # gnome-terminal
bindkey '\e[2~'   overwrite-mode     # Linux console, xterm, gnome-terminal, urxvt
bindkey '\e[3~'   delete-char        # Linux console, xterm, gnome-terminal, urxvt
bindkey '\e[4~'   end-of-line        # Linux console, PuTTY
bindkey '\e[8'    end-of-line        # urxvt
bindkey '\e[F'    end-of-line        # xterm
bindkey '\eOF'    end-of-line        # gnome-terminal
bindkey '\eOw'    end-of-line        # PuTTy in rxvt mode

# Make word-by-word movement work for Ctrl+Left/Right/Backspace/Delete/Tab
# TODO: Look into making an argument-by-argument delete
bindkey "\eOc"    forward-word  # urxvt
bindkey "\e[1;5C" forward-word  # everything else
bindkey "\eOd"    backward-word # urxvt
bindkey "\e[1;5D" backward-word # everything else
bindkey "\e[3\^"  kill-word # urxvt (old)
bindkey "\e[3;5~" kill-word # everything else
bindkey '^H'      backward-kill-word # konsole
bindkey "\e[Z"    reverse-menu-complete # urxvt
bindkey "\er"     reverse-menu-complete # everything else

# Set up Alt-Del to match Alt-Backspace if I'm ever stuck on VTE.
bindkey "\e[3;3~" kill-word

# Rebind Up/Down arrows to get what I like about bash's cmdhist option
# (ensure that 3 keypresses will move 3 commands up/down the history)
bindkey "^[OA" up-history
bindkey "^[OB" down-history
bindkey "^[[A" up-history
bindkey "^[[B" down-history

# The rest of the stuff from my .inputrc
bindkey "\eOa"   history-beginning-search-backward  # urxvt
bindkey "\e[1;5A" history-beginning-search-backward # everything else
bindkey "\eOb"   history-beginning-search-forward   # urxvt
bindkey "\e[1;5B" history-beginning-search-forward  # everything else
bindkey "\e[3~"   delete-char
bindkey '^r'      history-incremental-search-backward
bindkey ' '       magic-space

# }}}
# {{{ History:

# Make history work
setopt HIST_FCNTL_LOCK 2>/dev/null
setopt HIST_ALLOW_CLOBBER
setopt HIST_IGNORE_ALL_DUPS HIST_FIND_NO_DUPS
setopt HIST_IGNORE_SPACE # Easy way to omit things from history
setopt APPEND_HISTORY # Default, but let's be sure
setopt HIST_VERIFY # Safety for !<cmd><Tab> and the like
setopt SHARE_HISTORY

# http://www.zsh.org/mla/workers/2013/msg00807.html
setopt NO_HIST_REDUCE_BLANKS # TODO: Keep an eye on when this is fixed

HISTFILE=$HOME/.zhistory
HISTSIZE=1100
SAVEHIST=1000

# }}}
# {{{ Shell Options: (TODO: Split out into more appropriate places)

# Set shopts which bash doesn't support
setopt MULTIBYTE
setopt AUTO_PUSHD
setopt PUSHD_SILENT
setopt NUMERIC_GLOB_SORT
setopt LIST_PACKED
setopt SHORT_LOOPS
setopt AUTO_RESUME

# Set shopts equivalent to stuff in my .bashrc
setopt nolistambiguous autolist
setopt NOTIFY # Default, but just in case
setopt INTERACTIVE_COMMENTS
setopt NO_BG_NICE
setopt NOHUP
setopt AUTO_CONTINUE
setopt NO_NOMATCH

# }}}
# {{{ File Extension Associations
# Note: Must be after common_sh_init for EDITOR, IMAGE_MANAGER, and MUSIC_PLAYER

setopt AUTO_CD
alias -s {chm,CHM}=xdg-open
alias -s {pdf,PDF,ps,djvu,DjVu}=xdg-open
alias -s {pdf,PDF,ps,djvu,DjVu}=xdg-open
alias -s {cbr,Cbr,CBR,cbz,Cbz,CBZ}=xdg-open
alias -s {rar,Rar,RAR,zip,Zip,ZIP}=xdg-open
alias -s {php,css,js,htm,html}="$EDITOR"
alias -s {jpeg,jpg,JPEG,JPG,png,gif,xpm}="$IMAGE_VIEWER"
alias -s {avi,AVI,Avi,divx,DivX,mkv,mpg,mpeg,wmv,WMV,mov,rm,flv,ogm,ogv,mp4}=mplayer
alias -s {aac,ape,au,hsc,flac,gbs,gym,it,lds,ogg,m4a,mod,mp2,mp3,MP3,Mp3,mpc,nsf,nsfe,psf,sid,spc,stm,s3m,vgm,vgz,wav,wma,wv,xm}="$MUSIC_PLAYER"
# TODO: Is there any way to set up xdg-open as a default?
# TODO: Find a way to make these suffix aliases case-insensitive.

# }}}
# {{{ fortune command

# I prefer to have a fortune from any new shell, not just login ones
# ...but I don't want it further bogging down an already slow start.
local end_time="${(%):-"%D{%s}"}"
if [[ $(( end_time - start_time )) < 2 ]]; then
    # Might as well micro-optimize this. $+commands is up to 10x faster
    # (https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh/)
    if (( $+commands[fortune] )); then
        fortune
    fi
else
    echo "Skipping fortune (slow startup)"
fi

#}}}
# {{{ Allow the VENV_TO_ACTIVATE variable to activate virtualenvwrapper
if [ -n "$VENV_TO_ACTIVATE" ]; then
    workon "$VENV_TO_ACTIVATE"
    unset "$VENV_TO_ACTIVATE"

    if [ -n "$RUN_IN_VENV" ]; then
        $RUN_IN_VENV
    fi
fi
unset RUN_IN_VENV
# }}}
# {{{ Set prompt and hardstatus

# Defer these until as late as possible to avoid running them unnecessarily
source ~/.zsh/zshrc.d/prompt_gentoo_setup
source ~/.zsh/zshrc.d/hardstatus
source ~/.zsh/zshrc.d/command_not_found_handler

# Load enhanced Ctrl+R
eval "$(mcfly init zsh)"

# }}}
# {{{ Finish gathering profiling data (if enabled)
if [[ "$MAKE_XTRACE_DUMP" = 1 ]]; then
    unsetopt xtrace
    exec 2>&3 3>&-
    echo "Profiling data saved to $xtrace_path"
    if [ -e ~/bin/log2callgrind ]; then
        ~/bin/log2callgrind < "$xtrace_path" > "$xtrace_path".callgrind
        echo "KCachegrind data saved to $xtrace_path".callgrind
    fi
fi
# }}}

# TODO: Set ~/.zshrc immutable to keep things like RVM and the travis gem from
#       messing it up.

@ashleybartlett
Copy link
Contributor

This might be related to #785

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants