Gil*_*il' 22 zsh cd-command autocomplete
在 中zsh,该cd命令具有两个参数的形式:cd OLD NEW更改为${PWD/OLD/NEW}。使用新式补全系统,zsh 能够补全NEW:第二个参数根据OLD可替换的内容补全,以获取现有目录。但是第一个参数只对现有目录完成。
OLD除了完成现有目录之外,如何让 zsh 提供可能值的完成?
例如,如果当前目录是/path/to/foo并且还有目录/also/to/fooand /path/to/foo/prime,则cd pTab完成p到prime。如果我打算运行,cd path also那么我希望 zsh 也path作为完成提供。如何?
使用第二个参数的已输入值来限制第一个参数的可能性将是一个加号,但独立完成第一个参数也可以。
我想您可以将 的组件添加$PWD到cd完成列表中,尽管这似乎需要摆弄_cd; 也就是说, 的定制版本_cd必须首先出现在$fpath.
% cd && mkdir zcomp
% cp $fpath[-1]/_cd zcomp
% fpath=(~/zcomp $fapth)
Run Code Online (Sandbox Code Playgroud)
然后在顶部~/zcomp/_cd添加一个功能
_our_pwd() {
_values ourpwd ${(ps:/:)PWD}
}
Run Code Online (Sandbox Code Playgroud)
然后在该_alternative行之前添加返回到替代列表的内容
...
alt=("$service-options:$service option:_cd_options" "$alt[@]")
fi
alt=(ourpwd:pwd:_our_pwd "$alt[@]")
_alternative "$alt[@]" && ret=0
return ret
...
Run Code Online (Sandbox Code Playgroud)
尽管这总是将pwd组件添加到cd完成中:
% cd
Users jdoe Applications/ Desktop/ Documents/ Downloads/ Library/
...
Run Code Online (Sandbox Code Playgroud)
通过附加逻辑,您只能$PWD在已经存在第二个参数时添加组件,而不是总是添加组件。
然而!这总是会弄乱cd完成,并要求我们对上游_cd完成进行猴子修补。另一种选择是为两个参数提供的函数创建一个新名称cd,可能称为cdsub,并且仅显示组件的完成PWD。将其添加到~/.zshrc
function cdsub { builtin cd "$@" }
Run Code Online (Sandbox Code Playgroud)
然后_cd 将一个完整的内容_cdsub放在以下位置$fpath:
#compdef cdsub
#
# Modified version of _cd from ZSH 5.3.1 with specific support for the
# `cd old new` form whereby PWD elements are provided for completion.
_cd_options() {
_arguments -s \
'-q[quiet, no output or use of hooks]' \
'-s[refuse to use paths with symlinks]' \
'(-P)-L[retain symbolic links ignoring CHASE_LINKS]' \
'(-L)-P[resolve symbolic links as CHASE_LINKS]'
}
setopt localoptions nonomatch
local expl ret=1 curarg
integer argstart=2 noopts
if (( CURRENT > 1 )); then
# if not in command position, may have options.
# Careful: -<-> is not an option.
while [[ $words[$argstart] = -* && argstart -lt CURRENT ]]; do
curarg=$words[$argstart]
[[ $curarg = -<-> ]] && break
(( argstart++ ))
[[ $curarg = -- ]] && noopts=1 && break
done
fi
if [[ CURRENT -eq $((argstart+1)) ]]; then
# cd old new: look for old in $PWD and see what can replace it
local rep
# Get possible completions using word in position 2
rep=(${~PWD/$words[$argstart]/*}~$PWD(-/))
# Now remove all the common parts of $PWD and the completions from this
rep=(${${rep#${PWD%%$words[$argstart]*}}%${PWD#*$words[$argstart]}})
(( $#rep )) && _wanted -C replacement strings expl replacement compadd -a rep
else
_values ourpwd ${(ps:/:)PWD} && ret=0
return ret
fi
Run Code Online (Sandbox Code Playgroud)