cdコマンド改造記事第3回です。
前回の記事:ご注文はHOMEに帰らないcdですか?
今まで、cdコマンドで移動することに対して色々と手を入れてきたわけですよ。
まだcdコマンドは弄りますけど、ちょっと違うこともやってみましょう。
今回はちょっと長いです……。
TL;DR;
僕のbash設定は、もう改造に改造を重ねてこんな簡単なbashではなくなりました。
気になる人は読んで見てください。
気が向いたら解説記事でも書きます。
第3羽「楽するアイテムはbindとreadlineとスクリプト」
cdコマンドで一個上のディレクトリに戻るとき
$ cd ../../../../.../
って連打しませんか?
これって、
-
戻り先のディレクトリが、どれだけ離れてるか分かっていないといけない
パスを指さし確認して数えないと分からないですよねー。 -
正しく離れている数だけ../を入力しなければならない
../
をバカみたいな数だけタイプとかメンドクセーですよねー。
頑張っても、↑みたいにドットが3つになって「そんなディレクトリねぇから!」って怒られるんですよね。
そんで、再入力とかマジふぁっきゅー(キ〇ナアイ風)。
というスーパープレイが必要な訳ですが。
まぁ、控えめに言って無理ゲーですよね
その点、さすが!!
Windowsさんのエクスプローラ!
「Alt+↑」キーで親ディレクトリに戻っていくではありませんか!
これだ!!と思ったので、それを実装していきたいと思います。
アイテムその1:bindコマンド
キーバインドを設定するコマンドだと思ってたんですけど、
--helpを見る限りでは、なんかソケットファイル?まで操作できるらしいですね。
詳しいことは知りませんけど(´・_・`)
やってみよう
とりあえず、これでキーバインドしてみましょう。
# 暫定的にCtrl+fを使用する
bind '"\C-f":"cd ../\n"'
. ~/.bashrc
でbashを立ち上げ直しましょう。
そうするとCtrl+fを押すだけでcd ../
が実行されるようになります。
こんな感じですね。
これでcd ../../../
なんていうメンドクサイ無理ゲーコマンドから卒業出来ました!
Ctrl+fを連打するだけで好きなだけ親ディレクトリを辿れますよ!!
やったー!!
課題
でも、一つ問題があります。
最後、コマンドエラーになってますね。
これは単純にctrl+fでcd ../\n
コマンドを入力しているだけなので、すでにターミナルに文字列が入力されていると使えません。
この問題を解決してみましょう。
アイテムその2:readline
GNU readlineってのは、terminal上でemacsみたいな動きをさせるライブラリ(?)だそうです。
こんなのがデフォルトで設定されています。
めちゃくちゃ設定されているのでちょっとだけ書きます。
コマンド | readline関数 | 意味 |
---|---|---|
c-l | clear-screen | 画面をクリアする |
c-k | kill-line | カーソル以降の文字列を削除 |
c-u | unix-line-discard | カーソル以前の文字列を削除 |
c-a | beggining-of-line | カーソルを先頭に移動 |
c-e | end-of-line | カーソルを末尾に移動 |
c-x c-r | re-read-init-file | 設定ファイルをリロード |
画面が何が何だか分からなくなってきたらC-lで綺麗にしたり、
パスワード打ち間違えたらc-uで全消ししたり、
よくやりますよねー。
※C-cでシグナルを送信するのは、sttyという奴なのでこれとは違います。ご注意を。
もっと知りたい人は下記コマンドで現在の設定状況が見れます。
$ bind -p
どんな関数があるのか知りたい人は下記コマンドで見れます。
$ bind -l
やってみる前に準備
設定自体は$HOME/.inputrcに書くらしいです。
でも、環境変数INPUTRCを定義してあげればそっちを見に行ってくれるようです。
#INPUTRC="あなたの好きなパス"
INPUTRC="$HOME/.config/readline.inputrc"
私、.inputrcだけだと何のファイルだったか忘れちゃうんですよ。
なのでreadline.inputrcなんて名前にしてますけど、好きなのにしてくださいね。
それから、bashをリロードして設定を反映しておきましょう。
やってみよう
一単語ずつジャンプするカーソル移動を作ってみます。
$if bash
# readlineは他のプログラムも設定を読みに来るので、bashで分岐しておきます。
"\e[1;5C": forward-word # Control+Right
"\e[1;5D": backward-word # Control+Left
$endif
c-x c-r
を入力するとreadlineが再設定されます。※ダメだったらbashを立ち上げ直してください。
そうしたらこんな感じで動きますね。
アイテムその3:組み合わせてスクリプトにしてみよう
これでパーツは揃いました。
gnu readlineをbindしてやれば良さそうです。
でも、どんな関数を使いましょうか?
ctrl+uはカーソル以前の全文字列の削除
ctrl+kはカーソル以後の全文字列の削除
です。
ctrl+u ctrl+kと連続して実行してあげても問題はありませんが、今回は入力されている文字列を全削除するreadline関数を使ってみます。
$if bash
"\e[3;5~": kill-whole-line # Ctrl+Del
$endif
次に、これを使ってbindの設定をしてみましょう。
# \e[1;3A => Alt+↑
# \e[3;5~ => Ctrl+Del(Assign: kill-whole-line)
# \er => Ctrl+r (Assign: revert-line)
bind '"\e[1;3A":\e[3;5~\er cd ../\n'
# Ctrl+u Ctrl+kでもいけるハズ
# bind '"\e[1;3A":\C-u\C-k cd ../\n'
やっていることは
- kill-whole-lineで全文字列を削除
- revert-lineでPS1(※1)を再描画
- cd ../を実行
※1 PS1とは
prompt string1というパスなどを表示している文字列のこと。
よかったらここ読んで
revert-lineを入れている理由は、時々PS1が表示されないことがあったからです。
これでうまく動くことでしょう!
適当に文字列が入ってても問題なく実行できています!!
やりました!
謎の呪文「\e[3;5~」とは(。ω゚)?(゚。 3 )?(゚ω。)?(ε。゚ )?
最初に「いったい何の呪文だ?」と思った人だけ読んでください。
あんまり知らないんですけど、エスケープシーケンスというらしいです。
今回使ったものをまとめておきます。
Escape Sequence | 押下するボタン |
---|---|
\e[3;5~ | Ctrl + Del |
\e[1;5C | Ctrl + → |
\e[1;5D | Ctrl + ← |
\e[1;3A | Alt + ↑ |
catコマンドのあとに入力すると見ることができます。
$ cat
まとめ
今回は、bindコマンドとGNU readlineを使って楽にcd ../
を実行できるようにしてみました。
ほとんどが浅い知識で出来ているので、間違ってたら教えてください。
ホントはね?
こんな感じにbindコマンドにreadline関数を指定できるみたいなんですけど……
なんかフツーにエラーになったんですよね(´・_・`)コマンドガ,ミツカリマセン
bind '"\C-f": forward-word' # OK
bind '"\C-f": kill-whole-line revert-line cd ../\n' # NG
なので、.inputrcを使ってみたら回避できました。
それでは、今回はここで終わりです。