Search code examples
c#stringlinq

Efficient way to unindent lines of code stored in a string


I have a string[] which contains code. Each line contains some leading spaces. I need to 'unindent' the code as much as possible without changing the existing formatting.

For instance the contents of my string[] might be

                                         public class MyClass
                                         {
                                             private bool MyMethod(string s)
                                             {
                                                 return s == "";
                                             }
                                         }

I'd like to find a reasonably elegant and efficient method (LINQ?) to transform it to

public class MyClass
{
    private bool MyMethod(string s)
    {
        return s == "";
    }
}

To be clear I'm looking for

IEnumerable<string> UnindentAsMuchAsPossible(string[] content)
{
    return ???;
}

Solution

  • Building on Tim Schmelter's answer:

    static IEnumerable<string> UnindentAsMuchAsPossible(IEnumerable<string> lines, int tabWidth = 4)
    {
        if (!lines.Any())
        {
            return Enumerable.Empty<string>();
        }
    
        var minDistance = lines
            .Where(line => line.Length > 0)
            .Min(line => line
                .TakeWhile(Char.IsWhiteSpace)
                .Sum(c => c == '\t' ? tabWidth : 1));
        var spaces = new string(' ', tabWidth);
        return lines
            .Select(line => line.Replace("\t", spaces))
            .Select(line => line.Substring(Math.Min(line.Length, minDistance)));
    }
    

    This handles:

    • tab characters
    • source code that contains empty lines