如何在 Visual Studio 2008 中自动删除尾随空格?

Posted

技术标签:

【中文标题】如何在 Visual Studio 2008 中自动删除尾随空格?【英文标题】:How to automatically remove trailing whitespace in Visual Studio 2008? 【发布时间】:2010-09-10 02:59:20 【问题描述】:

是否可以将 Visual Studio 2008 配置为在保存文件时自动删除每行末尾的空白字符?似乎没有内置选项,那么是否有可用的扩展来执行此操作?

【问题讨论】:

使用 Visual Studio 2010 的读者请注意:如果您从 Microsoft 安装 PowerCommands 扩展,则可以在保存文件时自动格式化文档(通过工具/选项打开此功能) .除其他外,这将删除不必要的尾随空格。 【参考方案1】:

使用正则表达式查找/替换

在查找和替换对话框中,展开查找选项,勾选使用,选择正则表达式

查找内容:“:Zs#$

替换为:“”

点击全部替换

在其他编辑器(普通正则表达式解析器)中,“:Zs#$”将是“\s*$”。

【讨论】:

在 VS2012 中我会使用:[^\S\r\n]+(?=\r?$) 如果你使用标签,[:Zs\t]#$ 是一个有用的适应。 如何将它绑定到 File On Save 事件,以便每次我保存文件时都会执行? 在 VSC-1.56.2 中我使用 \s+$[ ]+$ :P【参考方案2】:

CodeMaid 是一个非常流行的 Visual Studio 扩展程序,它会自动执行此操作以及其他有用的清理。

下载:https://github.com/codecadwallader/codemaid/releases/tag/v0.4.3 现代下载:https://marketplace.visualstudio.com/items?itemName=SteveCadwallader.CodeMaid 文档:http://www.codemaid.net/documentation/#cleaning

我将它设置为在保存时清理文件,我认为这是默认设置。

【讨论】:

这是此页面上的最佳解决方案。它易于配置,按需或保存时自动为您完成,它与 VS 很好地集成,它还有许多其他非常有用的功能。很好地找到了 arserbin3。 在这个扩展中无法关闭完整的代码格式,因此它与自定义缩进样式等不兼容。 @Andriy 我不明白你的意思。它遵循您在 Visual Studio 中设置的任何自定义缩进。在工具 > 选项 > 文本编辑器 > [语言] > 选项卡中设置它们 @arserbin3 我的意思是,如果你想像这样格式化你的代码 - pastebin.com/uJqBQ1u2 - 你不走运,因为保存时它会自动重新格式化像 pastebin.com/761Lzra7 或类似的代码这取决于选项。并且没有完全关闭缩进规则的选项。如果没有 codemaid 文件重新格式化不会自动运行,因此您可以使用这种缩进保存文件。 @arserbin3 我认为你错过了安德烈的观点。我在一个巨大的开源项目中工作。我不拥有代码 - 我正在为代码做出贡献。我无法更改项目的缩进指南。我希望 VisualStudio 在我修改某些文件时删除尾随空格,并且我不会弄乱文件中的任何其他内容(制表符、空格、缩进等)。到目前为止,VisualStudio 是我使用过的唯一的 IDE,它无法做到这一点。任何其他半生不熟的编辑器(更不用说 IDE)都可以做到。我无法将 CodeMaid 配置为某些格式,因为格式不同。【参考方案3】:

您可以创建一个在保存后执行的宏来为您执行此操作。

将以下内容添加到您的宏的 EnvironmentEvents 模块中。

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

我已经使用了一段时间了,没有任何问题。我没有创建宏,而是根据 ace_guidelines.vsmacros 中的宏对其进行了修改,该宏可通过快速 google 搜索找到。

【讨论】:

请注意,这也将制表符替换为两个空格。 你把这些文档事件脚本放在哪里? 在保存之前执行此操作不是更好吗,这样您就不会收到烦人的 VS 提示:“嘿,自上次保存后文本已更改。您要重新加载吗? ?” 不幸的是,VS 2013 中没有更多的宏了。【参考方案4】:

在保存之前,您可以使用自动格式化快捷键CTRL+K+D

【讨论】:

【参考方案5】:

您可以通过以下三个操作轻松做到这一点:

Ctrl + A(选择所有文本)

编辑 -> 高级 -> 删除水平空白

编辑 -> 高级 -> 格式选择

等待几秒钟就完成了。

如果出现问题,可以使用 Ctrl + Z'。

【讨论】:

有一个快捷键:ctrl+w,然后输入Edit.RemoveHorizo​​ntalWhitespace 这个答案具有误导性,因为它还会删除缩进和所有格式。【参考方案6】:

从已经给出的所有答案中提取元素,这是我最终得到的代码。 (我主要写 C++ 代码,但很容易根据需要检查不同的文件扩展名。)

感谢所有贡献的人!

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

【讨论】:

【参考方案7】:

我个人喜欢 Trailing Whitespace Visualizer Visual Studio 扩展,它通过 Visual Studio 2012 得到支持。

【讨论】:

【参考方案8】:

您可以使用 Removing whitespace and rewriting comments, using regex searches

中描述的宏

【讨论】:

【参考方案9】:

除非这是一个人的项目,否则不要这样做。将本地文件与源代码存储库进行比较一定很简单,清除空格会更改您不需要更改的行。我完全理解;我喜欢让我的空白空间全部统一——但为了更清晰的协作,你应该放弃这一点。

【讨论】:

