Answers:
CodeMaid是一个非常流行的Visual Studio扩展,它会与其他有用的清理一起自动完成。
我将其设置为在保存时清理文件,我相信这是默认设置。
使用正则表达式查找/替换
在“查找和替换”对话框中,展开“ 查找选项”,选中“ 使用”,然后选择“ 正则表达式”
查找内容:“ :Zs#$
”
替换为:“”
单击全部替换
在其他编辑器(普通的正则表达式分析器)中,“ :Zs#$
”将是“ \s*$
”。
[^\S\r\n]+(?=\r?$)
[:Zs\t]#$
则是一种有用的适应方法。
您可以创建一个宏,该宏在保存后执行以为您执行此操作。
将以下内容添加到您的宏的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搜索找到它。
从已经给出的所有答案中提取元素,这就是我最终得到的代码。(我主要编写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
您可以使用正则表达式搜索来使用如删除空白和重写注释中所述的宏。
除非这是一个人的项目,否则不要这样做。将本地文件与源代码存储库进行比较很简单,清除空白将更改不需要更改的行。我完全理解;我喜欢将所有空白都统一起来-但这是您为了更清洁的协作而应该放弃的东西。
我认为,如果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
我个人很喜欢Trailing Whitespace Visualizer Visual Studio扩展,该扩展支持Visual Studio 2012。
我想我有这个宏的版本,不会在重构时使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
我使用ArtisticStyle(C ++)来执行此操作,并且还重新格式化了我的代码。但是,我必须将此添加为外部工具,并且您需要自己触发它,所以您可能不喜欢它。
但是,我发现我可以用更多自定义方式(例如,多行函数参数)重新格式化代码,以至于我可以付出手动运行代码的代价,这真是太好了。该工具是免费的。
基于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}+$
回车符来进行原始转换。
这是如何删除尾随空白的一个很好的例子。根据使用此宏所发现的内容,我需要更改一些内容。首先,宏会自动将制表符转换为空格。这并不总是可取的,并且可能会使喜欢制表符的人(通常基于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作为主界面有点令人惊讶,但是它可以很好地完成所需的工作。
一个简单的补充是在保存期间删除回车符。
' 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系统准备源文件的过程。