Eva*_*ser 6 bash autocomplete tab-completion bash-completion
我正在为点文件管理实用程序的bash完成脚本工作.该工具有一个命令dots diff [filename],用于显示已安装的点文件和源点文件之间的差异.它还有一个命令dots files,列出所有托管点文件的路径(相对于源目录).我想用files命令的输出完成diff命令.
这是文件输出的示例
X11/xkb/symbols/evan-custom
X11/xorg.conf.d/10-dual-monitors.conf
X11/xorg.conf.d/10-keylayout.conf
bash/aliases
bash/bashrc
bash/completion.d/dots
bash/profiles/standard-user
bash/profiles/systemd-user
bspwm/bspwmrc
compton/compton.conf
fontconfig/fonts.conf
git/config
git/ignore
gtk-2.0/gtkrc
gtk-3.0/settings.ini
mysql/config
mysql/grcat
ncmpcpp/config
pulse/client.conf
pulse/daemon.conf
pulse/default.pa
ssh/config
sublime-text-3/Packages/User/Preferences.sublime-settings
sxhkd/sxhkdrc
termite/config
transmission-daemon/settings.json
vim/vimrc
Run Code Online (Sandbox Code Playgroud)
使用这样的东西
COMPREPLY=( $(compgen -W "$(dots files)" -- $cur) )
Run Code Online (Sandbox Code Playgroud)
但是,当readline列出可用选项时,它会列出完整路径(上面的列表).
我希望它将这些单词视为文件路径,并且列出建议时只列出第一个正斜杠.
例如,如果我键入dots diff [tab][tab]以下应该打印
X11/
bash/
bspwm/
compton/
fontconfig/
git/
gtk-2.0/
gtk-3.0/
mysql/
ncmpcpp/
pulse/
ssh/
sublime-text-3/
sxhkd/
termite/
transmission-daemon/
vim/
Run Code Online (Sandbox Code Playgroud)
例如,如果我然后键入dots diff bash/[tab][tab]然后它会显示
aliases
bashrc
completion.d/
profiles/
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望它实际上将其视为一个路径,以便将readline选项更改mark-directories为off将排除尾部斜杠.
我已经尝试过设置compopt -o filenames但是这会提供文件名的建议,而不是最初的路径.
我已经解决了这个问题.
诀窍是使用compopt -o filename然后切掉正在完成的路径部分,该部分是正在完成的目录的子目录.
这是代码
# Do completion from a passed list of paths
#
# Accepts 2 arguments
# 1. The list of paths to complete from
# 2. The current word being completed
__dots_path_comp()
{
# This forces readline to only display the last item separated by a slash
compopt -o filenames
local IFS=$'\n'
local k="${#COMPREPLY[@]}"
for path in $(compgen -W "$1" -- $2)
do
local trailing_trim
# Determine what to trim from the end
trailing_trim="${path#${2%/*}/}/"
trailing_trim="${trailing_trim#*/}"
trailing_trim="${trailing_trim%/}"
# Don't add a space if there is more to complete
[[ "$trailing_trim" != "" ]] && compopt -o nospace
# Remove the slash if mark-directories is off
if ! _rl_enabled mark-directories
then
# If The current typed path doesnt have a slash in it yet check if
# it is the full first portion of a path and ignore everything after
# if it is. We don't have to do this once the typed path has a slash
# in it as the logic above will pick up on it
[[ "$2" != */* && "$path" == ${2}/* ]] && path="$2/$trailing_trim"
trailing_trim="/$trailing_trim"
fi
COMPREPLY[k++]="${path%%${trailing_trim}}"
done
}
Run Code Online (Sandbox Code Playgroud)