2011-01-25 62 views
2

有一个命令行功能,我一直在想了很久,我已经想过如何最好地实现它,但是我什么都没......发现在bash脚本的基于文​​件名自动完成

所以我想有是当我开始输入一个文件名和打标签,例如:

# git add Foo<tab> 

我想它运行一个find . -name "*$1*"基本上自动完成对匹配文件的完整路径,以我的命令线。

我有什么至今:

我知道我得写,将调用应用程序与我想要的参数, 例如git add功能。之后,它需要捕捉tab-keystroke事件并执行上面提到的查找,并显示结果(如果有),或者填写结果(如果有)。

我一直无法弄清楚:

如何捕捉功能中的一个函数中的Tab键的事件。

所以基本上在伪代码:

gadd() {git add autocomplete_file_search($1)} 

autocomplete_file_search(keyword) { 
    if(tab-key-pressed){ 
    files = find . -name "*$1*"; 
    if(filecount > 1) { 
     show list; 
    } 
    if(files == 1) { 
     return files 
    } 
    } 
} 

任何想法?

谢谢。

回答

1

你应该看看这个introduction to bash completion。简而言之,bash有一个用于配置和扩展标签页完成的系统。其他炮弹也是这样做的,每个炮弹都有不同的设置方式。使用这个系统不需要自己做所有事情,并且为命令添加自定义参数完成相对容易。

+0

真棒。谢谢! – 2011-01-25 12:13:14

0

我写了git-number,这样我就不需要在指定文件到git时打印选项卡。

使用git-number我可以使用数字来表示我想要git处理的文件名。

0

这是行不通的吗?

$ cat .bash_completion 
_foo() 
{ 
    local files 
    cur=${COMP_WORDS[COMP_CWORD]} 
    local files=$(for x in `find -type f`; do echo ${x}; done) 
    COMPREPLY=($(compgen -W "${files}" -- ${cur})) 
    return 0 
} 
complete -F _foo foo 

$ . /etc/bash_completion 
$ foo ./[tab] 
2

匹配文件名中的任何地方相当复杂,我不确定它真的有用。匹配文件名的开始更有意义,并且更容易实现,即使是递归的。

现在,你提到查找作为一个需求,但bash(从版本4.0开始)也可以递归地查找文件,并且让bash执行该部分应该更高效。要在bash中递归匹配,请通过运行shopt -s globstar来启用globstar shell选项,然后连续两个星号**将递归匹配。

接下来,因为你想递归匹配的Git仓库里的文件,我们最好有一种方法来检测,我们在一个Git仓库实际上是,否则,如果你不小心触发它/例如,您提示符会在等待bash搜索整个文件系统时挂起。以下函数在确定我们是否在git存储库中时应该相当有效。鉴于当前的工作目录,例如/foo/bar/baz,它会查找/foo/bar/baz/.git,/foo/bar/.git,/foo/.git,/.git,如果找到一个则返回true,否则返回false。

isgit() { 
    local p=$PWD 
    while [[ $p ]]; do 
     [[ -d $p/.git ]] && return 
     p=${p%/*} 
    done 
    return 1 
} 

为了简单起见,我们将创建一个gadd命令添加完成为。完成功能只能应用于命令的第一个单词。例如。我们可以添加完成git,但不是git add,因此我们将创建一个新的命令,将git add变成一个单词。

gadd() { 
    git add "[email protected]" 
} 

现在为实际完成功能。当触击TAB时,该函数将被调用三个参数。 $1是正在完成的命令,$2是命令行正在完成的当前字,并且$3是上一行字。所以我们要搜索的文件将由glob **/"$2"*匹配;所有以"$2"开头的文件。我们遍历这些文件名,并将它们追加到COMPREPLY数组中。如果COMPREPLY数组只在函数完成时包含一个值,则该字将被该值替换。如果它包含多个值,则再次点击选项卡以获取所有匹配的列表。

shopt -s globstar 
_git_add_complete() { 
    local file 
    isgit || return 
    for file in **/"$2"*; do 
     # If the glob doesn't match, we'll get the glob itself, so make sure 
     # we have an existing file 
     [[ -e $file ]] || continue 

     # If it's a directory, add a trailing/
     [[ -d $file ]] && file+=/ 
     COMPREPLY+=("$file") 
    done 
} 
complete -F _git_add_complete gadd 

添加上述三个代码块你~/.bashrc,然后打开一个新的终端,进入一个Git仓库,并尝试gadd something<tab>

+0

问题是,我希望各种命令,编辑器,ls,git等在回购期间工作。 – chx 2012-08-19 13:00:06