| « Fast struct/class copy and exchange in C++ | A lot of refactoring » |
Here's VS macro for searching and converting upper cased constants and enumerations to camel case style. For example, you can convert string like "ENTITY_FLAG_VISIBLE" to "EntityFlagVisible" or even better to "Entity::FlagVisible" in whole solution. Very useful for refactoring. Released under GNU GPL.
Function FindAndReplaceInSolution(ByVal FindWhat As String, ByVal ReplaceWith As String, Optional ByVal MatchCase As Boolean = True, Optional ByVal WholeWord As Boolean = True) As Boolean
'DTE.ExecuteCommand("Edit.Replace")
DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
DTE.Find.FindWhat = FindWhat
DTE.Find.ReplaceWith = ReplaceWith
DTE.Find.Target = vsFindTarget.vsFindTargetSolution
DTE.Find.MatchCase = MatchCase
DTE.Find.MatchWholeWord = WholeWord
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
DTE.Find.KeepModifiedDocumentsOpen = False
DTE.Find.FilesOfType = ""
DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
Return False 'Throw New System.Exception("vsFindResultNotFound")
End If
Return True
End Function
Function FindInDocument(ByVal FindWhat As String, Optional ByVal MatchCase As Boolean = False, Optional ByVal WholeWord As Boolean = False) As Boolean
'DTE.ExecuteCommand("Edit.Find")
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchWholeWord = WholeWord
DTE.Find.MatchCase = MatchCase
DTE.Find.FindWhat = FindWhat
DTE.Find.Action = vsFindAction.vsFindActionFind
DTE.Find.Backwards = False
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
Return False 'Throw New System.Exception("vsFindResultNotFound")
End If
Return True
End Function
Function FindAndNormalizeConstantName(Optional ByVal PrefixToDelete As String = "", Optional ByVal PrefixReplaceWith As String = "", Optional ByVal WholeSolution As Boolean = False) As Boolean
' Converts CONSTANT_NAME to ConstantName
Dim Document As EnvDTE.Document = DTE.ActiveDocument
If (Not FindInDocument("_", False, False)) Then
Return False
End If
Document.Selection.WordLeft()
Document.Selection.WordRight(True)
Dim Name As String = Document.Selection.Text
For Index = Name.Length - 1 To 0 Step -1
If (Not Char.IsWhiteSpace(Name.Chars(Index))) Then
Dim WhiteSpaceCount As Integer = Name.Length - (Index + 1)
If (WhiteSpaceCount > 0) Then
Name = Name.Trim() ' Remove any whitespaces
Document.Selection.CharLeft(WhiteSpaceCount) ' Fit selection
End If
Exit For
End If
Next
If ((Name.Chars(0) <> "_") And (Char.IsUpper(Name.Chars(1)))) Then
'Its not begining with "_" prefix, and so it's constant or enum.
Dim Result As New System.Text.StringBuilder()
Dim Original As String = Name ' Make backup
If (PrefixToDelete.Length > 0) Then
Name = Name.Remove(0, PrefixToDelete.Length) ' Delete prefix
Result.Append(PrefixReplaceWith) ' Write new prefix to result
End If
Dim Uppercase As Boolean = True
For Index = 0 To Name.Length - 1
Dim Value As Char = Name.Chars(Index)
If (Name.Chars(Index) = "_") Then
Uppercase = True
Else
If (Uppercase) Then
Result.Append(Char.ToUpper(Value))
Uppercase = False
Else
Result.Append(Char.ToLower(Value))
End If
End If
Next
If (WholeSolution) Then
FindAndReplaceInSolution(Original, Result.ToString(), True, True)
Else
Document.Selection.Text = Result.ToString()
End If
Else
' Skip it
Document.Selection.WordRight()
End If
Return True
End Function
Example usage, replaces "ENTITY_SOMETHING" with "Entity::Something":
Sub TemporaryMacro()
' Run macro 10 times when pressed Ctrl+Shift+P
For Index = 1 To 10
If (Not FindAndNormalizeConstantName("ENTITY_", "Entity::", False)) Then
Exit For
End If
Next
End Sub
Another example, convert everything (in opened document only):
Sub TemporaryMacro()
FindAndNormalizeConstantName("", "", False)
End Sub
Also, I should let you know that it works only when the names contains underscore character (one is enough) and that if you have guard macros that doesn't begin with underscore, they will be replaced as well. All my guard macros begins with underscore (e.g. _AGATE_XML_DOCUMENT_HPP_) so if you're using different style, you should modify the macro, or run it manually, like in the usage example.
Hope it helps.
Edit: If you want a faster way how to refactor, load the whole document into memory and use string class to replace all occurences. It's much faster than using find/replace dialog.
