概要
EclipseとかVisual Studioみたいな、全選択してボタン押すと一括でインデント綺麗にしてくれるのが欲しかった。
需要ありそうだからググればすぐ見つかるかと思ったら、あまりにも良い感じのが見つからなかったから自作してみた。探し方が悪いんだろうか。
本当はエディタ側で設定した方が理想的な動作になるんだろうけど、色々プラグイン入れたりとかの面倒なことはあんまりしたくなった。
コード
gist参照
https://gist.github.com/sensq/dc302c9185cb260104a581cc39c656bd
ちょっと改造すればたぶん他の言語でも使える。
使い方
以下のコマンドを実行
ruby formatter.rb 'file_path'
ざっくりした処理の説明
- ファイル読み込む
- 上記ファイルと同階層にバックアップ作成(フォーマット失敗したときや比較用)
- フォーマット処理
- 予約語を定義(defとかifとか、インデント変えるキーになる文字列)
- 最初にインデントを全部消去
- 一行ずつ探索し、予約語が存在する行が出てきたら、インデントを一つずらす
- コメント行は無視
- 探索中の行の頭に、インデントの深さに応じたスペースを追加
- 上書き保存
実行例
適当にインデントがめちゃくちゃなコードを書いてフォーマットしてみる。
class Test
attr_accessor :pub
def initialize
@pub = 0
end
# loopのサンプル
def loop
(0..10).each do |i|
(0..10).each do |j|
(0..10).each do |k|
if k%2
p i
elsif k%3
p j
else
p k
end
end
end
end
end
# caseのサンプル
def case_sample
case @pub
when 1
p "hoge"
when 2
p "fuga"
end
end
end
test = Test.new
# if true
test.pub = 2
# end
test.case_sample
これをフォーマットすると・・・
class Test
attr_accessor :pub
def initialize
@pub = 0
end
# loopのサンプル
def loop
(0..10).each do |i|
(0..10).each do |j|
(0..10).each do |k|
if k%2
p i
elsif k%3
p j
else
p k
end
end
end
end
end
# caseのサンプル
def case_sample
case @pub
when 1
p "hoge"
when 2
p "fuga"
end
end
end
test = Test.new
# if true
test.pub = 2
# end
test.case_sample
キレイ!!
バグ
-
do~endではなく、{}で書いてるコードには使えないインライン展開"#{}"とか、{}を1行で書いてる場合とかの判定が面倒そうだった- ↑直しました
- 文字列として"\sdo\s"の含まれる行があると、次の行からインデントされてしまう
- 「doが"や'で囲まれている場合は無視する」ってのが面倒そうだった
- 「前後が\sのdo」という条件にしているので、あまり起こらないバグのはず
自分で書いたコードが想定通りにフォーマットされることしか確認していないので、汎用的に使えるかどうかは自信ありません。
たぶんだいたいのコードには使えるんじゃないかと思います。
追記
いまいち使い勝手悪かったので、Mery(エディタ)のマクロにしてみた。
https://gist.github.com/sensq/589de2764297e22d9b5a99acebca4684