作用于 c# 多行字符串的缩进
Acting on the indentation of a c# multiline string
我想从 c# 写一些 Html(html 是一个例子,这可能是其他语言..)
例如:
string div = @"<div class=""className"">
<span>Mon text</span>
</div>";
将产生:
<div class="className">
<span>Mon text</span>
</div>
从 Html 的角度来看,这不是很酷...
获得正确 HTML 缩进的唯一方法是像这样缩进 C# 代码:
string div = @"<div class=""className"">
<span>Mon text</span>
</div>";
我们得到了正确的缩进 Html:
<div class="className">
<span>Mon text</span>
</div>
但是像这样缩进 C# 确实破坏了代码的可读性...
有没有办法在 C# 语言中对缩进进行操作?
如果没有,有人有比以下更好的提示吗:
string div = "<div class=\"className\">" + Environment.NewLine +
" <span>Mon text</span>" + Environment.NewLine +
"</div>";
并且优于
var sbDiv = new StringBuilder();
sbDiv.AppendLine("<div class=\"className\">");
sbDiv.AppendLine(" <span>Mon text</span>");
sbDiv.AppendLine("</div>");
我使用的解决方案:
非常感谢@Yotam 的回答。
我写了一点扩展来对齐 "dynamic" :
/// <summary>
/// Align a multiline string from the indentation of its first line
/// </summary>
/// <remarks>The </remarks>
/// <param name="source">The string to align</param>
/// <returns></returns>
public static string AlignFromFirstLine(this string source)
{
if (String.IsNullOrEmpty(source)) {
return source;
}
if (!source.StartsWith(Environment.NewLine)) {
throw new FormatException("String must start with a NewLine character.");
}
int indentationSize = source.Skip(Environment.NewLine.Length)
.TakeWhile(Char.IsWhiteSpace)
.Count();
string indentationStr = new string(' ', indentationSize);
return source.TrimStart().Replace($"\n{indentationStr}", "\n");
}
那我就可以这样用了:
private string GetHtml(string className)
{
return $@"
<div class=""{className}"">
<span>Texte</span>
</div>".AlignFromFirstLine();
}
那个 return 正确 html :
<div class="myClassName">
<span>Texte</span>
</div>
一个限制是它只能使用 space 缩进...
欢迎任何改进!
我更喜欢,但是怎么样:
string div = "<div class='className'>\n"
+ " <span>Mon text</span>\n"
+ "</div>";
这消除了一些混乱:
- 将字符串中的
"
替换为 '
,这样您就不需要转义引号了。 (Single quotes in HTML appear to be legal.)
- 您还可以使用常规
""
字符串文字代替 @""
。
- 使用
\n
而不是 Environment.NewLine
。
请注意,the string concatenation is performed during compilation, by the compiler. (See also this and this 博客 post 由 Eric Lippert 撰写,他之前从事 C# 编译器的工作。)没有运行时性能损失。
您可以将字符串换到下一行以获得所需的缩进:
string div =
@"
<div class=""className"">
<span>Mon text</span>
</div>"
.TrimStart(); // to remove the additional new-line at the beginning
另一个不错的解决方案(缺点:取决于缩进级别!)
string div = @"
<div class=""className"">
<span>Mon text</span>
</div>".TrimStart().Replace("\n ", "\n");
它只是删除了字符串中的缩进。确保 Replace
第一个字符串中的空格数与缩进的空格数相同。
如果它是一个长字符串,那么您始终可以将该字符串保存在文本文件中并将其读入您的变量,例如
string text = File.ReadAllText(@"c:\file.txt", Encoding.UTF8);
这样您就可以使用文本编辑器随意设置格式,而且不会对代码的外观产生负面影响。
如果您要即时更改部分字符串,那么 StringBuilder
是您的最佳选择。 - 或者如果您确实决定从文本文件中读取字符串,您可以在字符串中包含 {0}
元素,然后使用 string.format(text, "text1","text2", etc)
更改所需的部分。
受 Kotlin 中的 trimIndent()
启发。
此代码:
var x = @"
anything
you
want
".TrimIndent();
将产生一个字符串:
anything
you
want
或"\nanything\n you\nwant\n"
实施:
public static string TrimIndent(this string s)
{
string[] lines = s.Split('\n');
IEnumerable<int> firstNonWhitespaceIndices = lines
.Skip(1)
.Where(it => it.Trim().Length > 0)
.Select(IndexOfFirstNonWhitespace);
int firstNonWhitespaceIndex;
if (firstNonWhitespaceIndices.Any()) firstNonWhitespaceIndex = firstNonWhitespaceIndices.Min();
else firstNonWhitespaceIndex = -1;
if (firstNonWhitespaceIndex == -1) return s;
IEnumerable<string> unindentedLines = lines.Select(it => UnindentLine(it, firstNonWhitespaceIndex));
return String.Join("\n", unindentedLines);
}
private static string UnindentLine(string line, int firstNonWhitespaceIndex)
{
if (firstNonWhitespaceIndex < line.Length)
{
if (line.Substring(0, firstNonWhitespaceIndex).Trim().Length != 0)
{
return line;
}
return line.Substring(firstNonWhitespaceIndex, line.Length - firstNonWhitespaceIndex);
}
return line.Trim().Length == 0 ? "" : line;
}
private static int IndexOfFirstNonWhitespace(string s)
{
char[] chars = s.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
if (chars[i] != ' ' && chars[i] != '\t') return i;
}
return -1;
}
我想从 c# 写一些 Html(html 是一个例子,这可能是其他语言..)
例如:
string div = @"<div class=""className"">
<span>Mon text</span>
</div>";
将产生:
<div class="className">
<span>Mon text</span>
</div>
从 Html 的角度来看,这不是很酷...
获得正确 HTML 缩进的唯一方法是像这样缩进 C# 代码:
string div = @"<div class=""className"">
<span>Mon text</span>
</div>";
我们得到了正确的缩进 Html:
<div class="className">
<span>Mon text</span>
</div>
但是像这样缩进 C# 确实破坏了代码的可读性...
有没有办法在 C# 语言中对缩进进行操作?
如果没有,有人有比以下更好的提示吗:
string div = "<div class=\"className\">" + Environment.NewLine +
" <span>Mon text</span>" + Environment.NewLine +
"</div>";
并且优于
var sbDiv = new StringBuilder();
sbDiv.AppendLine("<div class=\"className\">");
sbDiv.AppendLine(" <span>Mon text</span>");
sbDiv.AppendLine("</div>");
我使用的解决方案:
非常感谢@Yotam 的回答。
我写了一点扩展来对齐 "dynamic" :
/// <summary>
/// Align a multiline string from the indentation of its first line
/// </summary>
/// <remarks>The </remarks>
/// <param name="source">The string to align</param>
/// <returns></returns>
public static string AlignFromFirstLine(this string source)
{
if (String.IsNullOrEmpty(source)) {
return source;
}
if (!source.StartsWith(Environment.NewLine)) {
throw new FormatException("String must start with a NewLine character.");
}
int indentationSize = source.Skip(Environment.NewLine.Length)
.TakeWhile(Char.IsWhiteSpace)
.Count();
string indentationStr = new string(' ', indentationSize);
return source.TrimStart().Replace($"\n{indentationStr}", "\n");
}
那我就可以这样用了:
private string GetHtml(string className)
{
return $@"
<div class=""{className}"">
<span>Texte</span>
</div>".AlignFromFirstLine();
}
那个 return 正确 html :
<div class="myClassName">
<span>Texte</span>
</div>
一个限制是它只能使用 space 缩进...
欢迎任何改进!
我更喜欢
string div = "<div class='className'>\n"
+ " <span>Mon text</span>\n"
+ "</div>";
这消除了一些混乱:
- 将字符串中的
"
替换为'
,这样您就不需要转义引号了。 (Single quotes in HTML appear to be legal.) - 您还可以使用常规
""
字符串文字代替@""
。 - 使用
\n
而不是Environment.NewLine
。
请注意,the string concatenation is performed during compilation, by the compiler. (See also this and this 博客 post 由 Eric Lippert 撰写,他之前从事 C# 编译器的工作。)没有运行时性能损失。
您可以将字符串换到下一行以获得所需的缩进:
string div =
@"
<div class=""className"">
<span>Mon text</span>
</div>"
.TrimStart(); // to remove the additional new-line at the beginning
另一个不错的解决方案(缺点:取决于缩进级别!)
string div = @"
<div class=""className"">
<span>Mon text</span>
</div>".TrimStart().Replace("\n ", "\n");
它只是删除了字符串中的缩进。确保 Replace
第一个字符串中的空格数与缩进的空格数相同。
如果它是一个长字符串,那么您始终可以将该字符串保存在文本文件中并将其读入您的变量,例如
string text = File.ReadAllText(@"c:\file.txt", Encoding.UTF8);
这样您就可以使用文本编辑器随意设置格式,而且不会对代码的外观产生负面影响。
如果您要即时更改部分字符串,那么 StringBuilder
是您的最佳选择。 - 或者如果您确实决定从文本文件中读取字符串,您可以在字符串中包含 {0}
元素,然后使用 string.format(text, "text1","text2", etc)
更改所需的部分。
受 Kotlin 中的 trimIndent()
启发。
此代码:
var x = @"
anything
you
want
".TrimIndent();
将产生一个字符串:
anything
you
want
或"\nanything\n you\nwant\n"
实施:
public static string TrimIndent(this string s)
{
string[] lines = s.Split('\n');
IEnumerable<int> firstNonWhitespaceIndices = lines
.Skip(1)
.Where(it => it.Trim().Length > 0)
.Select(IndexOfFirstNonWhitespace);
int firstNonWhitespaceIndex;
if (firstNonWhitespaceIndices.Any()) firstNonWhitespaceIndex = firstNonWhitespaceIndices.Min();
else firstNonWhitespaceIndex = -1;
if (firstNonWhitespaceIndex == -1) return s;
IEnumerable<string> unindentedLines = lines.Select(it => UnindentLine(it, firstNonWhitespaceIndex));
return String.Join("\n", unindentedLines);
}
private static string UnindentLine(string line, int firstNonWhitespaceIndex)
{
if (firstNonWhitespaceIndex < line.Length)
{
if (line.Substring(0, firstNonWhitespaceIndex).Trim().Length != 0)
{
return line;
}
return line.Substring(firstNonWhitespaceIndex, line.Length - firstNonWhitespaceIndex);
}
return line.Trim().Length == 0 ? "" : line;
}
private static int IndexOfFirstNonWhitespace(string s)
{
char[] chars = s.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
if (chars[i] != ' ' && chars[i] != '\t') return i;
}
return -1;
}