Comment supprimer automatiquement les espaces blancs de fin dans Visual Studio 2008?

122

Est-il possible de configurer Visual Studio 2008 pour supprimer automatiquement les caractères d'espacement à la fin de chaque ligne lors de l'enregistrement d'un fichier? Il ne semble pas y avoir d'option intégrée, alors existe-t-il des extensions disponibles pour le faire?

ChrisN
la source
1
Note à ceux qui lisent ceci qui utilisent Visual Studio 2010: Si vous installez l'extension PowerCommands de Microsoft, vous pouvez avoir le document formaté automatiquement lors de l'enregistrement du fichier (activez cette fonctionnalité via Outils / Options). Cela supprimera entre autres les espaces blancs de fin inutiles.
steinar

Réponses:

68

CodeMaid est une extension Visual Studio très populaire et le fait automatiquement avec d'autres nettoyages utiles.

Je l'ai configuré pour nettoyer un fichier lors de l'enregistrement, ce qui, je crois, est la valeur par défaut.

arserbin3
la source
1
C'est la meilleure solution sur cette page. Il est facilement configurable, fait automatiquement pour vous à la demande ou lors d'une sauvegarde, il s'intègre bien avec VS, il a beaucoup d'autres fonctionnalités très utiles. Bonne trouvaille arserbin3.
Chris R
Il n'y a aucun moyen de désactiver la mise en forme complète du code dans cette extension, elle est donc incompatible, par exemple, avec les styles d'indentation personnalisés.
aemxdp
@Andriy je ne comprends pas ce que tu veux dire. Il suit l'indentation personnalisée que vous définissez dans Visual Studio. Définissez-les dans Outils> Options> Éditeur de texte> [Langue]> Onglets
arserbin3
@ arserbin3 Je veux dire, que si vous voulez formater votre code comme ça - pastebin.com/uJqBQ1u2 - vous n'avez pas de chance, car lors de l'enregistrement, il reformatera automatiquement le code comme pastebin.com/761Lzra7 ou quelque chose comme ça, selon options. Et il n'y a pas d'option pour désactiver complètement les règles d'indentation. Et sans codemaid, le reformatage des fichiers ne s'exécute pas automatiquement, vous pouvez donc enregistrer votre fichier avec ce type d'indentation.
aemxdp
6
@ arserbin3 Je pense que vous manquez l'argument d'Andriy. Je travaille sur un énorme projet open-source. Je ne possède pas le code - je contribue au code. Je ne peux pas modifier les directives d'indentation du projet. Je veux que VisualStudio supprime les espaces de fin lorsque je modifie un fichier, et je ne veux pas gâcher quoi que ce soit d'autre dans le fichier (tabulations, espaces, indentation, etc.). Jusqu'à présent, VisualStudio est le seul IDE avec lequel j'ai travaillé qui ne peut pas le faire. Tout autre éditeur à moitié cuit (sans parler de l'IDE) peut le faire. Je ne peux pas configurer CodeMaid pour un formatage, car le formatage varie.
kliteyn
71

Rechercher / remplacer à l'aide d'expressions régulières

Dans la boîte de dialogue Rechercher et remplacer, développez Options de recherche , cochez Utiliser , choisissez Expressions régulières

Trouver quoi : " :Zs#$"

Remplacer par : ""

cliquez sur Remplacer tout

Dans d'autres éditeurs (un analyseur d'expressions régulières normal ) " :Zs#$" serait " \s*$".

Greg Ogle
la source
44
Dans VS2012, j'utiliserais:[^\S\r\n]+(?=\r?$)
M. Dudley
4
Si vous utilisez des onglets, [:Zs\t]#$c'est une adaptation utile.
dlanod
Comment le lier à l'événement File On Save pour qu'il soit exécuté chaque fois que j'enregistre un fichier, s'il vous plaît?
David Ferenczy Rogožan
30

Vous pouvez créer une macro qui s'exécute après une sauvegarde pour le faire pour vous.

Ajoutez ce qui suit dans le module EnvironmentEvents pour vos 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

Je l'utilise depuis un certain temps maintenant sans aucun problème. Je n'ai pas créé la macro, mais je l'ai modifiée à partir de celle de ace_guidelines.vsmacros qui peut être trouvée avec une recherche rapide sur Google.


