¿Cómo eliminar automáticamente los espacios en blanco finales en Visual Studio 2008?

122

¿Es posible configurar Visual Studio 2008 para eliminar automáticamente los espacios en blanco al final de cada línea al guardar un archivo? No parece haber una opción incorporada, ¿hay extensiones disponibles para hacer esto?

ChrisN
fuente
1
Nota para quienes lean esto y estén usando Visual Studio 2010: si instala la extensión PowerCommands de Microsoft, puede tener el documento formateado automáticamente al guardar el archivo (active esta función a través de Herramientas / Opciones). Esto, entre otras cosas, eliminará los espacios en blanco finales innecesarios.
steinar

Respuestas:

68

CodeMaid es una extensión de Visual Studio muy popular y lo hace automáticamente junto con otras limpiezas útiles.

Lo configuré para limpiar un archivo al guardar, que creo que es el predeterminado.

arserbin3
fuente
1
Esta es la mejor solución en esta página. Es fácilmente configurable, se realiza automáticamente a pedido o al guardar, se integra muy bien con VS, tiene muchas otras características muy útiles. Buen hallazgo arserbin3.
Chris R
No hay forma de desactivar el formato de código completo en esta extensión, por lo que es incompatible con, por ejemplo, estilos de sangría personalizados.
aemxdp
@Andriy No entiendo lo que quieres decir. Sigue cualquier sangría personalizada que establezca en Visual Studio. Configúrelos en Herramientas> Opciones> Editor de texto> [Idioma]> Pestañas
arserbin3
@ arserbin3 Quiero decir, que si desea formatear su código de esta manera - pastebin.com/uJqBQ1u2 - no tiene suerte, porque al guardarlo formateará automáticamente el código como pastebin.com/761Lzra7 o algo así, dependiendo de opciones. Y no hay opción para desactivar las reglas de sangría por completo. Y sin codemaid, el reformateo de archivos no se ejecuta automáticamente, por lo que puede guardar su archivo con ese tipo de sangría.
aemxdp
66
@ arserbin3 Creo que te estás perdiendo el punto de Andriy. Estoy trabajando en un gran proyecto de código abierto. No soy dueño del código, estoy contribuyendo al código. No puedo cambiar las pautas de sangría del proyecto. Quiero que VisualStudio elimine los espacios en blanco finales cuando modifico algún archivo, y no sé qué alterar con nada más en el archivo (pestañas, espacios, sangría, etc.). Hasta ahora, VisualStudio es el único IDE con el que he trabajado que no puede hacerlo. Cualquier otro editor a medias (por no hablar de IDE) puede hacerlo. No puedo configurar CodeMaid con algún formato, porque el formato varía.
kliteyn
71

Buscar / reemplazar usando expresiones regulares

En el cuadro de diálogo Buscar y reemplazar, expanda Opciones de búsqueda , marque Usar , elija Expresiones regulares

Encuentra qué : " :Zs#$"

Reemplazar con : ""

haga clic en Reemplazar todo

En otros editores (un analizador normal de expresiones regulares) " :Zs#$" sería " \s*$".

Greg Ogle
fuente
44
En VS2012 usaría:[^\S\r\n]+(?=\r?$)
M. Dudley
44
Si usa pestañas, [:Zs\t]#$es una adaptación útil.
dlanod
¿Cómo vincularlo al evento File On Save para que se ejecute cada vez que guardo un archivo, por favor?
David Ferenczy Rogožan
30

Puede crear una macro que se ejecute después de guardar para hacer esto por usted.

Agregue lo siguiente al módulo EnvironmentEvents para sus 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

He estado usando esto por algún tiempo sin ningún problema. No creé la macro, pero la modifiqué de la de ace_guidelines.vsmacros que se puede encontrar con una búsqueda rápida en Google.


fuente
8
Tenga en cuenta que esto también reemplaza las pestañas con dos espacios.
crdx
¿Dónde colocas estos scripts de eventos de documentos?
xagyg
¿No sería mejor hacer esto antes de guardar, para que no reciba ese molesto mensaje de VS que dice: "Hey, el texto ha cambiado desde la última vez que guardó. ¿Desea volver a cargar?"
jedmao 05 de
2
Desafortunadamente, no más macros en VS 2013.
Nathan Baulch
17

Antes de guardar, puede utilizar el acceso directo de formato automático CTRL+ K+ D.

Vyrotek
fuente
11

Puede hacer esto fácilmente con estas tres acciones:

  • Ctrl+ A(seleccionar todo el texto)

  • Editar -> Avanzado -> Eliminar espacio en blanco horizontal

  • Editar -> Avanzado -> Selección de formato

Espera unos segundos y listo.

Es Ctrl+ Z'capaz en caso de que algo salga mal.

