我开发了一个包含可执行脚本的gem(在rubygems术语中为application file)。在调用时,我想在给定目录(不是当前工作目录)中完成文件名,如下所示:
foo edit my<tab>
扩展为:
foo edit myfile
我能做的是包含一个安装shell完成的脚本。如果这是唯一的解决方案 - 罚款。但是我想知道是否有一种方法可以让用户免于额外的步骤并直接在我的宝石中包含完成。
那么:宝石有没有办法让自己的标签完成?
答案 0 :(得分:1)
在键入命令以启动脚本时,您的脚本尚未运行。当它们仍然被输入时,它不能干预它自己的参数的处理。如果可能,您可以让gem
文件安装bash完成文件并修改用户的~/.bashrc
文件,以便在安装过程中加载它们。
答案 1 :(得分:0)
看一下Ruby的Abbrev模块。 (About.com也有一些useful information。)
来自文档:
Calculate the set of unique abbreviations for a given set of strings. require 'abbrev' require 'pp' pp Abbrev::abbrev(['ruby', 'rules']).sort Generates: [["rub", "ruby"], ["ruby", "ruby"], ["rul", "rules"], ["rule", "rules"], ["rules", "rules"]] Also adds an abbrev method to class Array.
我读了目录,将文件和子目录传递给Abbrev,并将结果转换为哈希。观察用户类型。如果他们按 Tab ,看看他们输入的内容是否与哈希中的键匹配。如果确实如此,那么他们输入的内容就是唯一的,并且可以解析为该元素的值。
这是如何将Abbrev的输出转换为哈希:
irb(main):009:0> hash = Hash[%w[ruby rules].abbrev]
=> {"rub"=>"ruby", "rule"=>"rules", "rul"=>"rules", "ruby"=>"ruby", "rules"=>"rules"}
答案 2 :(得分:0)
虽然chepner已经得出正确的结论,即安装是不可避免的,但我建议看看其他一些项目是如何解决这个问题的。
Travis CI travis gem提供首次执行时安装完成。它将完成脚本保存到〜/ .travis / travis.sh ,然后将以下内容附加到 .bashrc :
# added by travis gem
[ -f ~/.travis/travis.sh ] && source ~/.travis/travis.sh
前面的例子有点侵入性。有关更自由放任的方法,请参阅Python的pip
(类似于Ruby&#39; s gem
)。它有一个隐藏的完成选项,可以将bash或zsh完成脚本输出到stdout。由用户决定如何获取它。
pip completion --bash
输出以下内容:
# pip bash completion start
_pip_completion()
{
COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \
COMP_CWORD=$COMP_CWORD \
PIP_AUTO_COMPLETE=1 $1 ) )
}
complete -o default -F _pip_completion pip
# pip bash completion end
在一个有点不同但相关的注释中...如果你看一下上面提到的完成脚本,你会注意到它做了一件非常奇怪的事情。它不是使用静态完成列表(必须经常更新并且容易出现不准确),也不是通过解析帮助消息动态生成完成(通常不可接受地慢),它使用第三个选项。它直接在pip
中传递命令行状态,以便生成完成。
也许最相关,但也是最宏伟的方法是为Ruby宝石创建一个全局完成脚本。用户只需要安装一个全局完成宝石(没有解决这个问题),然后完成任何其他宝石的立即可用。据我所知,没有人在Ruby中实现过这一点。有关Python实现,请参阅argcomplete。
安装如下:
pip install argcomplete
activate-global-python-argcomplete --dest=/path/to/bash_completion.d
脚本很容易适应。然后它基本上是一个单行程,将您的解析器对象传递给argcomplete。