Groovyでヒアドキュメントの本体をインデントして書く(最も少ないインデントに変更する)



ヒアドキュメントだと空白も意味を持つので、インデントを使うことができない。
そういう時は、ヒアドキュメントでインデントを使って書いて、後から最小のインデントに
変更する方がいいだろう。
そのためのメソッド。


ソース

test = """\
    * foo
\t  * buz
        * bar
"""


def rstrip(str){
    str.replaceAll(/\s+\z/,"")
}

def unindent(str, n, tabStop = 8){
    str.split("\n").toList().collect{line ->
        if (tabStop) {
           line.expand(tabStop).replaceAll(/(?m)^ {0,$n}/, "").unexpand(tabStop) 
        } else {
            line.replaceAll(/(?m)^ {0,$n}/, "")
        }
    }.join("\n")
}


def minimumIndent(str){
    
    indents = str.split("\n").toList().collect{line ->
         rstrip(line.expand()).find(/\A */).size()
    }
    indents.min()
}

def unindent_auto(str){
    unindent(str, minimumIndent(str))
}

println test
println unindent_auto(test)

実行結果

    * foo
          * buz
        * bar

* foo
      * buz
    * bar

補足

indentsを求めてる処理は以下の内容

  1. タブを空白に変換
  2. 行末の空白類を削除、
  3. 先頭からの空白を検索
    • find()はrubyのslice()の代わり
  4. サイズを取得

indents は[4, 10, 8]のようなリストになっている



添削歓迎

ここ間違ってるよ
こうした方がGroovyらしくないか?
などなど
方法は、コメント、トラックバックはてブTwitter @orange_clover宛 で、お願いしまます。

実行環境

  • OS:Windows XP
  • Groovy Version: 1.7.8 expand()、unexpand()が1.7.3以降だから
  • JVM: 1.6.0_12






Groovyの詳細についてはJavadocと以下の書籍を参考にしている。




Dierk Konig、Andrew Glover、Paul King、、Guillaume Laforge、Jon Skeet、杉浦 孝、櫻井 正樹、須江 信洋、関谷 和愛、佐野 徹郎、寺沢 尚史

Amazonでご確認ください。



問題自体は第2版のもの。rubyと似てる部分も多いので、ヒントにもなる。
写経でもいいが自分で考えるために他言語の例をGroovyで置き換えてる。




青木 峰郎、後藤 裕蔵、高橋 征義、まつもと ゆきひろ

価格: ¥ 2,940
価格は記載時点のものです。購入前にAmazonでご確認ください。




Groovyイン・アクションを読むならあった方が便利かな。

Rubyレシピブックは「ほんたった」で立ててる