Tech Nuggets (15) In English

fish_command_not_found

Posted:

fish 3.2.0 から導入された新しい組み込みコマンド fish_command_not_found を上書きし、パッケージマネージャへの問い合わせをさせないようした。

以下の環境での作業記録を備忘も兼ねて残しておく。

$ uname -srmo
Linux 5.11.9-arch1-1 x86_64 GNU/Linux

$ fish --version
fish, version 3.2.1

発覚の経緯 + 調査

PATH の通っていないコマンドや、そもそもインストールしていないコマンドを呼び出した際、以下のように表示されるようになった。

$ FBReader
fish: Unknown command: FBReader
warning: database file for 'core' does not exist (use '-Fy' to download)
warning: database file for 'extra' does not exist (use '-Fy' to download)
warning: database file for 'community' does not exist (use '-Fy' to download)
warning: database file for 'multilib' does not exist (use '-Fy' to download)

書かれている通り # pacman -Fy を実行することでこの warning は消え、以下のような出力になる。

$ FBReader
fish: Unknown command: FBReader
usr/bin/FBReader is owned by community/fbreader 0.99.4-9

「warning 消えてよかった〜」と思っていたが、そもそも誰がパッケージマネージャに問い合わせているのか気になる。 調べたところ公式のドキュメントにすべて書いてあった。

When fish tries to execute a command and can't find it, it invokes this function.

It can print a message to tell you about it, and it often also checks for a missing package that would include the command.

...

This command was introduced in fish 3.2.0. Previous versions of fish used the "fish_command_not_found" event instead.

fish_command_not_found - what to do when a command wasn't found — fish-shell 3.2.1 documentation

私の環境では、fish_command_not_found は以下のように定義されていた。

$ type fish_command_not_found
fish_command_not_found is a function with definition
# Defined in /usr/share/fish/functions/fish_command_not_found.fish @ line 61
function fish_command_not_found
        set -l paths $argv[1]
        # If we've not been given an absolute path, try $PATH as the starting point,
        # otherwise pacman will try *every path*, and e.g. bash-completion
        # isn't helpful.
        string match -q '/*' -- $argv[1]; or set paths $PATH/$argv[1]
        # Pacman only prints the path, so we still need to print the error.
        __fish_default_command_not_found_handler $argv[1]
        pacman -F $paths

end

無効化する

便利でユーザーフレンドリーな機能だとは思う。 が、「コマンドが見つからないときに毎回パッケージマネージャに問い合わせる」必要を個人的には感じないため無効化することにした。

When you leave fish_command_not_found undefined (e.g. by adding an empty function file) or explicitly call __fish_default_command_not_found_handler, fish will just print a simple error.

fish_command_not_found - what to do when a command wasn't found — fish-shell 3.2.1 documentation

ということなので、空のファイルを用意することで無効化する。

$ touch ~/.config/fish/functions/fish_command_not_found.fish

$ FBReader
fish: Unknown command: FBReader

🎉