iPixel
fuente
1
Hay un shorcut para hacer esto: ctrl + w, luego escriba Edit.RemoveHorizontalWhitespace
Josh
8

Tomando elementos de todas las respuestas ya dadas, aquí está el código con el que terminé. (Principalmente escribo código C ++, pero es fácil verificar si hay diferentes extensiones de archivo, según sea necesario).

¡Gracias a todos los que contribuyeron!

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
ChrisN
fuente
2

Estoy usando VWD 2010 Express donde las macros no son compatibles, desafortunadamente. Así que simplemente copiar / pegar en Notepad ++ menú superior izquierda Edit> Blank Operations> Trim Trailing Spacehay otras operaciones disponibles también. Luego copie / pegue nuevamente en Visual Studio.

También se puede usar NetBeans en lugar de Notepad ++, que tiene "Eliminar espacios finales" en el menú "Fuente".

Evgenii
fuente
Simplemente busque / reemplace: b + $ con una cadena vacía y puede hacerlo en las ediciones express de VS.
legalizar el
1

A menos que este sea un proyecto de una sola persona, no lo haga. Debe ser trivial diferenciar sus archivos locales contra su repositorio de código fuente, y borrar espacios en blanco cambiaría las líneas que no necesita cambiar. Entiendo perfectamente; Me encanta que mi espacio en blanco sea todo uniforme, pero esto es algo a lo que debes renunciar por una colaboración más limpia.

Kevin Conner
fuente
17
La mayoría de las buenas herramientas diff ignoran las diferencias sin importancia como el espacio en blanco al final. Si su herramienta no es así, obtenga Beyond Compare de scootersoftware.com
Jim McKeeth
19
Si todos en la empresa / proyecto lo hacen, las diferencias serán limpias. Solo tendrá que limpiar todos los espacios en blanco una vez. Luego, tiene una única confirmación que solo soluciona los problemas de espacios en blanco y no espacios en blanco en el futuro.
ThiefMaster
Es verdad. Pero si eso vuela dependerá del equipo. Agregar un paso adicional al trabajo de todos, o incluso una configuración adicional para mantenerse sincronizado, tiende a crear fricciones innecesarias. Si el equipo puede cambiar, o si los miembros del equipo pueden elegir su propio IDE, etc., le sugiero que deje el espacio en blanco. No es tan grande de un acuerdo.
Kevin Conner
3
El problema con los espacios en blanco y la limpieza de sangría es que reduce la efectividad de las funciones de control de fuente como anotar, y este es un problema que Beyond Compare no resolverá. Es mejor hacerlo bien la primera vez.
jammycakes
44
@KevinConner Parece una OMI mucho más difícil mantener coherente el espacio en blanco incorrecto que arreglarlo una vez con un compromiso de espacio en blanco gigante al comienzo del proyecto. Entonces, cualquiera cuyo editor sea estúpido y quebrado lo sabrá cuando verifiquen sus diferencias antes de comprometerse.
Dan Bechard
1

Creo que la versión de Jeff Muir podría mejorarse un poco si solo recorta los archivos de código fuente (en mi caso C #, pero es fácil agregar más extensiones). También agregué una verificación para asegurarme de que la ventana del documento sea visible porque algunas situaciones sin esa verificación me muestran errores extraños (LINQ to SQL files '* .dbml', por ejemplo).

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
David Abella
fuente
0

Creo que tengo una versión de esta macro que no bloqueará VS2010 en el refactorizador, y tampoco bloqueará el IDE al guardar archivos que no sean de texto. Prueba esto:

Private Sub DocumentEvents_DocumentSaved( _
    ByVal document As EnvDTE.Document) _
    Handles DocumentEvents.DocumentSaved
    ' See if we're saving a text file
    Dim textDocument As EnvDTE.TextDocument = _
        TryCast(document.Object(), EnvDTE.TextDocument)

    If textDocument IsNot Nothing Then
        ' Perform search/replace on the text document directly
        ' Convert tabs to spaces
        Dim convertedTabs = textDocument.ReplacePattern("\t", "    ", _
            vsFindOptions.vsFindOptionsRegularExpression)

        ' Remove trailing whitespace from each line
        Dim removedTrailingWS = textDocument.ReplacePattern(":Zs+$", "", _
            vsFindOptions.vsFindOptionsRegularExpression)

        ' Re-save the document if either replace was successful
        ' (NOTE: Should recurse only once; the searches will fail next time)
        If convertedTabs Or removedTrailingWS Then
            document.Save()
        End If
    End If
End Sub
Julian
fuente
0

Utilizo ArtisticStyle (C ++) para hacer esto y también reformateo mi código. Sin embargo, tuve que agregar esto como una herramienta externa y debes activarlo tú mismo para que no te guste.

Sin embargo, me parece excelente poder reformatear el código de manera más personalizada (por ejemplo, parámetros de función multilínea) que puedo pagar el precio de ejecutarlo manualmente. La herramienta es gratis.

Marcin Gil
fuente
0

Basándose en la respuesta de Dyaus y una expresión regular de un informe de conexión , aquí hay una macro que maneja guardar todo, no reemplaza las pestañas con espacios y no requiere una variable estática. ¿Su posible inconveniente? Parece un poco lento, quizás debido a múltiples llamadas a FindReplace.

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
                                         Handles DocumentEvents.DocumentSaved
    Try
        ' Remove all the trailing whitespaces.
        If vsFindResult.vsFindResultReplaced = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                             "{:b}+$", _
                             vsFindOptions.vsFindOptionsRegularExpression, _
                             String.Empty, _
                             vsFindTarget.vsFindTargetFiles, _
                             document.FullName, , _
                             vsFindResultsLocation.vsFindResultsNone) Then
            document.Save()
        End If
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub

