zshで究極のオペレーションを

第3回 zsh使いこなしポイント即効編

この記事を読むのに必要な時間:およそ 7 分

もっと bindkey -s を

tcshでも全く同様に使える機能だが,bindkey -sは,タイプした文字の流れを登録できるのでキーボードマクロ的な「複雑ではないが面倒」な処理をどんどん定義できる。しょっちゅうタイプする文字列や,キーの流れはどんどん登録したい。

シェルを主な作業場所としている人であれば,たとえば以下のような文字列やそれに類するものはよく打つはずである。

  • ファイルを展開するために"gtar zxpf "
  • 出力結果をページャで見るために「行末に移動して"| less"をタイプしてリターン」
  • 出力結果の行数を調べるために「行末に移動して "| wc" をタイプしてリターン」
  • 出力を捨てるために">/dev/null"あるいは">&/dev/null"
  • 何かの出力の第Nフィールドをawkで取り出すために" | awk '{print $N}' | "Nはその都度変わる)
  • カレントディレクトリ以下すべての通常ファイルを指定するために"**/*(.)"

このように,熟語的に用いるコマンド文字列は人によって様々な頻出用法があるはずである。これはbindkey -sで目の前にすぐ取り出せるようにしておくと効果的で,たとえば単純文字列なら以下のように設定するとESC-G"gtar zxpf "が出てくる。

bindkey -s '^[G' 'gtar zxpf '

また,以下のように設定すると,ESC-A のタイプでコマンドラインに"| awk '{print $}'|"が挿入され,カーソル位置が$の直後になる。

bindkey -s '^[A' "| awk '{print $}'|^B^B^B"

よく使うlessは以下のようにしておくとよいだろう。

bindkey -s '^[L' "^E|less^M"

ちなみにbashの場合は,~/.inputrcに記述する。

$if Bash
 "\ep": history-search-backward
 "\en": history-search-forward
 "\eG": "gtar zxpf "
 "\eL": downcase-word
 "\el": "\C-e|less\C-m"
$endif

割り当てるキーの選択

bindkeyで自分仕様のものをキーに割り当てるとき,どのキーに割り当てるかがちょっとした問題になる。emacsキーマップはほとんど空いているキーがない。標準では「ESC-英字」の英小文字と英大文字の両方に同じ機能が割り当てられているため,そのどちらかを上書きしても機能損失はない。たとえばESC-LESC-lはともにdown-case-wordで,カーソル位置の単語を小文字化する。小文字化と"^E|less^M"のよく使う方をESC-lそうでないほうをESC-Lに割り当てておくとよい。筆者は断然less起動の方をよく使うため,そちらをESC-lに割り当てている。

よりたくさんのキーを割り当てたいなら,新しいプレフィクスキーストロークを作ってしまうこともできる。zshのbindkeyで2ストローク以上のキーを指定すると,最後の1字以外の部分をプレフィクスキーストロークとして自動的に処理してくれる。

たとえば筆者は独自のキー割り当てを多数持ちたいので,あまり使わないC-qを新規プレフィクスキーストロークとしている。

# Ctrl-Q prefix
bindkey '^q '           set-mark-command
bindkey '^q^b'          vi-history-search-backward
bindkey '^q^d'          end-of-line
bindkey '^q^e'          up-line-or-beginning-search
bindkey '^q^n'          down-line-or-beginning-search
bindkey '^q^f'          history-incremental-search-backward
bindkey '^q^h'          backward-kill-word
bindkey '^q^i'          expand-or-complete-prefix
bindkey '^q^j'          exchange-point-and-mark
bindkey '^q^s'          beginning-of-line

特別な宣言なしに2ストローク以上のキーを指定しても,たとえばC-q C-dを押せばend-of-lineを呼び出してくれる。さらに,C-qだけをタイプして一定時間(デフォルトで100分の40秒=$KEYTIMEOUT経過するとC-q のみに割り当てた機能push-lineが呼び出される。

このように,連打する必要のないキーならばどのキーでも手軽にプレフィクスキーストロークにできるので欲張った拡張がやりやすい。また,キーに割り当てていない機能はM-xESC-xに機能名を指定して呼び出すことができる。

% ls /
     ↑ここで M-x beginning-of-line
% ls /

機能名はEmacsと同じ慣習で付けられている。機能名の入力時には,Tab補完やESC-C-dによる候補一覧表示が使えるため,zshのラインエディタ全体にどんな機能があるのかを調べることも容易にできる。

まとめ

プロンプトもキー割り当ても何度も触れるものだけに,とことん磨きあげる価値がある。キー割り当てに関して言えば,bindkeyコマンドを引数なしで起動して得られるものだけでなく,キー割り当てのない便利なものもたくさんあり,全部じっくり見るのはなかなかたいへんである。しょっちゅう面倒に感ずる操作があった場合は,それを解決する機能を見付けるチャンスかもしれない。

次回は「zshなら一発」を実感できる機能を紹介したい。