他のディレクトリに完全に関連するコマンドの完了

他のディレクトリに完全に関連するコマンドの完了

別のカテゴリで単一のコマンドを実行する機能があります。cd1 SOMEDIR MYCOMMAND ARG…同様に(cd SOMEDIR && MYCOMMAND ARG…)、2つの利点があります。入力が少し簡単で(コマンドライン中毒者の場合は、すべてのキーストロークが重要です)(ほとんど)SOMEDIR

つまり、完成関数を定義できますcd1親戚の完成をどのように準備できますかSOMEDIR

以下は変更しないと機能しません。

  • _filesここでは、コマンドパラメータの変更されたパラメータを使用して一時呼び出しを実行することはお勧めできません。そこ)一般的な状況に合った完成をすべて適用したいからです。
  • (cd $words[2] && shift 2 words && ((CURRENT-=2)) && _normal)完成がサブシェルで動作する場合、正しいことをしますが、そうではありません。
  • cd $words[2] && shift 2 words && ((CURRENT-=2)) && _normal; cd $OLDPWD通常の状況では機能しますが、+キャンセルをSOMEDIR押すと、完了するのに長い時間がかかるように、特定の状況では中断され、緊張しなくなります。CtrlC

これがの定義ですcd1。ターゲットディレクトリのエイリアスと拡張ワイルドカードをサポートします(一方、コマンドの置き換えなどは元のディレクトリで引き続き実行されます)。

cd1_glob () {
  if (($# <= 1)); then
    cd -- "$1"
  elif (($+aliases[$2])); then
    ( cd -- $1 && eval $2 '$~@[3,$#]' )
  else
    ( cd -- $1 && $~@[2,$#] )
  fi
}
alias cd1='noglob cd1_glob'

(私はこの関数を呼び出しません。呼び出す場合は、cd関数の内部呼び出しをに変更してください。)cdbuiltin cd

答え1

これが私が今まで持っているものです。完璧ではありませんが、次のようになります。

  • ターゲットディレクトリに基づいて完了しました。
  • 宛先ディレクトリがない場合、自動エラーが発生します。
  • スキップしてchpwd復元chpwd_functionsするのが正しいと思います。
  • キャンセルが完了すると、現在のディレクトリが復元されます。

複雑で脆弱に見えるので、極端なケースにはまったく自分がいません。既知の問題:

  • 補完が常にサフィックス文字(スペースやディレクトリなど)を追加するわけではありません/。たとえば、挿入のみを挿入cd1 / echo /biTabします(挿入は)。n/cd1 / echo biTabnecho biTabn/
  • 操作の完了中に元のディレクトリの名前が変更されると、シェルは新しい名前の古いディレクトリの代わりに古い名前の新しいディレクトリに戻ります。
#compdef cd1 cd1_glob
# cd for one command

_cd1_in () {
  setopt local_options local_traps
  # Cleanup:
  # * Restore the old directory. We do this only if cd succeeded beause
  #   the restoration can do the wrong thing in corner cases (renamed
  #   directory).
  # * Restore the chpwd hook function and the hook array.
  trap 'if ((_cd1_cd_succeeded)); then cd $OLDPWD; fi
        if [[ -n $_cd1_chpwd_function ]]; then
          functions[chpwd]=$_cd1_chpwd_function
        fi
       ' EXIT INT
  builtin cd $words[2] 2>/dev/null || { _cd1_cd_succeeded=0; return 1; }
  shift 2 words; ((CURRENT -= 2))
  _normal
}

_cd1 () {
  if ((CURRENT > 2)); then
    setopt local_options no_auto_pushd unset
    local _cd1_cd_succeeded=1
    # Save the current directory and the chpwd hook. They will be restored
    # by the exit trap in _cd1_in.
    local _cd1_chpwd_function=$functions[chpwd]
    # Save the current directory in $OLDPWD. _cd_in will call cd, which would
    # generally call cd
    local OLDPWD=$PWD
    # Turn off the chpwd hook function and the associated hook array.
    local chpwd_functions=
    unset -f chpwd 2>/dev/null
    # Call a separate function to do the work. Its exit trap will take care
    # of cleanup. The reason to have a separate function is so that the
    # local variables defined here can be used in the exit trap.
    _cd1_in
  else
    _dirs
  fi
}

_cd1 "$@"

関連情報