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

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

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

这有可能吗?您将如何实现它?

赏金:我非常希望得到这个问题的答案。目标是允许自动跳转当用户使用特定前缀启动所有命令时,完成所有命令的路径。例如,当从远端目录复制文件时,您可以输入:

cp $$patern + <Tab>

自动跳跃将会完成

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

您只需添加要放置文件的位置。当然,我可以使用 ott 的注释将其添加到几个特定命令中,但如果有人有更好的想法,我将不胜感激。

答案1

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

此函数获取当前命令行并将最后两个字符更改为“huugs”。

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

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

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

答案2

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

您必须通过(或点命令)将脚本输入到 bashsource <file-name>以使其开始工作,然后:

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 删除的来源。如果感兴趣,请让他恢复删除。

相关内容