home changes contents help options

059:ヒアドキュメントの本体をインデントして書く

Ruby ではヒアドキュメント終端記号をインデントして書いても本文のインデントは削除されないため、 そのようなことを行う関数を Ruby レシピブックでは提供しています。

Python にはヒアドキュメントはありませんが、三重クォート文字列では同じ悩みが発生します。

class HTML(object):
    # 各行先頭に空白が大量に
    temp = """
            <html>
                <body>
                    <p>
                        %s
                    </p>
                </body>
            </html>
           """

この空白を削除するには次の unindent_auto, unindent_auto0 関数を用いるとよいでしょう。 untabify, tabify, unindent0, unindent 関数は 058:インデントを変更する で出てきたものと同じです。

import re

def unindent_auto(string, tabstop=8):
    u"""インデントを自動削除する(タブ対応)"""
    minimum_indent = count_minimum_indent(string)
    return unindent(string, minimum_indent, tabstop)

def unindent_auto0(string):
    u"""インデントを自動削除する(タブ非対応)"""
    minimum_indent = count_minimum_indent(string)
    return unindent0(string, minimum_indent)

def count_minimum_indent(string):
    u"""もっとも浅いインデントを返す
    
    ただし空行は無視する。"""
    return min(len(line) for line in string.splitlines() if line)

def untabify(s, tabstop=8):
    u"""
    タブを半角空白文字に
    """
    return re.sub(
            '(.*?)\t',
            lambda mo: (
                mo.group(1) + 
                ' ' * (tabstop - (len(mo.group(1)) % tabstop))
                ),
            s)

def tabify(s, tabstop=8):
    u"""
    半角空白文字をタブに
    """
    def repl(mo):
        tab, space = divmod(len(untabify(mo.group(0), tabstop)), tabstop)
        return '\t' * tab + ' ' * space
    return re.sub('(?m)^[ \t]+', repl, s)

def unindent0(s, n):
    u"""
    半角空白文字 n 個分アンインデントする(タブ非対応)
    """
    return re.sub('(?m)^ {0,%d}' % n, '', s)

def unindent(s, n, tabstop=8):
    u"""
    半角空白文字 n 個分アンインデントする(タブ対応)
    """
    indent_re = re.compile('^ {0,%d}' % n, re.MULTILINE)
    if tabstop:
        return ''.join(
                tabify(
                    indent_re.sub(
                        "",
                        untabify(line, tabstop)),
                    tabstop)
                for line in s.splitlines(True))
    else:
        return indent_re.sub('', s)

関連