反转reindent.py(空格转制表符)

0 投票
1 回答
774 浏览
提问于 2025-04-16 17:48

据我所知,reindent.py(在标准的Python示例中可以找到)有一个分词器,可以根据缩进级别来智能地重新缩进,而不是根据每个级别的空格数量(这在糟糕的代码中可能会有所不同)

不幸的是,它强制使用4个空格的缩进,但我想用制表符,因为1个制表符等于1个缩进级别,这样更合理,而不是用几个空格。

这个问题没有合适的答案:

  • 我不在乎PEP-8(我知道怎么写我的代码)
  • 我已经安装了vim,但:retab!不能处理不一致的缩进
  • 所有工具也会把用于对齐的空格(不等于缩进)转换成制表符。

一种方法是使用reindent.py,然后再做一些像这样的事情:

#!/usr/bin/env python3
from re import compile
from sys import argv

spaces = compile("^ +")
multistr = False
for line in open(argv[1]):
    num = 0
    if not multistr:
        try:
            num = len(spaces.search(line).group(0)) // 4
        except AttributeError:
            pass
    print("\t"*num + line[num*4:-1])
    if line.count('"""') % 2 == 1:
        multistr = not multistr

但这有点像是临时解决办法。难道没有一个不那么极端的reindent.py版本吗?

附言:为什么高亮显示// 4是注释,而不是截断除法?


下面的脚本应该能解决这个问题,但要么是我漏掉了什么,要么是tokenize有问题(或者Python文档中的示例有问题)

#!/usr/bin/env python3

from tokenize import *
from sys import argv

f = open(argv[1])
def readline():
    return bytes(f.readline(), "utf-8")

tokens = []
ilvl=0
for token in tokenize(readline):
    if token.type == INDENT:
        ilvl+=1
        tokens.append((INDENT, "\t"*ilvl))
    else:
        if token.type == DEDENT:
            ilvl-=1
        tokens.append(token)

print(untokenize(tokens).decode('utf-8'))

1 个回答

3

在Unix系统中,你可以用sed这个工具一行代码就搞定:

sed -r ':f; s|^(\t*)\s{4}|\1\t|g; t f' file

补充说明:这个方法只适用于行首的空格。

撰写回答