How to automatically remove trailing whitespace in Visual Studio 2008?

Viewed 93150

Is it possible to configure Visual Studio 2008 to automatically remove whitespace characters at the end of each line when saving a file? There doesn't seem to be a built-in option, so are there any extensions available to do this?

16 Answers

Find/Replacing using Regular Expressions

In the Find and Replace dialog, expand Find Options, check Use, choose Regular expressions

Find What: ":Zs#$"

Replace with: ""

click Replace All

In other editors (a normal Regular Expression parser) ":Zs#$" would be "\s*$".

You can create a macro that executes after a save to do this for you.

Add the following into the EnvironmentEvents Module for your macros.

Private saved As Boolean = False
Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
                                         Handles DocumentEvents.DocumentSaved
    If Not saved Then
        Try
            DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                                 "\t", _
                                 vsFindOptions.vsFindOptionsRegularExpression, _
                                 "  ", _
                                 vsFindTarget.vsFindTargetCurrentDocument, , , _
                                 vsFindResultsLocation.vsFindResultsNone)

            ' Remove all the trailing whitespaces.
            DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                                 ":Zs+$", _
                                 vsFindOptions.vsFindOptionsRegularExpression, _
                                 String.Empty, _
                                 vsFindTarget.vsFindTargetCurrentDocument, , , _
                                 vsFindResultsLocation.vsFindResultsNone)

            saved = True
            document.Save()
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
        End Try
    Else
        saved = False
    End If
End Sub

I've been using this for some time now without any problems. I didn't create the macro, but modified it from the one in ace_guidelines.vsmacros which can be found with a quick google search.

Before saving you may be able to use the auto-format shortcut CTRL+K+D.

You can do this easily with these three actions:

  • Ctrl + A (select all text)

  • Edit -> Advanced -> Delete Horizontal Whitespace

  • Edit -> Advanced -> Format Selection

Wait a few seconds and done.

It's Ctrl + Z'able in case something went wrong.

Taking elements from all the answers already given, here's the code I ended up with. (I mainly write C++ code, but it's easy to check for different file extensions, as needed.)

Thanks to everyone who contributed!

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
    Handles DocumentEvents.DocumentSaved
    Dim fileName As String
    Dim result As vsFindResult

    Try
        fileName = document.Name.ToLower()

        If fileName.EndsWith(".cs") _
        Or fileName.EndsWith(".cpp") _
        Or fileName.EndsWith(".c") _
        Or fileName.EndsWith(".h") Then
            ' Remove trailing whitespace
            result = DTE.Find.FindReplace( _
                vsFindAction.vsFindActionReplaceAll, _
                "{:b}+$", _
                vsFindOptions.vsFindOptionsRegularExpression, _
                String.Empty, _
                vsFindTarget.vsFindTargetFiles, _
                document.FullName, _
                "", _
                vsFindResultsLocation.vsFindResultsNone)

            If result = vsFindResult.vsFindResultReplaced Then
                ' Triggers DocumentEvents_DocumentSaved event again
                document.Save()
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub

Unless this is a one-person project, don't do it. It's got to be trivial to diff your local files against your source code repository, and clearing whitespace would change lines you don't need to change. I totally understand; I love to get my whitespace all uniform – but this is something you should give up for the sake of cleaner collaboration.

I think that the Jeff Muir version could be a little improved if it only trims source code files (in my case C#, but is easy to add more extensions). Also I added a check to ensure that the document window is visible because some situations without that check show me strange errors (LINQ to SQL files '*.dbml', for example).

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) Handles DocumentEvents.DocumentSaved
    Dim result As vsFindResult
    Try
        If (document.ActiveWindow Is Nothing) Then
            Return
        End If
        If (document.Name.ToLower().EndsWith(".cs")) Then
            document.Activate()
            result = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, ":Zs+$", vsFindOptions.vsFindOptionsRegularExpression, String.Empty, vsFindTarget.vsFindTargetCurrentDocument, , , vsFindResultsLocation.vsFindResultsNone)
            If result = vsFindResult.vsFindResultReplaced Then
                document.Save()
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message & Chr(13) & "Document: " & document.FullName, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub

I use ArtisticStyle (C++) to do this and also reformat my code. However, I had to add this as an external tool and you need to trigger it yourself so you might not like it.

However, I find it excellent that I can reformat code in more custom way (for example, multiline function parameters) that I can pay the price of running it manually. The tool is free.

A simple addition is to remove carriage returns during the save.

' Remove all the carriage returns.
result = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                             "\x000d\x000a", _
                             vsFindOptions.vsFindOptionsRegularExpression, _
                             "\x000a", _
                             vsFindTarget.vsFindTargetCurrentDocument, , , _
                             vsFindResultsLocation.vsFindResultsNone)

The key to this working is changing \x000d\x000a to \x000a. The \x prefix indicates a Unicode pattern. This will automate the process of getting source files ready for Linux systems.

Related