C# 中的可直接使用的缩进文本写入器






4.33/5 (6投票s)
一个方便的代码片段,可以在使用 TextWriter 渲染多部分文档时设置缩进级别
引言
我最近正在编写一个代码生成器,使用了我之前的一些代码,来自 Rolex - 一个强大的多语言代码生成器,它根据输入规范文件创建词法分析器/词法生成器,这些文件由一系列命名的正则表达式组成。
该工具使用一种称为 CodeDOM 的东西来处理大部分繁重的工作,例如代码格式化,但现在,我更倾向于简化,我不需要 CodeDOM 及其渲染多种语言代码的能力。我不用 Visual Basic,所以似乎没必要进行所有支持它的工作,而别人可以直接将其链接为库。所以现在我直接用 C# 编写代码。速度更快,但让我缺少一些东西,其中之一就是自动代码格式化。
这并不能进行自动代码格式化,但它可以让我,或者更确切地说,你可以轻松地缩进代码块,或者其他文本部分,例如 XML、HTML 或任何需要缩进的地方。
Using the Code
使用该代码涉及将以下类完整地放入代码中的一个新文件中。与其提供下载,整个实现都足够简单,可以直接提供在这里
using System;
using System.IO;
using System.Text;
// quick and dirty indented text writer
// by honey the codewitch
class IndentedTextWriter : TextWriter
{
bool _needIndent;
TextWriter _writer;
public IndentedTextWriter(TextWriter writer)
{
if (writer == null) throw new ArgumentNullException();
_writer = writer;
_needIndent = false;
}
public override Encoding Encoding => _writer.Encoding;
public override void Write(char value)
{
if(_needIndent)
{
_writer.Write(_Indent(IndentLevel));
_needIndent = false;
}
if (value == '\n')
{
_needIndent = true;
_writer.Write("\n");
}
else
_writer.Write(value);
}
public int IndentLevel { get; set; } = 0;
public string Indent { get; set; } = " ";
string _Indent(int level)
{
if (level<=0) return "";
var len = level * Indent.Length;
var sb = new StringBuilder(len, len) ;
for(var i = 0;i<level;++i)
{
sb.Append(Indent);
}
return sb.ToString();
}
}
使用方法如下所示,并根据我正在进行的一个实际应用程序进行了调整
// create a text writer over the console
var tw = new IndentedTextWriter(Console.Out);
// write out "namespace {codenamespace} if
// codenamespace was specified
if(!string.IsNullOrEmpty(codenamespace))
{
tw.WriteLine("namespace {0}", codenamespace);
tw.WriteLine("{");
// increase the indent level for all
// subsequent writes
++tw.IndentLevel;
}
// this will be indented compared to the
// namespace declaration:
CodeGenerator.GenerateCodeAttribute(tw);
tw.WriteLine("partial class {0}", codeclass);
tw.WriteLine("{");
// increase the indent again
++tw.IndentLevel;
// generate a method
CodeGenerator.GenerateUnicodeFetchMethod(tw);
// decrease the indent to close the class
--tw.IndentLevel;
tw.WriteLine("}");
// if necessary decrease the indent and
// close the namespace
if (!string.IsNullOrEmpty(codenamespace))
{
--tw.IndentLevel;
tw.WriteLine("}");
}
如上所述,上面的代码是从一个实际应用程序改编的。并非全部显示在此处,但显示的内容足以说明如何使用 IndentedTextWriter
类。
注意,我们只是在写入内容,然后可以通过操作 IndentLevel
来增加缩进。您还可以通过修改 Indent
属性来更改用作缩进的字符串,默认值为四个空格。修改 IndentLevel
后,后续写入将以该级别进行,从而您可以透明地缩进写入文档的各个部分。上面可以看到,只有在指定了 codenamespace
时,其余代码才会缩进,然后我们可以像使用常规 TextWriter
一样将 IndentedTextWriter
传递给它,并且写入它的任何内容都将以该缩进级别写入。您还可以通过在另一个 IndentedTextWriter
上创建一个 IndentedTextWriter
来嵌套它,以防您需要这样做。
希望这能解决你的问题。
历史
- 2021 年 10 月 23日 - 初始提交