ラッパー関数の引数と既存のコマンドのzshオートコンプリートを組み合わせる方法


40

私は主にgvimと多くの端末で働いています。もともと、すべてのファイルを単一のvimインスタンスで開くことを好みました。そのために、エイリアスを使用して、現在の「vimサーバー」の端末からファイルを開きました。

alias rv="gvim --remote-silent"

しかし、1つのvimインスタンスで複数のプロジェクトから多くのファイルを開くと、生産性に影響するため、エイリアスを関数にアップグレードしています。

# main function
rv() {
    local args options server

    options=$(getopt -o hils:t: -l "help,info,list,set:,target:" -- "$@")

    if [[ $? -ne 0 ]]; then
        echo "Failed to parse options."
        return 1
    fi

    # a little magic, necessary when using getopt
    eval set -- "$options"

    # go through the options with a case and use shift to analyze one option at a time.
    while true; do
        case "$1" in
            -h|--help)
                echo "Usage: $0 [-hil] [--help] [--info] [--list]";
                echo "       $0 {-s | --set} <name> [<file1 file2...>]";
                echo "       $0 {-t | --target} <name>] <file1 file2...>";
                return 0;;
            -i|--info)
                gvim_show_info;
                return 0;;
            -l|--list)
                gvim_list_servers;
                return 0;;
            -s|--set)
                gvim_set_server_name ${2:u};
                shift 2;;
            -t|--target)
                server="$2";
                shift 2;;
            --)
                shift;
                break;;
        esac
    done

    if [[ "$#" -eq 0 ]]; then
        # if no files specified...
        if [[ -n "$server" ]]; then
            # throw error if --target option was specified.
            echo "Error!  --target requires one or more filenames."
            return 1;
        fi
    else
        # if files were specified...
        if [[ -n "$server" ]]; then
            # if --target was specified
            gvim_run_remote $server "$@"
        else
            gvim_run_remote $(gvim_get_default_server) "$@"
        fi
    fi

    return 0;
}

今、この新しいにrvは独自のオプションがあります。私はそれを使用することができます:

  • 使用可能なvimサーバーをリストします(-l --list)
  • 現在のシェルにデフォルトのvimサーバーを設定します(-s --set)
  • デフォルトのvimサーバーを表示します(-i --info)
  • 特定のvimサーバーでファイルを開く(-t --target)
  • デフォルトのvimサーバーでファイルを開く: rv files...

ただし、rvエイリアスの代わりに関数を使用しているため、以前は楽しんでいたzsh補完が失われます。のオプション_rvを表示する補完関数の作成について説明しましたrvが、補完オプションを既存のvim補完オプションと組み合わせたいと思います。私はといくつかの競合があるかもしれません知っているrv-svim-s、しかし私は私がエレガントなものを扱うことができる把握--セパレーター。

TLDR; だから、どのように私は、組み合わせて完成スクリプト作成できますか_arguments両方のオプションを_rvして_vim_vim引数リストをにコピー&ペーストする代わりに、可能であれば再利用することを好み_rvます。

ここに私のです_rv2014/6/10 16:10に更新

#compdef rv

_rv() {
    typeset -A opt_args
    local alternatives

    alternatives=(
        'args:rv options:_rv_options'
        'files:file:_vim_files'
    )

    _alternative $alternatives && return 0

    return 1
}

_rv_options() {
    local arguments

    arguments=(
        '(-i -l -s -t --info --list --set --target)'{-h,--help}'[Print usage info.]'
        '(-h -l -s -t --help --list --set --target)'{-i,--info}'[Print default vim server. As stored in $GVIM_SERVER.]'
        '(-i -h -s -t --info --help --set --target)'{-l,--list}'[Print list of existing vim servers.]'
        '(-i -h -l -t --info --help --list --target)'{-s,--set}'[Set default vim server for the current shell.]:vim servers:_rv_vim_servers'
        '(-i -h -l -s --info --help --list --set)'{-t,--target}'[Open files in a particular vim server.]:vim servers:_rv_vim_servers'
        )

    _arguments -s -C $arguments && return 0

    return 1
}

_rv_vim_servers() {
    local -a servers
    servers=( ${(f)"$(_call_program servers vim --serverlist 2>/dev/null)"} )
    _wanted servers expl server compadd -M 'm:{a-z}={A-Z}' -a servers && return
}

# invoke the completion command during autoload
_rv "$@"

現在の動作

現在、_rv完了は使用可能ですが、理想的ではありません。

  • と入力するとrv <TAB>、vimオプションが表示されません。rvオプションとファイルパスのみが表示されます。 _vim私のためにファイルパスを完成しています。
  • を入力するとrv -s <TAB>、vimサーバーのリストが表示されますが、ファイルパスも表示されます。ファイルはコマンドのこの時点では許可されていないため、オートコンプリートには表示されません。

予想される行動

  • と入力するとrv <TAB>、1)rvオプション、2)vimオプション、3)ファイルパスリストが表示されます。
  • 私が入力するとrv -s <TAB>、私が見ることを期待:1)VIMサーバ名を(によって提供されます_rv_vim_servers
  • と入力rv /valid/file/path/<TAB>すると、ファイルパスリストのみが表示されます。_vimすでにこの機能を持っているので、私はそれに頼ることを好むでしょう。

1
このunix.stackexchange.com/questions/128199/…は役立つ可能性があります。
クロブラノ

1
compdef-n「コマンドまたはコンテキストにすでに定義されている補完が上書きされるのを防ぐ」というオプションがあります。それで、compdef _vim rv続いてみましたcompdev -n _rv rvか?
Lqueryvg

3
28の賛成票と無回答...それはzshについての質問です...私はあなたのために@StéphaneChazelasを呼び出そうとします^^(私はこれを乱用しないようにしていますが、楽しいです。これを行う...と私はここで誰かが答えを知っている可能性がある場合は、それが彼をする必要があります...)これを削除し、再びそれを行うことは決してないだろう
オリヴィエ・デュラック

1
@OlivierDulac既にスレッドに投稿している場合にのみ通知を受け取ると思います。(重複する名前が許可されているため、これは理にかなっています。)チャットで彼を見つけることもできます。
スパルホーク

元の_vim ファイルを入手することは可能ですが、そうする前に_arguments関数をカスタムローカル関数で上書きしますか?そうすることで、から引数を取得できます_vim。たぶん、別のzshプロセスで。
ラファエルアーレンス

回答:


1

私は/ usr / share / zsh / functions / Completion / Unix / _gitを見つけました。これには、このようなエイリアスに関するヒントがあり、エイリアスに対してこれらの関数を定義することになりました。

_git-ls () {
  # Just return the _git-ls-files autocomplete function
  _git-ls-files
}

次に、まっすぐなcompdef g = gitを実行します。オートコンプリートシステムは、たとえばg lsを実行していることを確認し、_git-lsオートコンプリート機能を使用します。

などが見つかりました。ここで


感謝しますが、そうではありません。あなたのソリューションは、からのオートコンプリートのみが必要だと想定しています_git-ls-files。この質問にはgit-ls独自のオプションがあり(慣習に準拠するため)、これらのオプションの一部はと重複していgit-ls-filesます。のすべてのオプションのgit-lsオートコンプリートを記述する代わりに、オートコンプリートを取得して_git-ls-files(たとえば90%をカバー)、残りのオプション(たとえば10%)のオートコンプリートと組み合わせるオートコンプリートを作成するにはどうすればよいですか?
ジャスティンC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.