Search code examples
c#stringmultiline

Acting on the indentation of a c# multiline string


I want to write some Html from c# (html is an example, this might be other languages..)

For example:

    string div = @"<div class=""className"">
                      <span>Mon text</span>
                   </div>";

will produce:

<div class="className">
            <span>Mon text</span>
         </div>

that's not very cool from the Html point of view...

The only way to have a correct HTML indentation will be to indent the C# code like this :

            string div = @"<div class=""className"">
    <span>Mon text</span>
</div>";

We get the correctly indented Html:

<div class="className">
    <span>Mon text</span>
</div>

But indenting the C# like this really broke the readability of the code...

Is there a way to act on the indentation in the C# language ?

If not, does someone have a tip better than :

string div = "<div class=\"className\">" + Environment.NewLine +
             "  <span>Mon text</span>" + Environment.NewLine +
             "</div>";

and better than

var sbDiv = new StringBuilder();
sbDiv.AppendLine("<div class=\"className\">");
sbDiv.AppendLine("    <span>Mon text</span>");
sbDiv.AppendLine("</div>");

What i use as a solution:

Greats thanks to @Yotam for its answer.

I write a little extension to make the alignment "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");
    }

Then i can use it like that :

private string GetHtml(string className)
{
    return $@"
            <div class=""{className}"">
                <span>Texte</span>
            </div>".AlignFromFirstLine();
}

That return the correct html :

<div class="myClassName">
    <span>Texte</span>
</div>

One limitation is that it will only work with space indentation...

Any improvement will be welcome !


Solution

  • You could wrap the string to the next line to get the desired indentation:

        string div = 
    @"
    <div class=""className"">
        <span>Mon text</span>
    </div>"
    .TrimStart(); // to remove the additional new-line at the beginning
    

    Another nice solution (disadvantage: depends on the indentation level!)

            string div = @"
            <div class=""className"">
            <span>Mon text</span>
            </div>".TrimStart().Replace("\n            ", "\n");
    

    It just removes the indentation out of the string. make sure the number of spaces in the first string of the Replace is the same amount of spaces your indentation has.