Bash completion:生成一个单词列表,就好像它们是路径一样-只在下一个斜杠之前建议
我正在为一家公司编写bash完成脚本。该工具有一个命令Bash completion:生成一个单词列表,就好像它们是路径一样-只在下一个斜杠之前建议,bash,autocomplete,tab-completion,bash-completion,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 bas
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
用这样的东西
COMPREPLY=( $(compgen -W "$(dots files)" -- $cur) )
但是,当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/
例如,如果我随后键入dots diff bash/[tab][tab]
,则它将显示
aliases
bashrc
completion.d/
profiles/
理想情况下,我希望它实际将其视为一个路径,以便将readline选项markdirectories
更改为off将排除后面的斜杠
我尝试过设置compopt-o文件名
,但这反而为文件名提供了建议,而不是最初的路径
一个肮脏的黑客行为是将您的
$(dots文件)
替换为
$(dots files | sed 's,/.*/,,' | uniq)
这样完整的内容就可以理解为
COMPREPLY=( $(compgen -W "$(dots files | sed 's,/.*/,,' | uniq)" -- "$cur") )
现在我个人不太喜欢这种方法。相反,您是否可以修改您的脚本以接受,例如,将输出所需内容的basedirs
语句
此外,您应该注意,如果名称中有空格或其他有趣的符号,则补全将无法按预期工作。我认为您可以使用complete的-F参数获得所需的内容。发件人: 首先调用用-F指定的任何函数。该函数可以使用 壳牌的任何设施,包括康普根和康普特 如下所述的内置设备(参见可编程完成内置设备),以 生成匹配项。它必须把可能的完成放在 压缩数组变量 所以,像这样的设置:
complete -F _dots_complete dots
那么你的功能是:
function _dots_complete {
# your filtering logic to calculate the results array
COMPREPLY=( "${results[@]}" )
}
在函数中,$1是当前单词的位置,$2$n是单词本身。我已经解决了这个问题
诀窍是使用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
}
对不起,我应该指定的。我已经有了一个已经这样做了。问题是它没有将路径列表视为要完成的路径。这不起作用,因为它无法完成路径的第二部分。例如,在完成
bash/
之后,它不会完成该路径下的任何项目。我知道它不适用于空格之类的东西,但我并不担心这一点。@EvanPurkhiser我完全回答了你文章的这一部分:我希望它能将单词当作文件路径来对待,在列出建议时,只列出第一个正斜杠。例如,如果我键入dots diff[tab][tab],则应打印以下内容。。。现在我甚至不明白你到底想要什么,对此我深表歉意。我已经更新了这个问题,加入了一个例子,说明在完成路径的第一部分后会发生什么。