Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically align similar lines of code using whitespace in Visual Studio

Is there an existing macro or plugin which will turn this

public string Name { get; set; }
public int Age { get; set; }
public Person Mother { get; set; }

into this?

public string Name   { get; set; }
public int    Age    { get; set; }
public Person Mother { get; set; }

I'll have a go at describing the algorithm which I think is intuitively obvious - (for a particular selection) make each token on a line as left as possible, but not more left than any token of the same index on any of the other lines.

like image 207
Pete Montgomery Avatar asked Nov 29 '22 04:11

Pete Montgomery


2 Answers

Here is a primitive "Align Properties" macro to demonstrate how to accomplish this type of functionality using Visual Studio macros.

Sub AlignProperties()
    Dim win As EnvDTE.Window = DTE.ActiveWindow
    If win.Type <> EnvDTE.vsWindowType.vsWindowTypeDocument Then
        MsgBox("This macro can only be run in an active text editor window.")
        Exit Sub
    End If

    ' Determine the affected lines.
    Dim startLine As Integer = DTE.ActiveDocument.Selection.TopLine
    Dim endLine As Integer = DTE.ActiveDocument.Selection.BottomLine
    If endLine < startLine Then
        Dim temp As Integer = startLine
        startLine = endLine
        endLine = temp
    End If
    endLine = endLine - 1

    ' Parse the four columns: modifier, type, identifier, and rest.
    Dim regex = New Regex("(\s+)(.*)\s+(.*)\s+(.*)\s+({.*)")
    Dim leading As String = Nothing
    Dim array(endLine - startLine, 3) As String
    Dim widths(3) As Integer
    For i As Integer = 0 To endLine - startLine
        DTE.ActiveDocument.Selection.GotoLine(startLine + i)
        DTE.ActiveDocument.Selection.SelectLine()
        Dim line As String = DTE.ActiveDocument.Selection.text()
        Dim match As Match = regex.Match(line)
        If leading = Nothing Then
            leading = match.Groups(1).ToString()
        End If
        For j As Integer = 0 To 3
            Dim text As String = match.Groups(j + 2).ToString()
            array(i, j) = text
            widths(j) = Math.Max(widths(j), text.Length)
        Next
    Next
    widths(3) = 0

    ' Align the four columns.
    DTE.UndoContext.Open("Align Properties")
    Try
        For i As Integer = 0 To endLine - startLine
            DTE.ActiveDocument.Selection.GotoLine(startLine + i)
            DTE.ActiveDocument.Selection.SelectLine()
            Dim line As String = DTE.ActiveDocument.Selection.text()
            Dim replacement = leading
            For j As Integer = 0 To 3
                Dim padded As String = array(i, j).PadRight(widths(j) + 1)
                replacement = replacement & padded
            Next
            DTE.ActiveDocument.Selection.text() = replacement
        Next
    Finally
        DTE.UndoContext.Close()
    End Try
End Sub

Before:

Before

After:

After

like image 135
Rick Sladkey Avatar answered Dec 09 '22 10:12

Rick Sladkey


Not quite a full solution, but Productivity Power Tools has something similar called "Align Assignments":

This extension is useful for making your code a little more readable by aligning the assignments when you type Ctrl+Alt+] such that it takes this:

_test = test;
_commandTarget = commandTarget;
_state = state;

And turns it into this:

_test          = test;
_commandTarget = commandTarget;
_state         = state;
like image 34
Simon P Stevens Avatar answered Dec 09 '22 09:12

Simon P Stevens