使用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
相关产品推荐
相关产品推荐

