Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way to unindent lines of code stored in a string

Tags:

string

c#

linq

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 ???;
}
like image 773
shamp00 Avatar asked May 23 '13 15:05

shamp00


3 Answers

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 input
        .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
like image 130
Timothy Shields Avatar answered Oct 03 '22 16:10

Timothy Shields


Just count the number of leading spaces on the first line, and then "remove" that many characters from the start of each line:

IEnumerable<string> UnindentAsMuchAsPossible(string[] content)
{
    int spacesOnFirstLine = content[0].TakeWhile(c => c == ' ').Count();
    return content.Select(line => line.Substring(spacesOnFirstLine));
}
like image 24
Servy Avatar answered Oct 03 '22 17:10

Servy


This should work:

static IEnumerable<string> UnindentAsMuchAsPossible(IEnumerable<string> input)
{
    int minDistance = input.Min(l => l.TakeWhile(Char.IsWhiteSpace).Count());
    return input.Select(l => l.Substring(minDistance));
}

It moves the code to the left, all lines with the same number of spaces.

For example:

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


string[] lines = testString.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
string[] unindentedArray = UnindentAsMuchAsPossible(lines).ToArray();
like image 21
Tim Schmelter Avatar answered Oct 03 '22 16:10

Tim Schmelter