大多数优秀的差异工具都会忽略不重要的差异,例如尾随空格。如果您的工具没有,请从 scootersoftware.com 获得 Beyond Compare 如果公司/项目中的每个人都这样做,差异将是干净的。你只需要清理一次所有的空白。然后你有一个单一的提交,只修复空白,以后没有空白问题。 确实如此。但能否成功将取决于团队。为每个人的工作增加一个额外的步骤,甚至增加一个额外的设置来保持同步,往往会造成不必要的摩擦。如果团队可以改变,或者如果团队成员可以选择他们自己的 IDE 等,那么我建议你只保留空白。这没什么大不了的。 空白和缩进清理的问题在于它降低了注释等源代码控制功能的有效性,这是Beyond Compare无法解决的问题。最好第一次就做好。 @KevinConner 与在项目开始时用巨大的空白提交修复一次相比,保持错误空白一致似乎要困难得多。然后,任何编辑器愚蠢和破碎的人都会在提交前检查他们的差异时知道这一点。【参考方案10】:

不幸的是,我正在使用不支持宏的VWD 2010 Express。所以我只是复制/粘贴到Notepad++ 左上菜单Edit > Blank Operations > Trim Trailing Space 还有其他相关操作。然后复制/粘贴回 Visual Studio。

也可以使用NetBeans 代替Notepad++,后者在“源”菜单下有“删除尾随空格”。

【讨论】:

只需查找/替换 :b+$ 为空字符串,您可以在 VS 的 express 版本中执行此操作。【参考方案11】:

我认为 Jeff Muir 版本如果只修剪源代码文件(在我的例子中是 C#,但很容易添加更多扩展),可能会有所改进。我还添加了一项检查以确保文档窗口可见,因为在某些情况下没有该检查会显示奇怪的错误(例如 LINQ to SQL 文件“*.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

【讨论】:

【参考方案12】:

我想我有这个宏的一个版本,它不会在重构时使 VS2010 崩溃,并且在保存非文本文件时也不会挂起 IDE。试试这个:

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

【讨论】:

【参考方案13】:

我使用ArtisticStyle (C++) 来执行此操作并重新格式化我的代码。但是,我必须将其添加为外部工具,并且您需要自己触发它,因此您可能不喜欢它。

但是,我发现可以以更自定义的方式(例如,多行函数参数)重新格式化代码非常棒,我可以付出手动运行它的代价。该工具是免费的。

【讨论】:

【参考方案14】:

基于 Dyaus 的回答和来自 connect report 的正则表达式,这是一个处理全部保存的宏,不会用空格替换制表符,并且不需要静态变量。它可能的缺点?这似乎有点慢,可能是由于多次调用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

对于尝试在 Visual Studio 2012 加载项中使用它的任何其他人,我最终使用的正则表达式是 [ \t]+(?=\r?$)(如有必要,请不要忘记转义反斜杠)。在多次尝试解决raw conversion 或:b+$ 未能匹配回车符的问题后,我到达了这里。

【讨论】:

【参考方案15】:

这是一个很好的例子,说明如何删除尾随空格。根据我使用此宏的发现,我会更改一些内容。首先,宏自动将制表符转换为空格。这并不总是可取的,并且可能导致喜欢标签的人(通常基于 Linux)的情况变得更糟。无论如何,制表符问题与额外的空白问题并不完全相同。 其次,宏假设一次只保存一个文件。如果您一次保存多个文件,将无法正确删除空格。原因很简单。当前文档被认为是您可以看到的文档。 第三,它不对查找结果进行错误检查。这些结果可以更好地了解下一步该做什么。例如,如果没有找到并替换空格,则无需再次保存文件。一般来说,我不喜欢是否需要保存全局标志。它倾向于根据未知状态自找麻烦。我怀疑添加标志只是为了防止无限循环。

    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

我添加了调试消息框以帮助查看发生了什么。很明显,多个文件保存不起作用。如果您想和他们一起玩,请取消注释这些行。

关键区别在于使用 document.Activate() 强制文档进入前台活动当前文档。如果结果为 4,则表示文本已被替换。零表示什么都没发生。您将看到每个文件有两次保存。第一个将替换,第二个将什么也不做。如果保存无法写入文件,则可能会出现问题,但如果发生这种情况,希望不会调用此事件。

在原始脚本之前,我不知道脚本在 Visual Studio 中是如何工作的。它使用 Visual Basic 作为主界面有点令人惊讶,但它可以很好地完成它需要做的事情。

【讨论】:

对此的一个更改是支持保存并将焦点恢复到保存开始时具有焦点的窗口。只需在 Try 之后(使用 currdoc = DTE.ActiveDocument)和 document.Activate() 之前保存活动文档。保存完成后,只需激活原始文档(currdoc.Activate())即可。在保存过程中切换焦点看起来有点有趣,但总比失去焦点到你没看的代码上要好。【参考方案16】:

一个简单的添加是在保存期间删除回车。

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

这项工作的关键是将\x000d\x000a 更改为\x000a。 \x 前缀表示 Unicode 模式。这将使为 Linux 系统准备好源文件的过程自动化。

【讨论】:

以上是关于如何在 Visual Studio 2008 中自动删除尾随空格?的主要内容,如果未能解决你的问题,请参考以下文章

如何在visual studio中自定义dataGridView单元格

在 Visual Studio Code 中自定义语法突出显示

如何在 Visual Studio 2010 中使用 Visual Studio 2008 创建的 DLL?

如何在 Visual Studio 2008 中打开使用 Visual Studio 2005 创建的 rdl?

如何在 Visual Studio 2008 或 Visual Studio 2010 中设置 JavaScript 断点

visual studio 2008如何引用dll