【发布时间】:2009-10-07 02:49:59
【问题描述】:
我正在尝试在 tcsh 和/或 bash(两者都在我的站点上使用)中设置目录完成,但稍有改变:对于特定命令“foo”,我希望完成使用自定义函数将第一个 / 分隔的术语与实际的子树节点匹配,然后对任何后续术语遵循正常的目录完成。它是 cdpath 和完成的组合,或者我认为是目录完成的一种形式,其中起点由完成脚本控制。它的工作原理如下:
$ foo xxx<TAB>
(custom completion function produces choices it finds at arbitrary levels in the dir tree)
xxxYYY xxxZZZ xxxBLAH ...
foo xxxYYY/<TAB>
(normal directory completion proceeds from this point on, to produce something like:)
foo scene/shot/element/workspace/user/...
我们愿意这样做是因为我们有一个大型生产开发树(这是一个 CGI 生产设施),精通 shell 的用户一直在导航和跳转。抱怨是树的上层繁琐且多余;他们只需要快速搜索第一个术语即可找到可能的“头”选择并从那里完成目录完成。看起来可编程完成可以提供一种方法来做到这一点,但事实证明它非常难以捉摸。
我已经多次尝试自定义 bash 和 tcsh 补全来做到这一点,但我得到的最接近的是一种“单词补全”形式,用户必须将目录级别视为带有空格的单独单词(例如 foo场景/镜头/元素/工作区/ ...)。我可以继续修改我当前的脚本——但我一直想知道是否有一些我不理解的东西——这是我第一次尝试完成程序,并且在 shell 书籍和互联网上的文档和示例非常薄.如果有任何完成大师可以让我走上正轨,我将不胜感激。
FWIW:这是我到目前为止所得到的(首先是 tcsh,然后是 bash)。请注意,静态根 '/root/sub1/sub2/sub3' 只是搜索功能的占位符,它将在不同级别找到不同的匹配项。如果我能让它工作,我可以稍后加入搜索功能。同样,这两个示例都进行了单词补全,这要求用户在每个匹配项之后输入一个空格(我还必须删除函数中的空格来构造一个实际的路径,哎呀!)
TCSH 示例(注意该函数实际上是一个 bash 脚本):
complete complete_p2 'C@*@`./complete.p2.list.bash $:1 $:2 $:3 $:4 $:5 $:6 $:7 $:8 $:9`@@'
#!/bin/bash --norc
# complete.p2.list.bash - Completion prototype "p2" for shotc command
# Remove spaces from input arguments
ppath=`echo $@ | sed -e 's/ //g'`
# Print basenames (with trailing slashes) of matching dirs for completion
ls -1 -d /root/sub1/sub2/sub3/$ppath* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}'
BASH 示例:
_foo()
{
local cur prev opts flist
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Get all command words so far (omit command [0] element itself), remove spaces
terms=`echo ${COMP_WORDS[@]:1} | sed -e 's/ //g'`
# Get basenames (with trailing slashes) of matching dirs for completion
flist=`ls -1 -d /root/sub1/sub2/sub3/${terms}* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}' | xargs echo`
COMPREPLY=( $(compgen -W "${flist}" ${cur}) )
return 0
}
complete -F _foo foo
【问题讨论】:
-
bash 的 CDPATH 环境变量对你有用吗?
-
我查看了 CDPATH,但它无法完成。你可以“cd name”,但不能“cd name
...”我真的需要补全。 -
我认为 bash 补全(在大多数发行版上随 bash 一起提供的包含有用的额外脚本)包括使用 CDPATH 对 cd 补全的更新定义。
-
@Jefromi:你说得对,它似乎能够做我认为 Jeremy 想要做的事情。
-
感谢您的提示,我会检查一下。然而值得一提的是,我需要做的不仅仅是 cd;例如,即时设置特定于子树的环境。我正计划使用自定义命令,但也许我可以将 cd 别名为其他东西(不过这可能太侵入性了)。
标签: bash tcsh tab-completion bash-completion