la source
8
Notez que cela remplace également les onglets avec deux espaces.
crdx
Où mettez-vous ces scripts d'événements de document?
xagyg
Ne serait-il pas préférable de le faire avant une sauvegarde, pour ne pas recevoir cette invite VS ennuyeuse qui dit: "Hé, le texte a changé depuis la dernière sauvegarde. Voulez-vous recharger?"
jedmao
2
Plus de macros dans VS 2013 malheureusement.
Nathan Baulch le
17

Avant d'enregistrer, vous pourrez peut-être utiliser le raccourci de formatage automatique CTRL+ K+ D.

Vyrotek
la source
11

Vous pouvez le faire facilement avec ces trois actions:

  • Ctrl+ A(sélectionner tout le texte)

  • Edition -> Avancé -> Supprimer l'espace blanc horizontal

  • Edition -> Avancé -> Format de la sélection

Attendez quelques secondes et c'est fait.

C'est Ctrl+ Z'capable en cas de problème.

iPixel
la source
1
Il y a un raccourci pour faire cela: ctrl + w, puis tapez Edit.RemoveHorizontalWhitespace
Josh
8

Prenant des éléments de toutes les réponses déjà données, voici le code avec lequel je me suis retrouvé. (J'écris principalement du code C ++, mais il est facile de vérifier les différentes extensions de fichiers, si nécessaire.)

Merci à tous ceux qui ont contribué!

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
la source
2

J'utilise VWD 2010 Express où les macros ne sont malheureusement pas prises en charge. Je viens donc de faire copier / coller dans du Bloc - notes haut de menu de gauche Edit> Blank Operations> Trim Trailing Spaceil y a d' autres opérations connexes disponibles aussi. Ensuite, copiez / collez à nouveau dans Visual Studio.

On peut également utiliser NetBeans au lieu de Notepad ++, qui a "Supprimer les espaces de fin" dans le menu "Source".

Evgenii
la source
Recherchez / remplacez simplement: b + $ par une chaîne vide et vous pouvez le faire dans les éditions express de VS.
légaliser
1

À moins qu'il ne s'agisse d'un projet individuel, ne le faites pas. Il doit être trivial de comparer vos fichiers locaux à votre référentiel de code source, et effacer les espaces changerait les lignes que vous n'avez pas besoin de changer. Je comprends parfaitement; J'adore que mes espaces blancs soient tous uniformes - mais c'est quelque chose que vous devriez abandonner pour une collaboration plus propre.

Kevin Conner
la source
17
La plupart des bons outils de comparaison ignorent les différences sans importance comme les espaces blancs de fin. Si votre outil ne passe pas au-delà de la comparaison de scootersoftware.com
Jim McKeeth
19
Si tout le monde dans l'entreprise / le projet le fait, les différences seront propres. Vous n'aurez qu'à nettoyer tous les espaces une fois. Ensuite, vous avez un seul commit qui corrige uniquement les espaces blancs et aucun problème d'espaces blancs à l'avenir.
ThiefMaster
C'est vrai. Mais si cela vole dépendra de l'équipe. Ajouter une étape supplémentaire au travail de chacun, ou même un paramètre supplémentaire pour rester synchronisé, a tendance à créer des frictions inutiles. Si l'équipe peut changer, ou si les membres de l'équipe choisissent leur propre IDE, etc., alors je vous suggère de laisser les espaces. Ce n'est pas si grave.
Kevin Conner du
3
Le problème avec le nettoyage des espaces et de l'indentation est qu'il réduit l'efficacité des fonctionnalités de contrôle de code source telles que l'annotation, et c'est un problème que Beyond Compare ne résoudra pas. Mieux vaut bien faire les choses du premier coup.
jammycakes
4
@KevinConner Il semble beaucoup plus difficile à l'OMI de garder la cohérence des mauvais espaces que de le réparer une fois avec un commit d'espace blanc géant au début du projet. Ensuite, quiconque dont l'éditeur est stupide et cassé le saura quand il vérifiera ses différences avant de s'engager.
Dan Bechard
1

Je pense que le version de Jeff Muir pourrait être un peu améliorée si elle ne supprime que les fichiers de code source (dans mon cas C #, mais il est facile d'ajouter plus d'extensions). J'ai également ajouté une vérification pour m'assurer que la fenêtre du document est visible car certaines situations sans cette vérification me montrent des erreurs étranges (LINQ to SQL files '* .dbml', par exemple).

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
la source
0

Je pense que j'ai une version de cette macro qui ne plantera pas VS2010 sur le refactor, et qui ne bloquera pas non plus l'IDE lors de l'enregistrement de fichiers non texte. Essaye ça:

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
julien
la source
0

J'utilise ArtisticStyle (C ++) pour faire cela et aussi reformater mon code. Cependant, j'ai dû l'ajouter en tant qu'outil externe et vous devez le déclencher vous-même pour ne pas l'aimer.

Cependant, je trouve excellent que je puisse reformater le code de manière plus personnalisée (par exemple, les paramètres de fonction multiligne) que je puisse payer le prix de son exécution manuelle. L'outil est gratuit.

Marcin Gil
la source
0

S'appuyant sur la réponse de Dyaus et une expression régulière d'un rapport de connexion , voici une macro qui gère tout enregistrer, ne remplace pas les tabulations par des espaces et ne nécessite pas de variable statique. Son inconvénient possible? Cela semble un peu lent, peut-être en raison de plusieurs appels à 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

Pour toute autre personne essayant de l'utiliser dans un complément Visual Studio 2012, l'expression régulière que j'ai fini par utiliser est [ \t]+(?=\r?$)(n'oubliez pas d'échapper les barres obliques inverses si nécessaire). Je suis arrivé ici après plusieurs tentatives vaines pour résoudre les problèmes avec une conversion brute de {:b}+$ne pas correspondre au retour chariot.

Michael Urman
la source
-1

Ceci est un très bon exemple de la façon de supprimer les espaces blancs de fin. Il y a quelques choses que je changerais en fonction de ce que j'ai découvert en utilisant cette macro. Tout d'abord, la macro convertit automatiquement les tabulations en espaces. Ce n'est pas toujours souhaitable et pourrait aggraver les choses pour les personnes qui aiment les onglets (généralement basés sur Linux). Le problème de tabulation n'est pas vraiment le même que le problème d'espace blanc supplémentaire de toute façon. Deuxièmement, la macro suppose qu'un seul fichier est enregistré à la fois. Si vous enregistrez plusieurs fichiers à la fois, cela ne supprimera pas correctement les espaces. La raison est simple. Le document actuel est considéré comme le document que vous pouvez voir. Troisièmement, il ne vérifie aucune erreur sur les résultats de la recherche. Ces résultats peuvent donner une meilleure information sur ce qu'il faut faire ensuite. Par exemple, si aucun espace n'est trouvé et remplacé, il n'est pas nécessaire de sauvegarder à nouveau le fichier. En général, je n'aimais pas la nécessité du drapeau global pour être sauvegardé ou non. Il a tendance à poser des problèmes en fonction d'états inconnus. Je soupçonne que le drapeau a été ajouté uniquement pour empêcher une boucle infinie.

    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

J'ai ajouté des boîtes de message de débogage pour aider à voir ce qui se passait. Cela montrait clairement que la sauvegarde de plusieurs fichiers ne fonctionnait pas. Si vous voulez jouer avec eux, décommentez ces lignes.

La principale différence consiste à utiliser document.Activate () pour forcer le document au premier plan du document actif actif. Si le résultat est 4, cela signifie que le texte a été remplacé. Zéro signifie que rien ne s'est passé. Vous verrez deux sauvegardes pour chaque fichier. Le premier remplacera et le second ne fera rien. Il pourrait y avoir des problèmes si la sauvegarde ne peut pas écrire le fichier, mais nous espérons que cet événement ne sera pas appelé si cela se produit.

Avant le script d'origine, je ne savais pas comment le script fonctionnait dans Visual Studio. Il est légèrement surprenant qu'il utilise Visual Basic comme interface principale, mais cela fonctionne très bien pour ce qu'il doit faire.

Jeff Muir
la source
Une modification apportée à cela consiste à prendre en charge l'enregistrement et la restauration du focus dans la fenêtre qui avait le focus au démarrage de l'enregistrement. Enregistrez simplement le document actif après le Try (en utilisant currdoc = DTE.ActiveDocument) et avant le document.Activate (). Une fois la sauvegarde terminée, rendez simplement le document original actif (currdoc.Activate ()). Cela a l'air un peu drôle lorsque la mise au point est inversée pendant la sauvegarde, mais c'est mieux que de perdre la concentration sur du code que vous ne regardiez pas.
Jeff Muir
-1

Un ajout simple consiste à supprimer les retours chariot pendant la sauvegarde.

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

La clé de ce fonctionnement est de changer \ x000d \ x000a en \ x000a. Le préfixe \ x indique un modèle Unicode. Cela automatisera le processus de préparation des fichiers source pour les systèmes Linux.

Jeff Muir
la source