Wie entferne ich nachgestellte Leerzeichen in Visual Studio 2008 automatisch?

122

Ist es möglich, Visual Studio 2008 so zu konfigurieren, dass Leerzeichen am Ende jeder Zeile beim Speichern einer Datei automatisch entfernt werden? Es scheint keine integrierte Option zu geben. Gibt es dafür Erweiterungen?

ChrisN
quelle
1
Hinweis für diejenigen, die dies lesen und Visual Studio 2010 verwenden: Wenn Sie die PowerCommands-Erweiterung von Microsoft installieren, können Sie das Dokument beim Speichern der Datei automatisch formatieren lassen (aktivieren Sie diese Funktion über Extras / Optionen). Dadurch werden unter anderem unnötige nachgestellte Leerzeichen entfernt.
Steinar

Antworten:

68

CodeMaid ist eine sehr beliebte Visual Studio-Erweiterung und führt dies automatisch zusammen mit anderen nützlichen Bereinigungen durch.

Ich habe es so eingestellt, dass beim Speichern eine Datei bereinigt wird, was meiner Meinung nach die Standardeinstellung ist.

arserbin3
quelle
1
Dies ist die beste Lösung auf dieser Seite. Es ist einfach zu konfigurieren, wird bei Bedarf oder beim Speichern automatisch für Sie erledigt, lässt sich gut in VS integrieren und verfügt über viele andere sehr nützliche Funktionen. Guter Fund arserbin3.
Chris R
Es gibt keine Möglichkeit, die vollständige Codeformatierung in dieser Erweiterung zu deaktivieren, sodass sie beispielsweise nicht mit benutzerdefinierten Einrückungsstilen kompatibel ist.
Aemxdp
@Andriy Ich verstehe nicht, was du meinst. Es folgt jeder benutzerdefinierten Einrückung, die Sie in Visual Studio festgelegt haben.
Stellen Sie sie unter Extras
@ arserbin3 Ich meine, wenn Sie Ihren Code wie folgt formatieren möchten - pastebin.com/uJqBQ1u2 - haben Sie kein Glück, denn beim Speichern wird Code wie pastebin.com/761Lzra7 oder ähnliches automatisch neu formatiert , je nachdem Optionen. Und es gibt keine Möglichkeit, Einrückungsregeln vollständig auszuschalten. Und ohne Codemaid wird die Neuformatierung von Dateien nicht automatisch ausgeführt, sodass Sie Ihre Datei mit dieser Art von Einzug speichern können.
Aemxdp
6
@ arserbin3 Ich denke du vermisst Andriys Punkt. Ich arbeite in einem riesigen Open-Source-Projekt. Ich weiß nicht besitzen , den Code - ich einen Beitrag zur Code. Ich kann die Einrückungsrichtlinien des Projekts nicht ändern. Ich möchte, dass VisualStudio nachfolgende Leerzeichen entfernt, wenn ich eine Datei ändere, und ich weiß nicht, was ich mit irgendetwas anderem in der Datei (Tabulatoren, Leerzeichen, Einrückungen usw.) anfangen soll. Bisher ist VisualStudio die einzige IDE, mit der ich gearbeitet habe und die dies nicht kann. Jeder andere halbgebackene Editor (geschweige denn IDE) kann dies tun. Ich kann CodeMaid nicht für eine bestimmte Formatierung konfigurieren, da die Formatierung variiert.
Kliteyn
71

Suchen / Ersetzen mit regulären Ausdrücken

Erweitern Sie im Dialogfeld Suchen und Ersetzen die Option Suchoptionen , aktivieren Sie Verwenden und wählen Sie Reguläre Ausdrücke

Finden Sie was : " :Zs#$"

Ersetzen durch : ""

Klicken Sie auf Alle ersetzen

In anderen Editoren (einem normalen Parser für reguläre Ausdrücke) :Zs#$wäre " \s*$" " ".