Para cualquier otra persona que intente usar esto en un complemento de Visual Studio 2012, la expresión regular que terminé usando es [ \t]+(?=\r?$)(no olvide escapar de las barras diagonales inversas si es necesario). Llegué aquí después de varios intentos inútiles de solucionar los problemas con una conversión cruda de {:b}+$no coincidir con el retorno del carro.

Michael Urman
fuente
-1

Este es un muy buen ejemplo de cómo eliminar los espacios en blanco finales. Hay algunas cosas que cambiaría en función de lo que descubrí usando esta macro. En primer lugar, la macro convierte automáticamente las pestañas en espacios. Esto no siempre es deseable y podría empeorar las cosas para las personas que aman las pestañas (generalmente basadas en Linux). El problema de tabulación no es realmente el mismo que el problema de espacio en blanco adicional de todos modos. En segundo lugar, la macro supone que solo se está guardando un archivo a la vez. Si guarda varios archivos a la vez, no eliminará correctamente el espacio en blanco. El motivo es simple. El documento actual se considera el documento que puede ver. En tercer lugar, no hace ningún error al comprobar los resultados de búsqueda. Estos resultados pueden dar una mejor inteligencia sobre qué hacer a continuación. Por ejemplo, si no se encuentra ningún espacio en blanco y se reemplaza, no hay necesidad de guardar el archivo nuevamente. En general, no me gustó la necesidad de guardar o no la bandera global. Tiende a pedir problemas basados ​​en estados desconocidos. Sospecho que la bandera se ha agregado únicamente para evitar un bucle infinito.

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

    Try
        document.Activate()

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

        'nameresult = document.Name & " " & Str$(result)

        'MsgBox(nameresult, , "Filename and result")

        If result = vsFindResult.vsFindResultReplaced Then
            'MsgBox("Document Saved", MsgBoxStyle.OkOnly, "Saved Macro")
            document.Save()
        Else
            'MsgBox("Document Not Saved", MsgBoxStyle.OkOnly, "Saved Macro")
        End If

    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try

End Sub

Agregué cuadros de mensaje de depuración para ayudar a ver lo que estaba sucediendo. Dejó muy claro que guardar varios archivos no funcionaba. Si quieres jugar con ellos, descomenta esas líneas.

La diferencia clave es usar document.Activate () para forzar el documento en el documento actual activo en primer plano. Si el resultado es 4, eso significa que el texto fue reemplazado. Cero significa que no pasó nada. Verá dos guardados para cada archivo. El primero reemplazará y el segundo no hará nada. Potencialmente podría haber problemas si el guardado no puede escribir el archivo, pero es de esperar que este evento no se llame si eso sucede.

Antes del guión original, no sabía cómo funcionaban los guiones en Visual Studio. Es un poco sorprendente que use Visual Basic como interfaz principal, pero funciona bien para lo que necesita hacer.

Jeff Muir
fuente
Un cambio a esto es permitir guardar y restaurar el foco en la ventana que tenía foco cuando comenzó el guardado. Simplemente guarde el documento activo después de Try (usando currdoc = DTE.ActiveDocument) y antes del documento.Activate (). Una vez completado el guardado, simplemente active el documento original (currdoc.Activate ()). Parece un poco extraño cuando se cambia el foco durante el guardado, pero es mejor que perder el foco en el código que no estaba viendo.
Jeff Muir
-1

Una adición simple es eliminar los retornos de carro durante el guardado.

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

La clave de este trabajo es cambiar \ x000d \ x000a a \ x000a. El prefijo \ x indica un patrón Unicode. Esto automatizará el proceso de preparación de archivos fuente para sistemas Linux.

Jeff Muir
fuente