代码审查:bash 别名的自动完成

代码审查:bash 别名的自动完成

我正在读书如何获得命令别名的 bash 补全?我想,Shawn J. Goff 的答案需要一些东西:减少用户设置,所以我编写了一个小脚本,旨在从您的 中获取.bashrc,但它不太有效,所以希望有人能发现我的错误。

function make-completion-wrapper-1 () {
    local function_name="$2"
    local arg_count=$(($#-3))
    local comp_function_name="$(complete -pr $1|sed -e 's/^\(.* -F \)\([^ ]*\) [^ ]*$/\2/')"
    shift 2
    local function="
        function $function_name {
            ((COMP_CWORD+=$arg_count))
            COMP_WORDS=( "$@" \${COMP_WORDS[@]:1} )
            "$comp_function_name"
            return 0
        }"
    echo "$function"
    eval "$function"
}

function make-completion-wrapper-2 () {
    local function_name="$1"
    local alias_name="$2"
    local comp_function_base="$(complete -pr $3|sed -e 's/^\(.* -F\)\( [^ ]*\) [^ ]*$/\1/')"
    echo "$comp_function_base $function_name $alias_name"
    eval "$comp_function_base $function_name $alias_name"
}

[ -e ~/.cache/bash_alias_complete ] && rm ~/.cache/bash_alias_complete

alias | \
    sed \
        -e 's/^alias //' \
        -e '/^\([^=]\+\)='\''\1 /d' \
        -e "/'.*=/d" -e '/\$/d' \
        -e h \
        -e "s/.*='\([^ ]*\)\( .*\)'$/\1! \1\2/" \
        -e 'y/ -!/__ /' -eG -e 's!\n[^=]*='\''\(.*\)'\''! \1!' \
        -e 's/^/make-completion-wrapper-1 /p' \
        -e 's/^[^ ]* [^ ]* \([^ ]*\) .*$/\1/' \
        -e x \
        -e 's!='\''\([^ ]*\) .*$! \1!' \
        -e x \
        -e 's!^!make-completion-wrapper-2 !' \
        -e G \
        -e 'y/\n/ /' \
    > ~/.cache/bash_alias_complete

. ~/.cache/bash_alias_complete

当我按下该键时,出现以下错误Tab

bash: COMP_POINT - : syntax error: operand expected (error token is "- ")

笔记:上面的代码可以放置在一个文件中,例如myfuncs.bash,然后可以直接在 shell 中获取该代码或从$HOME/.bashrc.

有关此代码的完整更改历史记录,请参阅https://github.com/hildred/scripts.git

答案1

错误消息 COMP_POINT 来自Bash 参考手册:

COMP_POINT

当前光标位置相对于当前命令开头的索引。如果当前光标位置位于当前命令的末尾,则该变量的值等于${#COMP_LINE}。此变量仅在 shell 函数和由可编程完成工具调用的外部命令中可用(请参阅可编程完成)。

尝试一下这个

我尝试按原样使用您的代码。当采购直到最后一行的所有内容时效果都很好。当该行运行时,. ~/.cache/bash_alias_complete我收到错误。太多了,无法包含在这里。

将结果生成到文件中似乎存在一些问题~/.cache/bash_alias_complete

我遇到的错误

我有以下别名:

$ alias|grep cdc
alias cdl='cdctl -o1'
alias cdu='cdctl -o0'

您的sed命令允许其通过,然后传播到我的缓存文件,导致这些命令导致以下错误:

$ make-completion-wrapper-1 cdctl _cdctl__o1 cdctl -o1
$ make-completion-wrapper-2 _cdctl__o1 cdl cdctl
$ make-completion-wrapper-1 cdctl _cdctl__o0 cdctl -o0
$ make-completion-wrapper-2 _cdctl__o0 cdu cdctl
bash: complete: cdctl: no completion specification
 _cdctl__o1 cdl

还有其他示例,但要点是命令sed并不像可能需要的那么严格,这最终是您遇到的问题。

相关内容