前回の記事でpecoを導入しました。
まぁ、114514番煎じの記事だったので、ちょっと違う形でpecoを使っていきたいと思います。
第5羽:ココア先輩の優雅なpecoチュートリアル
前回pecoを使っただろって?
あんなパクリ記事はチュートリアルですらないってことで
コマンドがユーザーに尋ねる
2回目の記事で、「引数がないcdコマンドはエラーにする」ことを実装しました。
この時はpecoを入れていなかったのでエラーにしましたが、ただエラーにするだけではもったいないです。
引数なしでcdコマンドを実行すると、「どこに行くか」を尋ねてくれるようにしましょう。
custom_cdls()
{
local -r argc=$#
local destination=$*
case ${argc} in
0)if ! type peco &> /dev/null; then
# Don't move $HOME
echo 'Missing args';
return 1;
fi
local asc_order='sort -f'
destination=$(find ./ -maxdepth 1 -mindepth 1 -type d
| eval $asc_order
| peco)
;;
esac
# \cd => builtin cd
\cd ${destination}
if [ $? -ne 0 ]; then
return $?
fi
clear && ls
}
alias cd='custom_cdls'
スクリプト解説
引数の数で処理を分岐します。
現状、0個の場合しか考えてません。
! type peco &> /dev/null
まず、pecoを持っているかどうかを確認しています。
type
はビルトイン関数なので、which
よりこっちを使うと色んな環境でエラーにならなくていいですね。asc_order
候補をアルファベット順に並べるための処理です。-maxdepth 1
findコマンドの検索範囲を絞るオプション。
カレントディレクトリだけを検索してほしいので、深さには1を指定する。-mindepth 1
findコマンドを使用すると.
だけのディレクトリも検索してしまう。
.
はカレントディレクトリを示すため、結局「移動しない」。それはスゴイ無駄なモノを表示しているので、含めないようにしたい。
maxdepth/mindepthの両方に階層1を指定して、検索範囲を対象ディレクトリのみに制限することで実現している。
../
(一つ上に戻る)も表示されないようなのでちょっと不便……?-type d
findコマンドで検索するモノを絞るオプション。
dを指定するとDirectoryだけを検索してくれる。
fを指定するとFileだけを検索してくれる。
これを組み合わせて実現しています。
最後に
pecoはかなり色々とフィルターできて便利ですね。
まだ大きな変更が一つありますが、それはまたの機会ということで。
今回は、パクリ出ないチュートリアルでした。
追記
使ってたら問題に遭遇したのでスクリプトを改修します。
pecoで行き先を選択しなかったらホームに戻るとは思わなかったです。
考えてみりゃそうですよね。
pecoをc-cでキャンセルした場合は変数には空文字が入っているようです。
それをcdコマンドに渡してるわけですから、私が嫌ったホームに戻るcdが再現してしまっています。
少し考えてみましたが、行き先が空文字になることと引数の数が0であることは特に関係はありません。
闇雲にpecoの実行後にケアコードを導入すると色んなところにケアコードが出てきてメンドクサそうです。
そこで、以下の修正を加えます。
-
引数0の場合からMiising argsなどのエラー部を除去する
よって、pecoの有無の判断は持ってなかったらから持ってたらに変更する。
pecoを用いて今のパスからディレクトリを検索する実装は引数の数に依存するため、この変更に問題ない。 -
新たに行き先不明のケアコードを導入する
ただし、当然ながら引数の数を判定する箇所ではない場所にすること
できるだけエラーはデフォルトのcdコマンドに任せるつもりでしたが、デフォルトではエラーでは無い訳ですから仕方ありません。英語のエラーメッセージを使いましょう。
custom_cdls()
{
local -r argc=$#
local destination=$*
case ${argc} in
0)if type peco &> /dev/null; then
local asc_order='sort -f'
destination=$(find ./ -maxdepth 1 -mindepth 1 -type d
| eval $asc_order
| peco)
fi
;;
esac
# Don't move $HOME
if [ -n $destination ];then
echo 'Missing args';
return 1;
fi
# \cd => builtin cd
\cd ${destination}
if [ $? -ne 0 ]; then
return $?
fi
clear && ls
}
alias cd='custom_cdls'
とりあえず、これで$HOMEへ戻ってしまう既存動作を塞ぐことができました。