是否可以配置bash完成目录名称的方式?


8

我想指示bash使用特殊方法对某些目录名称执行补全。例如,如果路径以“ $$”开头,bash会调用我的程序来执行完成,否则将正常执行。

这是可能吗?您将如何实施?

赏金:非常感谢您回答该问题。目的是允许用户在使用特定前缀启动命令时自动跳转以完成所有命令的路径。因此,例如,当从远目录复制文件时,可以键入:

cp $$patern + <Tab>

和自动跳转将完成

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

并且您只需要添加要放置文件的位置即可。当然,我可以使用ott的注释将其添加到一些特定的命令中,但是如果有人有更好的主意,我将不胜感激。


请参见bash手册页中的“可编程完成”部分。

如果您投票解决我的问题,请解释原因。
珀尔帖

2
“ complete”支持“ -G模式”来匹配您的$$和“ -F func”来调用您自己的函数,但是它需要一个或多个命令名称才能起作用。

为什么不只使用环境变量?例如:cp $ prefix / file / path / to / dest /
Xenoactive 2011年

@Xenoactive:因为自动跳转是完全自动化的,并且可以在多个路径上运行。使用手动设置的环境变量没有帮助。也许您有一个我不明白的好主意?
珀尔帖

Answers:


3

您可以通过重写TAB(^ i)的默认绑定来实现。首先,您需要覆盖TAB绑定,然后需要构建一个调用命令的函数,最后,需要从该命令中获取输出并更新包含当前命令行的变量。

此函数采用当前命令行并将最后两个字符更改为“拥抱”。

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

对于您的示例,您可能希望将new_argument行更改为如下所示:

  new_argument=$(autojump $argument)

现在覆盖^ i绑定:

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

现在测试它是否有效:

$ cd /ro<TAB>
changes my command to:
$ cd /root

因此正常完成仍然有效,您可以通过执行cd $$ ...等来测试$$部分

如果遇到问题,请打开详细模式:

$ set -x

它将打印出该功能正在执行的所有操作。

我在Ubuntu 11上使用bash 4.2.8(1)-release(默认)对此进行了测试。


在我看来,这仅适用于该命令的第一个参数,也可以做怪异的东西,如果该选项卡以意想不到的方式使用(例如命令名称后$$$或之后),还是我错了?
harrymc 2011年

好吧,它传递了$ *,因此它不仅可以在第一个参数上工作(我完全不知道自动跳转,所以我不确定是否可以接受多个参数)。您可以移至末尾,仅将最后一个发送给自动跳转,或者使用READLINE_POINT确定光标在命令参数中的位置,并且也仅发送该“字”以自动跳转。
多项式

您的解决方案很有趣,但是您必须承认接管Tab键有点极端。您不可能预见所有可能的情况。
harrymc

感谢您的回答,这是一个不错的替代解决方案,它确实解决了我的问题的“对于所有命令”部分。我同意harrymc的观点,不过这有点极端。我想如果没有人提出更好的解决方案,我将尝试一下,看看它是否可行。
珀尔帖

是的,我也同意harrymc的观点,但是我试图按照要求回答这个问题。就我个人而言,我只是将其绑定到另一个控制键,例如^ G之类的东西,这样我可以不理会选项卡,但仍然使用此功能。
多项式

1

bash完成例程可以编程为shell脚本。

这里是一个shell脚本,将在任何参数替换的例子$$[Tab]通过my replacement string,但只适用于特定的命令mycommand且仅当参数是完全“$$”:

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

您必须通过source <file-name>(或dot命令)将脚本源化为bash 才能开始运行,然后:

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

为了始终让它对某些或所有用户都有效,请将其包括在bash配置文件例程之一中

complete命令的问题在于,它仅适用于指定为参数的一个或多个命令名称。只需给它列出用户可能使用的所有命令的列表,或者在绝望的情况下进行扩展/bin/* /usr/bin/* ~/bin/*

在CentOS 5.5上测试。

这个简单的脚本基于我在其他答案中列出的来源-该内容已由主持人studiohack删除。如果有兴趣,请让他取消删除。


感谢您的回答。我的问题不是真的,因为我有新的可能,但是不会完成所有命令。但是我认为,如果多项式的解决方案不被接受,我将实现类似的方法并尝试针对最常见的命令。
珀尔帖
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.