我怎么能替换选项卡完成命令行参数? [英] How can I replace a command line argument with tab completion?

查看:105
本文介绍了我怎么能替换选项卡完成命令行参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道这是否可能在Bash中,但我想用tab完成,完全取代的正在扩大目前的说法。
 我举个例子:
我想有上移树级别的任意数量的功能,这样我就可以调用
    涨2
这将CD我2个目录了。
不过,我想使它所以,如果在2号,我preSS选项卡,将这一数字扩大到作为路径(相对或绝对的,要么是罚款)。
我有这样的工作几乎用它除了完整的内建只会追加文本,所以它会像
    高达2 /卷/开发/

是否有可能更换完毕符号?

在此先感谢:)

更新:

因此​​,一个大感谢chepner,因为实际上我检查code显露在我的错误了。我是比较反对错了var和调试code我有是导致价值所不能替代的。

有关任何有兴趣,这里的code(而且有可能是一个更好的方法来做到这一点):

 #移目录树的N级
#或者通过在该PWD一些迪尔打字
#如。假设你是PWD/卷/用户/ natecavanaugh /文件/东西
#`起来2`向上移动2目录/卷/用户/ natecavanaugh
#`涨2 /`和pressing标签将自动填充迪尔斯在/卷/用户/ natecavanaugh
#`高达Users`定位到/卷/用户
#`起来us`和pressing标签会自动填充到/卷/用户
运作起来{
    DIR =../
    如果[-n$ 1];然后
        如果[[$ 1 =〜^ [0-9] + $]];然后
            strPath的= $(printf的%$ {1}的);
            DIR =$ {// strPath中/ $ DIR}
        其他
            DIR = $ {PWD%/ $ 1 / *} / $ 1
        科幻
    科幻    CD $ DIR
}功能_get_up {
    当地CUR
    本地目录
    本地结果
    COM prePLY =()
    #变量来保存当前字
    CUR =$ {COMP_WORDS [COMP_CWORD]}    当地lower_cur =`回声$ {CUR ## * /} | TR [:上:] [:降低:]`    #是ARG后跟一个斜线号码或号码
    如果[[$ CUR =〜^ [0-9] + /? ]];然后
        DIR =../
        strPath的= $(printf的%$ {CUR %% / *} S);
        DIR =$ {// strPath中/ $ DIR}        #是ARG只是一个数字?
        如果[[$ CUR =〜^ [0-9] + $]];然后
            COM prePLY =($(compgen -W$ {DIR}))
        其他
            如果[[$ CUR =〜/.*$]];然后
                CUR =$ {CUR ## * /}
            科幻            结果= $(在`CD $目录和放大器吨;&安培; LS-D * /`;办[`回声$ T | T R [:上:] [:降低:]`==$ lower_cur* ]];然后回声$ {T】网络连接完成)            COM prePLY =($(compgen -P$目录-W$ {}结果))
        科幻
    其他
        #是ARG一个词,我们可以看看在PWD
        结果= $(在`$回声PWD T | TR/,\\ n';办[`回声$ T | T R [:上:] [:降低:]`==$ lower_cur* ]];然后回声$ {T】网络连接;完成)        COM prePLY =($(compgen -W$ {}结果))
    科幻
}#Assign我们的命令,在自动完成功能_get。
完成-F _get_up起来


解决方案

有可能用一个新词完全取代当前的单词。随着我的bash 4.2.29,我可以这样做:

  _xxx(){COM prePLY =(富); }
完成-F _xxx点¯x
X条形图#pressing选项卡打开此成X个富

您遇到的问题,但是,如果有多个可能的完成,并且希望得到普通preFIX的部分完成。然后我的实验表明,庆典将尝试可用的落成匹配您输入的preFIX。

所以一般:你可能只能替换的东西,如果有些事情是唯一定义完全不同的当前参数。否则,你应该产生符合当前preFIX这落成,让用户从这些选择。你的情况,你可以在 COM prePLY =($(compgen -P$目录-W$ {}结果))沿着这些东西取代行:

 本地IFS = $'\\ n'
COM prePLY =($(发现$ {DIR}-maxdepth 1型Ð-iname$ {#CUR * /} *-printf%P \\ N))
如果[[$ {#COM prePLY [@]} -eq 1];然后
    COM prePLY =($ {DIR} $ {COM prePLY [0]})
科幻

然而,在这种特殊情况下可能会更好仅通过相应的路径替换preFIX位,并保留一切为默认的bash补全:

  _up_ preFIX(){
    本地目录CUR =$ {COMP_WORDS [COMP_CWORD]}
    COM prePLY =()    如果[[$ {} CUR =〜^ [0-9] + /? ]];然后
        #以数字开始,后面有一个斜杠
        DIR = $(printf的%$ {CUR %% / *} S);
        DIR =$ {DIR // /../}
        如果[[$ {} CUR == * / *];然后
            DIR =$ {DIR} $ {#CUR * /}
        科幻
        COM prePLY =($ {DIR}$ {DIR})#黑客用晚餐preSS尾随空间
    ELIF [[$ {} CUR = * / *]!]然后
        #不是一个数字,或者没有斜线,所以搜索的父目录
        COM prePLY =($(IFS ='/'; compgen -W$ {密码}$ {} CUR))
        如果[[$ {#COM prePLY [@]} -eq 1];然后
            DIR =$ {PWD%$ {COM prePLY [0]} / *} $ {COM prePLY [0]} /
            COM prePLY =($ {DIR}$ {DIR})#如上破解
        科幻
    科幻
}完成-F _up_ preFIX -o dirnames中了

在code变得容易了很多阅读和维护,以及更有效的引导。唯一的缺点是,在某些情况下比你用你不得不preSS标签一次:第一次来替代preFIX,并两次以实际看到可能的补全列表。您的选择不管是可以接受的。

一件事:完成将会把参数转化为常规路径,但你的了功能,因为它是不接受的。因此,也许如果存在的话,你应该开始以 [-d $ 1]] 检查功能,只需要更改到该目录。否则,你的完成将产生论据是不能接受的调用的函数。

I'm wondering if this is possible in Bash, but I'd like to use tab completion to completely replace the current argument that's being expanded. I'll give an example: I'd like to have a function that moves up an arbitrary number of levels in the tree, so I can call up 2 And that would cd me 2 directories up. However, I would like to make it so that if at the number 2, I press tab, it will expand that number to being the path (either relative or absolute, either is fine). I have this almost working using the complete builtin except it will only append the text, so it will be something like up 2/Volumes/Dev/

Is it possible to replace the completed symbol?

Thanks in advance :)

Update:

So a big thanks to chepner, because actually checking my code revealed where my bug was. I was comparing against the wrong var, and the debug code I had was causing the value to not replace.

For anyone interested, here's the code (and there could be a much better way to accomplish this):

# Move up N levels of the directory tree
# Or by typing in some dir in the PWD
# eg. Assuming your PWD is "/Volumes/Users/natecavanaugh/Documents/stuff"
#     `up 2` moves up 2 directories to "/Volumes/Users/natecavanaugh"
#     `up 2/` and pressing tab will autocomplete the dirs in "/Volumes/Users/natecavanaugh"
#     `up Users` navigate to "/Volumes/Users"
#     `up us` and pressing tab will autocomplete to "/Volumes/Users"
function up {
    dir="../"
    if [ -n "$1" ]; then
        if [[ $1 =~ ^[0-9]+$ ]]; then
            strpath=$( printf "%${1}s" );
            dir=" ${strpath// /$dir}"
        else
            dir=${PWD%/$1/*}/$1
        fi
    fi

    cd $dir
}

function _get_up {
    local cur
    local dir
    local results
    COMPREPLY=()
    #Variable to hold the current word
    cur="${COMP_WORDS[COMP_CWORD]}"

    local lower_cur=`echo ${cur##*/} | tr [:upper:] [:lower:]`

    # Is the arg a number or number followed by a slash
    if [[ $cur =~ ^[0-9]+/? ]]; then
        dir="../"
        strpath=$( printf "%${cur%%/*}s" );
        dir=" ${strpath// /$dir}"

        # Is the arg just a number?
        if [[ $cur =~ ^[0-9]+$ ]]; then
            COMPREPLY=($(compgen -W "${dir}"))
        else
            if [[ $cur =~ /.*$ ]]; then
                cur="${cur##*/}"
            fi

            results=$(for t in `cd $dir && ls -d */`; do if [[ `echo $t | tr [:upper:] [:lower:]` == "$lower_cur"* ]]; then echo "${t}"; fi done)

            COMPREPLY=($(compgen -P "$dir" -W "${results}"))
        fi
    else
        # Is the arg a word that we can look for in the PWD
        results=$(for t in `echo $PWD | tr "/" "\n"`; do if [[ `echo $t | tr [:upper:] [:lower:]` == "$lower_cur"* ]]; then echo "${t}"; fi; done)

        COMPREPLY=($(compgen -W "${results}"))
    fi  
}

#Assign the auto-completion function _get for our command get.
complete -F _get_up up

解决方案

It is possible to completely replace the current word with a single new word. With my bash 4.2.29, I can do this:

_xxx() { COMPREPLY=( foo ); }
complete -F _xxx x
x bar # pressing tab turns this into x foo

You encounter problems, however, if there is more than one possible completion, and you want to get partial completion of the common prefix. Then my experiments indicate that bash will try to match the available completions to the prefix you entered.

So in general you should probably only replace the current argument with something completely different if that something is uniquely defined. Otherwise, you should generate completions which match the current prefix, to have the user select from those. In your case you could replace the COMPREPLY=($(compgen -P "$dir" -W "${results}")) with something along these lines:

local IFS=$'\n'
COMPREPLY=( $(find "${dir}" -maxdepth 1 -type d -iname "${cur#*/}*" -printf "%P\n") )
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
    COMPREPLY=( "${dir}${COMPREPLY[0]}" )
fi

However, in this specific case it might be better to only replace the prefix digit by the appropriate path, and leave everything else to the default bash completion:

_up_prefix() {
    local dir cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=()

    if [[ ${cur} =~ ^[0-9]+/? ]]; then
        # Starting with a number, possibly followed by a slash
        dir=$( printf "%${cur%%/*}s" );
        dir="${dir// /../}"
        if [[ ${cur} == */* ]]; then
            dir="${dir}${cur#*/}"
        fi
        COMPREPLY=( "${dir}" "${dir}." ) # hack to suppress trailing space
    elif [[ ${cur} != */* ]]; then
        # Not a digit, and no slash either, so search parent directories
        COMPREPLY=( $(IFS='/'; compgen -W "${PWD}" "${cur}") )
        if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
            dir="${PWD%${COMPREPLY[0]}/*}${COMPREPLY[0]}/"
            COMPREPLY=( "${dir}" "${dir}." ) # hack as above
        fi
    fi
}

complete -F _up_prefix -o dirnames up

The code becomes a lot easier to read and maintain, plus more efficient to boot. The only drawback is that in some cases you'd have to press tab one more time than you used to: once to substitute the prefix, and twice more to actually see the list of possible completions. Your choice whether that's acceptable.

One more thing: the completion will turn the argument into a regular path, but your up function as it is does not accept those. So perhaps you should start that function with a [[ -d $1 ]] check, and simply cd to that directory if it exists. Otherwise your completion will generate arguments which are unacceptable to the called function.

这篇关于我怎么能替换选项卡完成命令行参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