bashのfcコマンドを整形後にエディタで編集する
bashはshoptでcmdhistがonになっていると複数行入力されたとき一行にしてくれる。
zshの複数行編集と比較すると悲しい…このままではいられない!(笑
bashはfcなるコマンドで直前のコマンドラインをエディタで編集した後に実行する機能がある。
一方、zshの複数行編集は新規行挿入ができない。(とおもう)
じゃあ、エディタに回す前に複数行!しかも整形済みで渡してやれば編集時はインデント付き、結果はワンライナーと両方の長所がとれるのではないのか?
と、いうことで以下のいずれかを~/.bashrcに追加。
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を使う場合
マシンが速くなったおかげで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
実行例
$ for i in {1..3} > do for j in {1..4} > do echo $i $j > done > done 1 1 1 2 1 3 1 4 2 1 2 2 2 3 2 4 3 1 3 2 3 3 3 4 $ fc
ここでエディタが立ち上がる。(ちゃんとshellモード)
エディタ内でセーブ&終了後
for i in {1..3}; do for j in {1..4}; do echo $i $j; done; done 1 1 1 2 1 3 1 4 2 1 2 2 2 3 2 4 3 1 3 2 3 3 3 4 $
ポイントは履歴に現れるものが一行に圧縮できている点だな。コピペに最高!
$ for i in {1..3}; do for j in {1..4} ; do echo $i $j; done; done
これもfc後では以下のように補正される
$ for i in {1..3}; do for j in {1..4}; do echo $i $j; done; done
コメントが消えてしまうのが難点か最終行のコメントが残る
展開したソース
もちろん自分自身で整形したソースをコピペしてある。
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 }
追記 2009/03/11 15:20:04:
最終行コメントに対応
ヒアドキュメントが使えない。
原因はbashでcmdhistがonになっていると複数行入力されたとき一行にするアルゴリズムにある。
下記のhistoryの文字列中をみると EOFまでの文字が履歴から消えていることで確認がとれる。
bash4.0ではcmdhistで一行にすることを諦めているfcの呼び出し方を工夫しないとこの点は解決できなさそう。
$ function foo { > cat <<EOF > bar > buzz > EOF > } $ history | grep function | tail -1 4025 function foo { cat <<EOF; } $ declare -f foo foo () { cat <<EOF bar buzz EOF }
declareでは保持されているところが笑える。
あと、zshの新規行追加は C-kC-yC-yC-kでいける なんとかなるもんだなぁ。vi互換キーバインドだとすぐできるのかな?