You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LibCST缩进代码时如何保留空行,避免空行被添加缩进空格

使用LibCST缩进代码时如何保留空行,避免空行被添加缩进空格

我太懂你这种困扰了——用cst.IndentedBlock给代码块加缩进时,连空行都被硬生生加上了缩进空格,完全破坏了原本的代码格式。别担心,咱们有两种靠谱的方法能解决这个问题,让空行保持干干净净的无缩进状态。

方法一:自定义CST Transformer处理空行

这是最灵活也最省心的方案,我们可以写一个Transformer,专门“照顾”空行节点,让它们在缩进时保持原样:

import libcst as cst

class PreserveEmptyLinesTransformer(cst.CSTTransformer):
    def leave_EmptyLine(self, original_node: cst.EmptyLine, updated_node: cst.EmptyLine) -> cst.EmptyLine:
        # 把空行的缩进强制设为空,这样就不会被IndentedBlock添加缩进了
        return updated_node.with_changes(indent=cst.Indent(whitespace=cst.SimpleWhitespace("")))

# 解析你的原始代码
s = cst.parse_module("""\
a = 1

b = 2
""")

# 先让代码过一遍Transformer处理空行,再包裹进IndentedBlock
transformed_code = s.visit(PreserveEmptyLinesTransformer())
indented_block = cst.IndentedBlock(transformed_code.body)

# 生成最终代码
print(cst.Module([indented_block]).code)

运行这段代码后,输出就是你想要的效果:

a = 1

    b = 2

原理很简单:这个Transformer会遍历代码里所有的EmptyLine节点,把它们的缩进内容改成空字符串,这样就算被IndentedBlock包裹,空行也不会带上多余的缩进空格,完美保留原本的空行格式。

方法二:手动拆分节点处理(适合简单场景)

如果你的代码结构比较简单,也可以手动把空行和非空行分开处理,只对实际的代码语句应用缩进:

import libcst as cst

s = cst.parse_module("""\
a = 1

b = 2
""")

# 先把原始代码的body拆成多个块,用空行分隔
blocks = []
current_block = []
for node in s.body:
    if isinstance(node, cst.EmptyLine):
        # 遇到空行,就把当前块(如果有的话)加入blocks,再加入空行
        if current_block:
            blocks.append(cst.IndentedBlock(current_block))
            current_block = []
        blocks.append(node)
    else:
        current_block.append(node)
# 别忘了加入最后一个块
if current_block:
    blocks.append(cst.IndentedBlock(current_block))

# 生成最终代码
print(cst.Module(blocks).code)

这种方法适合代码里空行不多、结构简单的情况,不过相比Transformer,它的鲁棒性稍差一些,如果代码里有复杂的嵌套结构,还是第一种方法更靠谱。

小结

优先推荐自定义Transformer的方案,它能自动处理所有位置的空行,不管你的代码结构多复杂,都能轻松保留空行的原始格式,不会出现意外的缩进问题。

备注:内容来源于stack exchange,提问作者Nico Schlömer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 11:44:49