はじめに
zshで日本語から始まるファイル名をタブ補完したい場合に、先頭数文字の入力のためにIMEを日本語入力に切り替えるのが手間1なので、
ローマ字で日本語ファイル名を補完できるようにしてみました。今回はその方法を紹介します。
動作はUbuntu 24.04で確認しています。
方法
日本語→ローマ字変換にKAKASIを使用するため、あらかじめインストールしておきます。
自分でビルドしても良いですが、Ubuntuであればapt install kakasi
でインストール可能です。
インストール後、.zshrc
に以下の内容を追加すれば、ローマ字での補完が可能になります。
_expand_japanese()
{
setopt localoptions rematchpcre # [:ascii:] を使用出来るようにする
local IFS=$'\0' suffix file romaji
if [ "$words[1]" = cd ]; then
# cdコマンドの場合はフォルダのみを対象とする
suffix=/
else
suffix=""
fi
# ファイル名一覧でループ
for file in $(print -nN "${1:h}"/*"$suffix"); do
if [[ "${file:t}" =~ [^[:ascii:]] ]]; then
# 先頭が非ASCII文字の場合、ファイル名をローマ字に変換する
romaji=(${(f)$(kakasi -iutf8 -Ha -Ea -Ka -Ja <<< "${file:t}")})
if [[ "$romaji" == "${1:t}"* ]]; then
# 変換後のファイル名先頭部分が入力と一致すれば展開候補に追加
reply+=(${(q)"${file#./}"})
fi
fi
done
}
# ローマ字展開関数を_user_expandに登録
zstyle ':completion:*' user-expand _expand_japanese
# ローマ字展開の候補一覧に all expansions や original が出現しないようにする
zstyle ':completion:*:user-expand:*' tag-order expansions
# デフォルトのcompleter(_complete _ignored)をまず実行し、候補が無ければローマ字展開を実行する
zstyle ':completion:*' completer _complete _ignored _user_expand
解説
zshの補完システムには、入力文字の続きを自動入力する通常の補完とは別に、
入力文字自体を別の内容で置き換える展開機能(expansion)が存在します。
どのような補完や展開を行うかを定義したcompleterというものが複数存在し、どれをどの順で使用するかは自由に設定可能です。
この内、_user_expand
というcompleterには自作の展開関数を登録することが可能で、
展開関数内でreply
配列に追加した値が展開候補として表示されます。2
上記.zshrc
では、「ローマ字に変換したファイル名の先頭と入力文字が一致する場合に展開する」という展開関数を実装して登録しています。
おわりに
この設定は完璧ではなく、ローマ字展開より通常の補完が優先されるため、例えば
「日本語
というファイルとniwatori
というファイルがある場合、ni
→Tab と入力するとniwatori
となり、日本語
に展開できない」
という欠点があります。
completerの指定順で_user_expand
を先に指定すれば展開可能ですが、その場合逆にniwatori
を補完できなくなります。
そもそもシェル上で日本語ファイルを扱う頻度はそこまで高くないため、通常の補完を優先する設定にしています。
ちなみに、zshのタブ補完はCtrl+x u
でundo可能なので、
日本語
というファイルとniwatori
というファイルがある場合、ni
→Tab と入力するとniwatori
となり
このような場合でもundoでni
に戻してからh
→Tabと入力すれば日本語
に展開できるため、わりとどうにかなります。