bash / zshフック - 一致するファイルが見つからない場合にのみPATHに追加する

bash / zshフック - 一致するファイルが見つからない場合にのみPATHに追加する

bash / zshを探しています。フック、コマンドが見つからない場合に呼び出されます。

ランダムな実行ファイルを実行するとしましょう。

xyz foo --bar
  1. bash / zshが実行可能ファイルを見つけることができないと言います。
  2. 「見つかりません」を処理し、いくつかのライブラリをPATHに動的にロードする方法はありますか?

このような:

function xyz {
  if ! test -f xyz; then
     load_libs xyz
  fi
  command -v xyz;
}

この関数に似ていますが、不明な実行可能ファイルで動作します。

したがって、通常は次のようになります。

function on_not_found {
  if ! test -f "$1"; then
     load_libs "$1"
  fi
  command -v "$@";
}

答え1

どちらにも、コマンドが見つからない状況を処理するzshために定義できるフック機能があります。bashそれはcommand_not_found_handleinbashcommand_not_found_handlerin zshからインスピレーションを得ましbashたが、誤字/誤った名称が修正されました。)。

ただし、子プロセスで実行されるため(サブシェルがコマンドを見つけることができない可能性があることは言うまでもありません)、シェル環境を変更することはできません。

次のことができます。

扱いにくい

command_not_found_handler() {
  {
    if (( ! IN_CNFH++)) && load_lib "$1"; then
      "$@"
    else
      print -ru2 -- "$functrace[1]: command not found: $1"
      return 127
    fi
  } always {
    (( IN_CNFH-- ))
  }
}

IN_CNFH成功後もコマンドが見つからない場合は、無限再帰部分を避けてくださいload_lib

すでに1つがある場合command_not_found_handler(一部のシステムは、コマンドが見つからない場合はインストールするパッケージ名を提案するためにzshのデフォルト構成に1つを提供します)、前に次の内容を挿入できます。

functions[command_not_found_handler]='
  {
    if (( ! IN_CNFH++)) && load_lib "$1"; then
      "$@"
      return
    fi
  } always {
    (( IN_CNFH-- ))
  }
  '$functions[command_not_found_handler]

強く打つ

Bashの対応する項目は次のとおりです。

command_not_found_handle() {
  local ret
  if (( ! IN_CNFH++)) && load_lib "$1"; then
    "$@"
    ret=$?
  else
    printf >&2 '%s\n' "$BASH_ARGV0: $1: command not found: $1"
    ret=127
  fi
  (( IN_CNFH-- ))
  return "$ret"
}

またはすでに存在する場合は、増分変形command_not_found_handle

eval 'command_not_found_handle() {
  local ret
  if (( ! IN_CNFH++)) && load_lib "$1"; then
    "$@"
    ret=$?
    (( IN_CNFH-- ))
    return "$ret"
  fi
  (( IN_CNFH-- ))
  '"$(typeset -f command_not_found_handle | tail -n +2)"'
}'

関連情報