Greg Ogle
quelle
44
In VS2012 würde ich verwenden:[^\S\r\n]+(?=\r?$)
M. Dudley
4
Wenn Sie Registerkarten verwenden, [:Zs\t]#$ist dies eine nützliche Anpassung.
Dlanod
Wie binde ich es an das File On Save-Ereignis, damit es jedes Mal ausgeführt wird, wenn ich eine Datei speichere?
David Ferenczy Rogožan
30

Sie können ein Makro erstellen, das nach dem Speichern ausgeführt wird, um dies für Sie zu tun.

Fügen Sie dem EnvironmentEvents-Modul für Ihre Makros Folgendes hinzu.

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

Ich benutze dies seit einiger Zeit ohne Probleme. Ich habe das Makro nicht erstellt, sondern von dem in ace_guidelines.vsmacros geändert, das mit einer schnellen Google-Suche gefunden werden kann.


quelle
8
Beachten Sie, dass dadurch auch Tabulatoren durch zwei Leerzeichen ersetzt werden.
Crdx
Wo platzieren Sie diese Dokumentereignisskripte?
Xagyg
Wäre es nicht besser, dies vor dem Speichern zu tun, damit Sie nicht die nervige VS-Eingabeaufforderung erhalten, die besagt: "Hey, der Text hat sich seit dem letzten Speichern geändert. Möchten Sie neu laden?"
jedmao
2
Leider keine Makros mehr in VS 2013.
Nathan Baulch
17

Vor dem Speichern können Sie möglicherweise die Verknüpfung zum automatischen Formatieren CTRL+ K+ verwenden D.

Vyrotek
quelle
11

Mit diesen drei Aktionen können Sie dies ganz einfach tun:

  • Ctrl+ A(Alle Texte auswählen)

  • Bearbeiten -> Erweitert -> Horizontales Leerzeichen löschen

  • Bearbeiten -> Erweitert -> Formatauswahl

Warten Sie einige Sekunden und fertig.

Es ist Ctrl+ Z‚ in der Lage, falls etwas schief gelaufen ist .

iPixel
quelle
1
Es gibt einen Shorcut dafür: Strg + W, dann geben Sie Edit.RemoveHorizontalWhitespace
Josh
8

Hier ist der Code, mit dem ich am Ende Elemente aus allen bereits gegebenen Antworten erhalten habe. (Ich schreibe hauptsächlich C ++ - Code, aber es ist einfach, bei Bedarf nach verschiedenen Dateierweiterungen zu suchen.)

Vielen Dank an alle, die dazu beigetragen haben!

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
quelle
2

Ich verwende VWD 2010 Express, wo Makros leider nicht unterstützt werden. Also habe ich nur tun , Kopieren / Einfügen in Notepad ++ links oben Menü Edit> Blank Operations> Trim Trailing Spacegibt es weitere ähnliche zu verfügbaren Operationen. Kopieren Sie es anschließend in Visual Studio.

Sie können auch NetBeans anstelle von Notepad ++ verwenden, das im Menü "Quelle" die Option "Nachgestellte Leerzeichen entfernen" enthält.

Evgenii
quelle
Finden / ersetzen Sie einfach: b + $ durch eine leere Zeichenfolge und Sie können dies in den Express-Editionen von VS tun.
Legalisieren Sie den
1

Tun Sie es nicht, es sei denn, dies ist ein Ein-Personen-Projekt. Es muss trivial sein, Ihre lokalen Dateien von Ihrem Quellcode-Repository zu unterscheiden, und das Löschen von Leerzeichen würde Zeilen ändern, die Sie nicht ändern müssen. Ich verstehe vollkommen; Ich liebe es, mein Leerzeichen einheitlich zu gestalten - aber das sollten Sie aufgeben, um eine sauberere Zusammenarbeit zu gewährleisten.

