如何解决如何将 zsh 函数作为文件自动完成?
我用zsh写了一个函数来代替cd函数。在一些帮助下,我让它像我想要的那样工作(主要是)。这是 one of my other question 的后续。 该函数几乎按我的意愿工作,但我在语法突出显示和自动完成方面仍然存在一些问题。
对于示例,假设您的目录如下所示:
/
a/
b/
c/
d/
some_dir/
cl () {
local first=$( echo $1 | cut -d/ -f1 )
if [ -d $first ]; then
pushd $1 >/dev/null # If the first argument is an existing normal directory,move there
else
pushd ${PWD%/$first/*}/$1 >/dev/null # Otherwise,move to a parent directory or a child of that parent directory
fi
}
_cl() {
_cd
pth=${words[2]}
opts=""
new=${pth##*/}
local expl
# Generate the visual formatting and store it in `$expl`
_description -V ancestor-directories expl 'ancestor directories'
[[ "$pth" != *"/"*"/"* ]] && middle="" || middle="${${pth%/*}#*/}/"
if [[ "$pth" != *"/"* ]]; then
# If this is the start of the path
# In this case we should also show the parent directories
local ancestor=$PWD:h
while (( $#ancestor > 1 )); do
# -f: Treat this as a file (incl. dirs),so you get proper highlighting.
# -Q: Don't quote (escape) any of the characters.
# -W: Specify the parent of the dir we're adding.
# ${ancestor:h}: The parent ("head") of $ancestor.
# ${ancestor:t}: The short name ("tail") of $ancestor.
compadd "$expl[@]" -fQ -W "${ancestor:h}/" - "${ancestor:t}"
# Move on to the next parent.
ancestor=$ancestor:h
done
else
# $first is the first part of the path the user typed in.
# it it is part of the current direoctory,we kNow the user is trying to go back to a directory
first=${pth%%/*}
# $middle is the rest of the provided path
if [ ! -d $first ]; then
# path starts with parent directory
dir=${PWD%/$first/*}/$first
first=$first/
# List all sub directories of the $dir/$middle directory
if [ -d "$dir/$middle" ]; then
for d in $(ls -a $dir/$middle); do
if [ -d $dir/$middle/$d ] && [[ "$d" != "." ]] && [[ "$d" != ".." ]]; then
compadd "$expl[@]" -fQ -W $dir/ - $first$middle$d
fi
done
fi
fi
fi
}
compdef _cl cl
问题: 当返回到父目录时,complition 最有效。但是当你转到父目录的一个子目录时,建议是错误的(显示的是你输入的完整路径,而不仅仅是子目录)。
示例:
$ cd /a/c/d
$ cl a/[tab] # What it currently displays
a/b a/c a/some_dir
$ cl a/[tab] # What I want it to display
b c some_dir
如何让它显示第二个建议?
解决方法
通过提供带有 -d
选项的显示字符串数组,您可以让完成以任何您想要的方式显示:
local -a disp
# (N) gives an empty array when there are no matches,rather than an error.
# (:t) returns the last segment of each path.
for d in $dir/$middle*(N:t); do
disp=( "$d" )
compadd "$expl[@]" -fQ -W $dir/ -d disp - $first$middle$d
done
文档:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。