如何在 VisualStudio2008中自动删除尾随空格?

是否可以将 VisualStudio2008配置为在保存文件时自动删除每行末尾的空格字符?似乎没有一个内置的选项,那么有没有可用的扩展来实现这一点呢?

95037 次浏览

您可以使用类似于 使用正则表达式搜索删除空白并重写注释中描述的宏

我使用 艺术风格(C + +)来完成这项工作,并重新格式化我的代码。然而,我必须添加这个作为一个外部工具,你需要自己触发它,所以你可能不喜欢它。

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

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

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

查找 : “ :Zs#$

替换为 : “”

全部替换

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

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

除非这是一个个人项目,否则不要做。将本地文件与原始码储存库进行区分是很容易的,而清除空格将改变不需要改变的行。我完全理解; 我喜欢让我的空白都统一——但是为了更清晰的协作,你应该放弃这一点。

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

将以下内容添加到宏的 Environmental Events 模块中。

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 _ guide 中修改了它。Vsmacros,可以通过快速谷歌搜索找到。

这是一个很好的例子,说明了如何删除尾随的空格。根据我使用这个宏所发现的内容,有一些地方需要修改。首先,宏自动将制表符转换为空格。这并不总是令人满意的,而且可能导致喜欢标签页(通常基于 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

我添加了调试消息框来帮助查看正在发生的事情。很明显,多个文件保存不起作用。如果你想玩它们,取消注释这些行。

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

在使用原始脚本之前,我并不知道在 VisualStudio 中脚本是如何工作的。它使用 VisualBasic 作为主界面,这有点令人惊讶,但是对于它需要做的事情,它工作得很好。

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

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

' 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 系统准备源文件的过程。

基于 Dyaus 的回答和来自 连接报告的正则表达式,这里有一个宏,它可以处理保存所有内容,不用空格替换制表符,也不需要静态变量。它可能的缺点是什么?它似乎有点慢,可能是由于多次调用 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?$)(如果需要,不要忘记转义反斜杠)。我来到这里后,几次徒劳的尝试,以解决与 {:b}+$原始转换不匹配回车的问题。

从已经给出的所有答案中提取元素,这是我最终得到的代码。(我主要编写 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

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

  • Ctrl + A(选择所有文本)

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

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

等几秒钟就好了。

它是 Ctrl + Z’,以防出现问题。

我想我有一个版本的这个宏,不会崩溃 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

不幸的是,我使用的是不支持宏的 VWD2010 Express。所以我只是做复制/粘贴到 记事本 + + 左上方菜单 Edit > Blank Operations > Trim Trailing Space还有其他相关的操作也可用。然后复制/粘贴回 VisualStudio。

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

CodeMaid 是一个非常流行的 VisualStudio 扩展,可以自动执行此操作以及其他有用的清理。

我把它设置为在保存时清除一个文件,我认为这是默认设置。

我个人很喜欢 后面的空白可视化工具 Visual Studio 扩展,它支持 Visual Studio 2012。