Kevin Conner
quelle
17
Die meisten guten Diff-Tools ignorieren unwichtige Unterschiede wie nachgestellte Leerzeichen. Wenn Ihr Werkzeug dann nicht bekommt Jenseits von Vergleichen scootersoftware.com
Jim McKeeth
19
Wenn jeder im Unternehmen / Projekt dies tut, sind die Unterschiede sauber. Sie müssen nur alle Leerzeichen einmal bereinigen. Dann haben Sie ein einziges Commit, das in Zukunft nur Leerzeichen und keine Leerzeichenprobleme behebt.
ThiefMaster
Das ist richtig. Aber ob das fliegt, hängt vom Team ab. Das Hinzufügen eines zusätzlichen Schritts zu jedem Job oder sogar einer zusätzlichen Einstellung, um synchron zu bleiben, führt zu unnötiger Reibung. Wenn sich das Team ändern kann oder wenn Teammitglieder ihre eigene IDE usw. auswählen können, empfehle ich Ihnen, das Leerzeichen einfach zu lassen. Es ist keine so große Sache.
Kevin Conner
3
Das Problem bei der Bereinigung von Leerzeichen und Einrückungen besteht darin, dass die Effektivität von Quellcodeverwaltungsfunktionen wie Annotate verringert wird. Dieses Problem wird von Beyond Compare nicht gelöst. Besser gleich beim ersten Mal richtig machen.
Jammycakes
4
@ KevinConner Es scheint IMO viel schwieriger zu sein, falsche Leerzeichen konsistent zu halten, als sie zu Beginn des Projekts einmal mit einem riesigen Leerzeichen-Commit zu beheben. Dann wird es jeder wissen, dessen Editor dumm und kaputt ist, wenn er seine Unterschiede überprüft, bevor er sich verpflichtet.
Dan Bechard
1

