我已经尝试了几个小时来让它工作但感觉我还没有成功。
我正在尝试通过从 Mac OS X 终端制表符完成目录名称来缩短我们的工作流程。
我们有一个内部工具,我们称之为bob
,它会自动在 git 子模块上运行命令。我想让它自动完成子目录名称。问题是,这些子目录位于静态位置。
project directory
->public
->submodules
->a-module
->another-module
->other-module
->some-module
命令从顶级项目目录运行,如下所示:
bob start bugfix anothermodule
我希望能够让 Tab 自动完成功能发挥作用,而不是像我们现在所做的那样,必须完全输入“anothermodule”。我们每天都会多次使用这种工作流程,如果能节省几秒钟的时间,并避免输入错误,那就太好了。
最终目标是:
bob start bugfix an<tab>
将自动完成至
bob start bugfix anothermodule
我尝试过CDPATH
但很快意识到这不是我想要的,因为这不遵循命令cd
,只是我的自定义命令。
我已经bash_completion
安装了,但总体来说我不太擅长使用 bash。不过还是提一下,万一它能成为解决方案的一部分!
答案1
这是Kamil 的精彩回答-module
从每个子目录名称的部分中删除连字符。
bugfix)
curdir=$(pwd)
cd public/submodules/ 2>/dev/null && _filedir -d
# Strip the hyphen from `-module` in each sub-directory name.
for ((i=0; i<${#COMPREPLY[@]}; i++)); do
COMPREPLY[$i]="${COMPREPLY[$i]/-module/module}"
done
cd "$curdir"
;;
这部分仍有改进的空间:你可能需要输入连字符,即输入a-Tab以完成 to ,而不是在andamodule
之间进行选择amodule
anothermodule
(连字符仍然被完成功能剥离)。
答案2
这是正确的,bash_completion
这是一个解决方案。我可以告诉你我的 Ubuntu 中有什么。我希望 Mac 上的情况至少也类似。
有/etc/bash_completion
文件来源/usr/share/bash-completion/bash_completion
。
目录中/usr/share/bash-completion
还有一个completions
子目录。这是脚本的位置。让我们看一下eject
脚本:
# bash completion for eject(1) -*- shell-script -*- _eject() { local cur prev words cword _init_completion || return case $prev in -h|--help|-V|--version|-c|--changerslot|-x|--cdspeed) return ;; -a|--auto|-i|--manualeject) COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) return ;; esac if [[ $cur == -* ]]; then COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) ) return elif [[ $prev == @(-d|--default) ]]; then return fi _cd_devices _dvd_devices } && complete -F _eject eject # ex: ts=4 sw=4 et filetype=sh
即使没有阅读文档,我们也可以对其进行一些逆向工程,并根据您的情况进行调整。对我们来说,上述代码中最重要的部分是它说在 之后-a
,--auto
-i
或者--manualeject
可以有on
或off
。在您的例子中,bugfix
您需要一个目录名称。
(或者不是。你有another-module
目录,但你使用anothermodule
参数。现在我假设这是一个打字错误。如果不是,安东尼的回答我认为它将为你指明正确的方向。)
我们可以以某种方式提取您想要的目录并替换'on off'
,但利用现有代码可能更好。在我输入之后cd
,bash
会自动完成目录,即使有空格或特殊字符,它也能正常工作。所以让我们看看_cd()
函数;它在/usr/share/bash-completion/bash_completion
,我不会在这里粘贴它。接下来,这个函数的关键部分似乎是调用。就在定义_filedir -d
where 之前,我们有:_filedir()
# This function performs file and directory completion. It's better than # simply using 'compgen -f', because it honours spaces in filenames.
答对了。
于是我复制了eject
该名称下的脚本bob
并编辑为以下形式:
# bash completion for bob -*- shell-script -*-
_bob()
{
local cur prev words cword curdir
_init_completion || return
case $prev in
bob)
COMPREPLY=( $( compgen -W 'start stop foo bar' -- "$cur" ) )
return
;;
start)
COMPREPLY=( $( compgen -W 'bugfix' -- "$cur" ) )
return
;;
bugfix)
curdir=$(pwd)
cd public/submodules/ 2>/dev/null && _filedir -d
cd "$curdir"
;;
esac
} &&
complete -F _bob bob
现有bash
会话不会注意到此文件,您必须运行一个新的bash
来测试它。
是的,这是快速而肮脏的巫术编程,对不起。
注意我们下降到public/submodules/
并返回。通常我会使用子 shell:
export -f _filedir
( cd … && _filedir -d )
但这样看起来_filedir
不行。