bashをzshに負けないぐらい高機能化するためのtips

はっきり言って先方予測と複数行編集は無理。だけど代替手段がありそうだ。

ということで、bashでどこまでzshに近づけるかチャレンジしてみる。
使用環境は環境はubuntu8.10

以下を.bashrcに追加

if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi
function share_history { history -a; history -c; history -r; }
PROMPT_COMMAND='share_history'
shopt -u histappend
export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S: "
export HISTSIZE=300000
function fceditor ()  {  tt=/tmp/$$.sh; cat $1 | ( read -rd '' s; t=/tmp/$$; echo "function a(){" > $t; echo "$s" >> $t; echo -e " }\n declare -f a" >> $t; chmod +x $t; $t > /dev/null 2>&1; if [ $? = 0 ]; then a=`$t|sed '1,2d;$d;s/....//'`";"`echo "$s"|tail -1|sed 's/^.\+\(#[^#]\+\)$/\1/'`; else a="$s"; fi; rm $t; echo "$a" ) > $tt; vim $tt; sed 's/^ *//' $tt > $1; rm $tt; }
export FCEDIT=fceditor


↓は解説

TABキーによるコマンド補完

デフォルト(/etc/skel/.bashrc)をそのまま使っているなら問題無く使えているはず。

~$ sudo apt

この段階でTABキーを押して次のようになるはず

~$ sudo apt
apt-cache                     apt-mark
apt-cdrom                     apt-sortpkgs
apt-config                    aptitude
apt-extracttemplates          aptitude-create-state-bundle
apt-ftparchive                aptitude-run-state-bundle
apt-get                       apturl
apt-key                       
~$ sudo apt

ならなかった場合には~/.bashrcに以下を追加

if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

実をいうと自分はdebianから同じ.bashrcを使っていたので、この設定を見逃してた。たまには/etc/skelをのぞいてみよう。

自分でルールを追加したい時には/etc/bash_completion か/etc/bash_completion.d/以下を参考にする
(暇を見てrarとかのオプションの書き方でもかくか)

ubulog: bashの補完機能を拡張してみたとかがすごく参考になる。

履歴検索

まあデフォルトのままでも使えるんだが

プロンプトの段階でC-r(reverse-i-search)を押してやればいい。

~$

プロンプトが出ているときにC-rをおすとプロンプトが(reverse-i-search)`':になる

(reverse-i-search)`':

この段階で検索したい語句を入れていくと逐次検索してくれる

(reverse-i-search)`v': vi .bashrc 

ここで履歴の最新から検索し直したいときにはM->でよい。

履歴にタイムスタンプ追加

いつ打ったコマンドかが分かればなんか役に立つかもしれない?~/.bashrcに以下を追加

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S: "

履歴の容量を増やす

やっぱ、スクリプトはファイルにせずに履歴から検索しよう

export HISTSIZE=300000

これだけ増やしておいて、ワンライナー製作時にコメントを入れておくと全文検索でコマンドを探せるようになる。
こうなってくるとファイル名の存在意義を疑うようになるな(笑

(reverse-i-search)`サブ': for i in * ; do (cd "$i"; pwd ; for j in *; do echo "$j" ; zip -qr "../$j.zip" "$j" ;done);done ; #サブフォルダ毎にzip

注意しなきゃいけないのはIMEにて文節を検索ワードとして入力てしまうとbashの方が検索ミスした際、i-searchを止めてしまう。そのときはC-cでやり直すべし。
この辺がbashが多言語化されていないところ。

複数の端末で履歴を共有する

iandeth. - bashにて複数端末間でコマンド履歴(history)を共有する方法より

~/.bashrcに以下を追加

function share_history {
    history -a
    history -c
    history -r
}
PROMPT_COMMAND='share_history'
shopt -u histappend
export HISTSIZE=300000

履歴編集

どうもzshの複数行編集は無理そうなので代替でインデント付きの編集モードを追加。
bashの履歴をエディタで編集するfcコマンドを拡張する(→インデント付で編集)

vimを使う場合
function fceditor ()  {  tt=/tmp/$$.sh; cat $1 | ( read -rd '' s; t=/tmp/$$; echo "function a(){" > $t; echo "$s" >> $t; echo -e " }\n declare -f a" >> $t; chmod +x $t; $t > /dev/null 2>&1; if [ $? = 0 ]; then a=`$t|sed '1,2d;$d;s/....//'`";"`echo "$s"|tail -1|sed 's/^.\+\(#[^#]\+\)$/\1/'`; else a="$s"; fi; rm $t; echo "$a" ) > $tt; vim $tt; sed 's/^ *//' $tt > $1; rm $tt; }
export FCEDIT=fceditor
emacsを使う場合
function fceditor ()  {  tt=/tmp/$$.sh; cat $1 | ( read -rd '' s; t=/tmp/$$; echo "function a(){" > $t; echo "$s" >> $t; echo -e " }\n declare -f a" >> $t; chmod +x $t; $t > /dev/null 2>&1; if [ $? = 0 ]; then a=`$t|sed '1,2d;$d;s/....//'`";"`echo "$s"|tail -1|sed 's/^.\+\(#[^#]\+\)$/\1/'`; else a="$s"; fi; rm $t; echo "$a" ) > $tt; emacs -nw $tt; sed 's/^ *//' $tt > $1; rm $tt; }
export FCEDIT=fceditor


詳しくは bashのfcコマンドを整形後にエディタで編集する - 計算機と戯れる日々 を参照のこと

今後やろうとおもっていること

やり方募集中(笑

エラー音をPCMにしたい。

本体がなるの嫌なんだよな。
ちなみにエラー音(というかbeep音)を画面の明滅にするのは以下でよい。

echo set bell-style visible >> .inputrc
先方予測(インクリメンタルな補完)

無理な気がする。これだけでもzshの価値があるんだよな…
zshの以下の機能

autoload predict-on
predict-on
複数行編集

zshでは複数行で入力されたコマンドは複数行のまま表示される。しかもzshでは、表示された複数行のコマンドをエディタでも使うように編集できてしまう。
しかし、bashでは1行コマンドに変換されたものが表示される。

zshってEnterの意味が微妙なんだな。最初の入力はいいけど二回目の編集でEnterやC-oで行の挿入ができない。(C-kC-yC-yC-kでできる)