Ich denke, dass die Jeff Muir- Version ein wenig verbessert werden könnte, wenn sie nur Quellcodedateien schneidet (in meinem Fall C #, aber es ist einfach, weitere Erweiterungen hinzuzufügen). Außerdem habe ich eine Prüfung hinzugefügt, um sicherzustellen, dass das Dokumentfenster sichtbar ist, da einige Situationen ohne diese Prüfung seltsame Fehler anzeigen (z. B. LINQ to SQL-Dateien '* .dbml').

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
quelle
0

Ich glaube, ich habe eine Version dieses Makros, die VS2010 auf Refactor nicht zum Absturz bringt und auch die IDE beim Speichern von Nicht-Text-Dateien nicht hängen lässt. Versuche dies:

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
julianisch
quelle
0

Ich benutze dazu ArtisticStyle (C ++) und formatiere meinen Code neu. Ich musste dies jedoch als externes Tool hinzufügen und Sie müssen es selbst auslösen, damit es Ihnen möglicherweise nicht gefällt.

Ich finde es jedoch hervorragend, dass ich Code auf benutzerdefiniertere Weise neu formatieren kann (z. B. mehrzeilige Funktionsparameter), um den Preis für die manuelle Ausführung zu zahlen. Das Tool ist kostenlos.

Marcin Gil
quelle
0

Aufbauend auf Dyaus 'Antwort und einem regulären Ausdruck aus einem Verbindungsbericht ist hier ein Makro, das das Speichern aller Elemente behandelt, Tabulatoren nicht durch Leerzeichen ersetzt und keine statische Variable erfordert. Es ist ein möglicher Nachteil? Es scheint ein wenig langsam, vielleicht aufgrund mehrerer Anrufe an 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

Für alle anderen, die versuchen, dies in einem Visual Studio 2012-Add-In zu verwenden, lautet der reguläre Ausdruck, den ich letztendlich verwendet habe [ \t]+(?=\r?$)(vergessen Sie nicht, die Backslashes bei Bedarf zu umgehen). Ich kam hier nach mehreren vergeblichen Versuchen , die Probleme mit einer zu beheben Raw - Konvertierung von {:b}+$Versagen des Wagenrücklauf zu entsprechen.

Michael Urman
quelle
-1

Dies ist ein wirklich gutes Beispiel dafür, wie nachgestellte Leerzeichen entfernt werden. Es gibt einige Dinge, die ich basierend auf dem, was ich mit diesem Makro entdeckt habe, ändern würde. Zunächst konvertiert das Makro Tabulatoren automatisch in Leerzeichen. Dies ist nicht immer wünschenswert und kann dazu führen, dass sich die Situation für Menschen, die Tabs lieben (normalerweise Linux-basiert), verschlimmert. Das Tab-Problem ist sowieso nicht wirklich dasselbe wie das zusätzliche Whitespace-Problem. Zweitens geht das Makro davon aus, dass nur eine Datei gleichzeitig gespeichert wird. Wenn Sie mehrere Dateien gleichzeitig speichern, wird das Leerzeichen nicht korrekt entfernt. Der Grund ist einfach. Das aktuelle Dokument wird als das Dokument betrachtet, das Sie sehen können. Drittens werden die Suchergebnisse nicht auf Fehler überprüft. Diese Ergebnisse können eine bessere Aufklärung darüber geben, was als nächstes zu tun ist. Wenn beispielsweise kein Leerzeichen gefunden und ersetzt wird, Die Datei muss nicht erneut gespeichert werden. Im Allgemeinen gefiel mir nicht, dass die globale Flagge gespeichert werden muss oder nicht. Es neigt dazu, aufgrund unbekannter Zustände nach Ärger zu fragen. Ich vermute, die Flagge wurde nur hinzugefügt, um eine Endlosschleife zu verhindern.

    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

Ich habe Debug-Meldungsfelder hinzugefügt, um zu sehen, was los ist. Es wurde sehr deutlich, dass das Speichern mehrerer Dateien nicht funktionierte. Wenn Sie mit ihnen spielen möchten, kommentieren Sie diese Zeilen aus.

Der Hauptunterschied besteht in der Verwendung von document.Activate (), um das Dokument in den Vordergrund des aktiven aktuellen Dokuments zu zwingen. Wenn das Ergebnis 4 ist, bedeutet dies, dass der Text ersetzt wurde. Null bedeutet, dass nichts passiert ist. Sie sehen zwei Speicherungen für jede Datei. Der erste wird ersetzen und der zweite wird nichts tun. Möglicherweise kann es zu Problemen kommen, wenn der Speicher die Datei nicht schreiben kann. Hoffentlich wird dieses Ereignis in diesem Fall nicht aufgerufen.

Vor dem ursprünglichen Skript war mir nicht bekannt, wie die Skripterstellung in Visual Studio funktioniert. Es ist etwas überraschend, dass Visual Basic als Hauptschnittstelle verwendet wird, aber es funktioniert einwandfrei für das, was es tun muss.

Jeff Muir
quelle
Eine Änderung besteht darin, das Speichern und Wiederherstellen des Fokus in dem Fenster zu unterstützen, das zu Beginn des Speichers den Fokus hatte. Speichern Sie das aktive Dokument einfach nach dem Try (mit currdoc = DTE.ActiveDocument) und vor dem document.Activate (). Aktivieren Sie nach Abschluss des Speichervorgangs einfach das Originaldokument (currdoc.Activate ()). Es sieht ein bisschen komisch aus, wenn der Fokus während des Speicherns umgeschaltet wird, aber es ist besser, als den Fokus auf Code zu verlieren, den Sie nicht gesehen haben.
Jeff Muir
-1

Eine einfache Ergänzung besteht darin, Wagenrückläufe während des Speicherns zu entfernen.

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

Der Schlüssel zu dieser Arbeit ist das Ändern von \ x000d \ x000a in \ x000a. Das Präfix \ x gibt ein Unicode-Muster an. Dies automatisiert den Prozess der Vorbereitung von Quelldateien für Linux-Systeme.

Jeff Muir
quelle