home changes contents help options

058:インデントを変更する

Python でも正規表現が使用できるので Ruby レシピブックと同じことが可能です。 String#gsub(pattern){|matched| .... } (これは便利)は re.sub の第 2 引数に関数を指定することで代用しています。 String#map {|item| ....} の代用は str.splitlines を核としたジェネレータ式で行いました。しかし、読みやすさという点では、ジェネレータ関数をきっちり定義するほうがよかったかもしれません。

import re

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 indent0(s, n):
    u"""
    半角空白文字 n 個分インデントする(タブ非対応)
    """
    return re.sub('(?m)^', ' ' * n, s)

def indent(s, n, tabstop=8):
    u"""
    半角空白文字 n 個分インデントする(タブ対応)
    """
    if tabstop:
        return ''.join(' ' * n + untabify(line, tabstop)
                for line in s.splitlines(True))
    else:
        return re.sub('(?m)^', ' ' * n, 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)