修正する:

修正する:

以下が必要なカスタムスクリプトがあります。

  1. 短い/長い形式のオプションパラメータ
  2. 必須コマンドライン引数

次の短い/長いコマンドラインオプション:

-r, --readonly
-m, --mount

必須パラメーターの場合、パラメーターは実際にはスクリプト内のCaseステートメントとして指定されます。つまり、この例fooでは次のようになります。bar

case $1 in
  foo )
  :
  ;;

  bar )
  :
  ;;

zsh completion次のパラメータが開始されたときにオプションのパラメータが完了するようにスクリプトを生成し、スクリプトケースの説明から必須パラメータを-取得するにはどうすればよいですか。

修正する:

答えからインスピレーションを受け、これまでに得た内容は次のとおりです@Marlon Richert

myscript.sh私のカスタムスクリプトが呼び出され、私が作成した完了ルールが次の場所にあるとしましょう/usr/share/zsh/functions/Completion/Unix/_myscript.sh

#compdef myscript.sh

_myscript () {
  local -a args

  args+=(
    {-r,--readonly}'[description for "readonly"]' 
    {-m,--mount}'[description for "mount"]' 
  )

  _arguments $args && return
}

_myscript "$@"

私のスクリプトmyscript.sh自体は/usr/local/bin/myscript.sh

オプションのパラメータがあり、それを処理するときに、-rスクリプトに必要なコマンドラインパラメータに対してCaseステートメントのエントリが完全に提供されるように、完了ルールを変更する必要が-mあります。/usr/local/bin/myscript.sh

args+=(また、スクリプトの6行目で始まるブロックを完成する構文が正しいかどうかわかりません。一重引用符はどこに入れるべきですか?

答え1

完成を定義したい関数が呼び出されたとしますmyfunc

まず、実際の機能を設定してみましょう。

  1. myfunc.notesというファイルに関数を配置します。
    • .zshこれはまたはで終わりません.sh
    • 関数を独自のファイルに配置するときに定型句を追加する必要はありませんfuncname() {…}
  2. ファイルが含まれているディレクトリがmyfuncあることを確認してください$fpath。たとえば、ファイルがmyfuncある場合は、ファイル~/Functionsに以下を追加します~/.zshrc
    fpath+=( ~/Functions )
    
  3. 最後にmyfuncファイルに自動ロードします~/.zshrc
    # We pass a couple of options that make the code 
    # less likely to break:
    # -U suppresses alias expansion
    # -z marks the function for zsh-style autoloading == 
    #    `unsetopt KSH_AUTOLOAD`
    autoload -Uz myfunc
    

myfuncこれで、コマンドラインで使用できます(まだ何も実行されていません)。

次に、完成関数を作成しましょう。

  1. というファイルを作成します_myfunc
  2. このファイルを入れてください:
    #compdef myfunc
    
    # The line above means "This function generates 
    # completions for myfunc."
    # The combination of that line, plus the file name
    # starting with an `_`, plus having this file's 
    # parent dir in your `$fpath`, ensures this file 
    # will be autoloaded when you call `compinit`.
    
    # `+X` makes sure `myfunc`'s definition will get 
    # loaded immediately, even if you have not called 
    # this function yet.
    autoload +X -Uz myfunc
    
    # Get the definition of `myfunc` in string form.
    local funcdef="$( type -f myfunc )"
    
    # Get the part that matches `case*esac`, then split
    # it on whitespace and put the resulting words in an 
    # array.
    local -a words=( ${=funcdef[(r)case,(r)esac]} )
    
    # Keep only the words that start with `(` and end 
    # with `)`.
    # Even if you used the `case` syntax with only the 
    # closing `)`s, `type -f` will show your cases with
    # both `(` and `)`.
    local -a required=( ${(M)words:#'('*')'} )
    
    # `-s`: Allow options to `myfunc ` to be stacked, 
    # that is, you are allowed to specify `myfunc -rm`.
    # If not, remove the `-s` option.
    # `*:`: Let this argument be completed in any 
    # position.
    _arguments -s \
        {-r,--readonly}'[description for "readonly"]' \
        {-m,--mount}'[description for "mount"]' \
        "*:required argument:( ${required//[()]/}  )"
    
    • required argument呼び出すパラメータに置き換えます。
    • オプションの説明を入力します。
  3. もう一度、ファイルがあるディレクトリが$fpath
  4. これをautoload -Uz compinit; compinit実行して実行されていることを確認してください。.zshrc後ろに上記のディレクトリがに追加されました$fpath
  5. シェルを再起動するexec zshか、ターミナルウィンドウを閉じて新しいウィンドウを開きます。

これで完了できますmyfunc


readonlyが相互に排他的である場合は、mount次のように完成関数の最後の行を再構築する必要があります。

_arguments \
    (-m --mount){-r,--readonly}'[description for "readonly"]' \
    (-r --readonly){-m,--mount}'[description for "mount"]' \
    "*:required argument:( ${required//[()]/}  )"

関連情報