|
|
Comments and Discussions
|
|
 |

|
It doesn't work 100% yet, but I haven't the time to fix it right now. If you fix anything with it, post it here. '------------------------------------------------------------------------------ 'FILE DESCRIPTION: Routines to reformat C/C++ source code. 'Created by Alvaro Mendez - June 10, 1999 'Ported to VS.NET 7.1 by Anders Dalvander - July 18, 2003 'Last Updated: July 18, 2003 '------------------------------------------------------------------------------ Option Explicit On Imports EnvDTE Imports System.Diagnostics Imports Microsoft.VisualStudio.VCProjectEngine Imports System Public Module MakeCodeNicer Sub MakeCodeNicer() 'DESCRIPTION: Reformats the source code to look nicer, the way I like it. ' Check that we have a valid source file If Not CheckActiveDocument() Then Exit Sub End If ' Select the whole file and reformat it ActiveDocument.Selection.SelectAll() ReformatSelection() End Sub Sub MakeSelectedCodeNicer() 'DESCRIPTION: Reformats the currently selected source code to look nicer. ' Check that we have a valid source file If Not CheckActiveDocument() Then Exit Sub End If ' Check that there's a valid selection If ActiveDocument.Selection.Text = "" Then ShowError("NoSelection") Exit Sub End If ' Reformat the current selection ReformatSelection() End Sub
' Verify there's an active document and that it's valid Function CheckActiveDocument() CheckActiveDocument = False ' Check that there's a file to reformat If ActiveDocument Is Nothing Then ShowError("NoFile") Exit Function End If ' Check that it's at least a text file If ActiveDocument.Type <> "Text" Then ShowError("InvalidFile") Exit Function End If CheckActiveDocument = True End Function ' Show one of the predefined errors in a message box. Sub ShowError(ByVal strType) Dim strMessage Select Case strType Case "NoFile" strMessage = "Please open a C/C++ source file " & _ "and run this macro again." Case "InvalidFile" strMessage = "Please activate a window containing " & _ "C/C++ source code and run this macro again." Case "NoSelection" strMessage = "Please select the source code you want to " & _ "reformat and run this macro again." Case "OutOfMemory" strMessage = "This macro is not working properly because " & _ "Visual C++ has apparently run out of memory." & _ vbLf & vbLf & "Unfortunately this is a bug in " & _ "Visual C++. It typically manifests itself " & _ "whenever the macro is run multiple times on very " & _ "large files, inside the same Visual C++ session. " & _ "The only way around it is to open a new Visual " & _ "C++ session for each large file you want to " & _ "reformat." & vbLf & vbLf & "Press OK to go back " & _ "to the original file. You should then exit Visual C++." Case Else strMessage = "Unknown Error of type: " & strType End Select MsgBox(strMessage, vbExclamation) End Sub ' Reformat the currently selected source code (if any) Function ReformatSelection() ' Check if there's something selected If ActiveDocument.Selection.Text = "" Then Exit Function End If ' Copy the selection to the clipboard ActiveDocument.Selection.Copy() ' Open a new document and change its language to C/C++ ' This is required for SmartIndent to work. DTE.Documents.Add("Text") ActiveDocument.Language = "C/C++" ' Paste the selection into the new document ActiveDocument.Selection.Paste() ' Reformat it! If Not ReformatActiveDocument() Then ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo) Exit Function End If ' Select the resulting code and copy it to the clipboard ActiveDocument.Selection.SelectAll() ActiveDocument.Selection.Copy() ' Close the new document (without saving it) ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo) ' Paste the reformatted code back over the original selection ActiveDocument.Selection.Paste() End Function ' Reformat the source code in the currently active file (document) Function ReformatActiveDocument() ReformatActiveDocument = False ' Add spaces in a few places and get rid of it in others Replace(":b+;", ";") Replace(":b+\:\::b+", "::") Replace(":b+\(", "(") Replace(" =\(", " = (") Replace("if\(", "if (") Replace("for\(", "for (") Replace("while\(", "while (") Replace("switch\(", "switch (") Replace("catch\(", "catch (") Replace("return\(", "return (") Replace("\(:b+", "(") Replace(":b+\)", ")") 'Replace(";\)", "; )") Replace(";;:b+\)", ";;)") Replace("\[:b+", "[") Replace(":b+\]", "]") Replace(":b+\[", "[") Replace(":b+->", "->") Replace("->:b+", "->") Replace("\|\(", "| (") Replace("&\(", "& (") Replace("\+\(", "+ (") Replace("\-\(", "- (") Replace("\*\(", "* (") Replace("/\(", "/ (") ' Make sure these statements don't end on the same line they started. BreakSingleLiners("if (") BreakSingleLiners("for (") BreakSingleLiners("switch (") ' Break up any lines containing multiple statements BreakLinesWithMultipleStatements() ' Make sure braces are on lines by themselves (unless followed by comments) IsolateOnLeft("\{") IsolateOnRight("\{") IsolateOnRight("\}") IsolateOnLeft("\}") ' Break up simple else statements on the same line (except "else if") Replace("else:b+if \(", "elseif(") IsolateOnRight("else:b+") Replace("elseif\(", "else if (") ' Break up case statements appearing on single lines IsolateOnRight("case .+\::b+") IsolateOnRight("default\::b+") IsolateOnLeft("break;") ' Add a space between these operators FixOperator("=", 1) FixOperator("==", 2) FixOperator("!=", 2) FixOperator("\+=", 2) FixOperator("-=", 2) FixOperator("\*=", 2) FixOperator("/=", 2) FixOperator("\+", 1) FixOperator("-", 1) FixOperator("<=", 2) FixOperator(">=", 2) FixOperator("<<", 2) FixOperator(">>", 2) FixOperator("&&", 2) FixOperator("\|\|", 2) FixOperator("\|", 1) FixOperator("\?", 1) FixLessThanAndGreaterThanOperators() FixExponents() ' Append a space after these AppendSpace(",") AppendSpace(";") ' Make sure the first C++ comment of every line has a space after it. InsertSpaceAfterFirstInLineComment() ' Replace all the trailing whitespace (thanks to Paul Bludov) ActiveDocument.Selection.ReplaceText(":b+{$}", "\1", vsFindOptions.vsFindOptionsRegularExpression) ' Run Smart Indent on function blocks only SmartIndentFunctionBlocks() ' Remove any lines that are considered extraneous (ie. extra blank lines) If Not RemoveExtraneousLines() Then Exit Function End If ' Indent every "case" inside switch statements (thanks to Jim Cooper) IndentSwitchBody() ' Return OK ReformatActiveDocument = True End Function ' Is the cursor currently within a quoted string (or character) Function IsWithinQuotes() Dim nCurrentLine, nCurrentColumn, iPos, strBuffer, nCount nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.Cancel() ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, True) nCount = 0 iPos = 0 strBuffer = ActiveDocument.Selection.Text ' Count all occurrences of a double quote which apply to quoted strings Do While True iPos = InStr(iPos + 1, strBuffer, """", vbTextCompare) If Not (iPos > 0) Then Exit Do End If If iPos = 1 Then ' if it's the first character, then it's valid nCount = nCount + 1 Else ' Make sure it's not preceded by a \ or a \\ If Mid(strBuffer, iPos - 1, 1) <> "\" Then nCount = nCount + 1 ElseIf (iPos > 2) And (Mid(strBuffer, iPos - 2, 1) = "\") Then nCount = nCount + 1 End If End If Loop ' If number of quotes is odd, we must be inside a quoted string! IsWithinQuotes = ((nCount > 0) And ((nCount Mod 2) <> 0)) ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) ' If we're not inside a quoted string, check for a quoted character If Not IsWithinQuotes Then ActiveDocument.Selection.CharLeft(True) ' If we find a quoted character left of us, check for one on the right If ActiveDocument.Selection.Text = "'" Then ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharRight(True) If ActiveDocument.Selection.Text = "\" Then ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharRight(True) End If ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharRight(True) If ActiveDocument.Selection.Text = "'" Then IsWithinQuotes = True End If End If ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) End If ' If we're inside quotes, proceed from the next character If IsWithinQuotes Then ActiveDocument.Selection.CharRight() End If End Function ' Is current selection preceded by a C++ comment? ("//") Function IsWithinComment() Dim nCurrentLine, nCurrentColumn nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.Cancel() ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, True) IsWithinComment = False If (InStr(1, ActiveDocument.Selection.Text, "//", vbTextCompare) > 0) Then IsWithinComment = True ' since it's commented out nCurrentLine = nCurrentLine + 1 ' we proceed from the next line End If ActiveDocument.Selection.MoveTo(nCurrentLine, 1) End Function ' Is the cursor on a line with a preprocessor macro? ("#define ") Function IsPreprocessorMacro() Dim nCurrentLine, nCurrentColumn nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn IsPreprocessorMacro = False ActiveDocument.Selection.EndOfLine(True) If (Mid(LTrimTabs(ActiveDocument.Selection.Text), 1, 8) = "#define ") Or _ (Right(ActiveDocument.Selection.Text, 1) = "\") Then IsPreprocessorMacro = True ' since it's in a macro nCurrentLine = nCurrentLine + 1 ' we proceed from the next line End If ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) End Function ' Should the current selection be ignored? ' (ie., is it within a comment, between quotes, or inside a macro?) Function ShouldIgnore() ShouldIgnore = False If IsWithinQuotes() Then ShouldIgnore = True Exit Function End If If IsWithinComment() Then ShouldIgnore = True Exit Function End If If IsPreprocessorMacro() Then ShouldIgnore = True End If End Function ' Put the cursor at the top of the document and return "" to be passed ' initially to GetCurrenPosition Function InitializePosition() ActiveDocument.Selection.StartOfDocument() InitializePosition = "" End Function ' Retrieve the current position and return true if it's greater than the ' last one. This is used to ensure that the file is only searched once ' (provided the search is started from the top) Function GetCurrentPosition(ByRef strPos) Dim nLastLine, nLastColumn, nCurrentLine, nCurrentColumn, iPos, ch nLastLine = -1 nLastColumn = -1 nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Parse the last position and extract the line and column For iPos = 1 To Len(strPos) ch = Mid(strPos, iPos, 1) If ch = "," Then nLastLine = CInt(Mid(strPos, 1, iPos - 1)) nLastColumn = CInt(Mid(strPos, iPos + 1)) Exit For End If Next ' Return true if we're currently past the last position strPos = nCurrentLine & "," & nCurrentColumn GetCurrentPosition = (nCurrentLine > nLastLine) Or _ ((nLastLine = nCurrentLine) And (nCurrentColumn > nLastColumn)) End Function ' Move by a certain number of columns Sub MoveByColumns(ByVal nBy) ActiveDocument.Selection.MoveTo(ActiveDocument.Selection.CurrentLine, _ ActiveDocument.Selection.CurrentColumn + nBy) End Sub ' Replace the given strFrom with strTo case sensitively Sub Replace(ByVal strFrom, ByVal strTo) Dim strLastPos, bContinue strLastPos = InitializePosition() Do While ActiveDocument.Selection.FindText(strFrom, _ vsFindOptions.vsFindOptionsMatchCase + vsFindOptions.vsFindOptionsRegularExpression) bContinue = GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at ' the beginning of the line ActiveDocument.Selection.FindText(strFrom, _ vsFindOptions.vsFindOptionsMatchCase + vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.Text = strTo ElseIf Not bContinue Then Exit Do End If Loop End Sub ' Break the given str ending in (, so that instead of this: ' if (a) return b; ' it looks like this: ' if (a) ' return b; Sub BreakSingleLiners(ByVal str) Dim strLastPos, strFound, nCol, bBreak, strAfterFound ' Verify str ends in (, the beginning parenthesis If Right(str, 1) <> "(" Then Exit Sub End If strLastPos = InitializePosition() While ActiveDocument.Selection.FindText(str, vsFindOptions.vsFindOptionsMatchCase) And _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText(str, vsFindOptions.vsFindOptionsMatchCase) ' Find the matching brace and go to the end of the line ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharLeft() ExecuteCommand("Edit.GotoBrace") ActiveDocument.Selection.CharRight() nCol = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.EndOfLine(True) strFound = LTrimTabs(ActiveDocument.Selection.Text) ' If there's anything after the brace that isn't a comment, move ' it to the next line If (Len(strFound) > 0) And (Left(strFound, 1) <> "/") Then bBreak = False ' Check if there's a "{" after the statement which should ' also be broken into multiple lines If (Mid(strFound, 1, 1) = "{") And (Len(strFound) > 1) Then strAfterFound = LTrimTabs(Mid(strFound, 2)) If strAfterFound <> "" Then ActiveDocument.Selection.Text = "{" + strAfterFound ActiveDocument.Selection.MoveTo( _ ActiveDocument.Selection.CurrentLine, nCol) ActiveDocument.Selection.NewLine() ActiveDocument.Selection.CharRight() ActiveDocument.Selection.NewLine() bBreak = True ' primitive but it works End If End If If Not bBreak Then ActiveDocument.Selection.Text = strFound ActiveDocument.Selection.MoveTo( _ ActiveDocument.Selection.CurrentLine, nCol) ActiveDocument.Selection.NewLine() End If End If End If End While End Sub ' Trim blanks AND tabs from the left side Function LTrimTabs(ByVal str) Dim iPos, ch For iPos = 1 To Len(str) ch = Mid(str, iPos, 1) If ch <> " " And ch <> vbTab Then Exit For End If Next LTrimTabs = Mid(str, iPos) End Function ' Isolate the given str on a new line with nothing left of it Sub IsolateOnLeft(ByVal str) Dim strLastPos, nLen, bContinue, nCurrentLine, nCurrentColumn strLastPos = InitializePosition() While ActiveDocument.Selection.FindText("^.*" & str, vsFindOptions.vsFindOptionsRegularExpression + _ vsFindOptions.vsFindOptionsMatchCase) And GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("^.*" & str, _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) ' Get the length of the found string ' (which may have been a regular expression) ActiveDocument.Selection.CharRight() ActiveDocument.Selection.FindText(str, _ vsFindOptions.vsFindOptionsBackwards + vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) nLen = Len(ActiveDocument.Selection.Text) ActiveDocument.Selection.CharLeft() If Not ShouldIgnore() Then ' Now that we have the length, we need to redo ' the search and go on ActiveDocument.Selection.StartOfLine() ActiveDocument.Selection.FindText("^.*" & str, _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) bContinue = False ' If we're isolating a brace, make sure its matching brace ' isn't on the same line If (str = "{") Or (str = "}") Then ActiveDocument.Selection.CharRight() nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.CharLeft() ExecuteCommand("Edit.GotoBrace") If ActiveDocument.Selection.CurrentLine = nCurrentLine Then ActiveDocument.Selection.MoveTo( _ nCurrentLine, nCurrentColumn) bContinue = True ' we found it so move to the next match Else ActiveDocument.Selection.MoveTo(nCurrentLine, 1) ActiveDocument.Selection.FindText("^.*" & str, _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) End If End If
If LTrimTabs(ActiveDocument.Selection.Text) <> str And _ Not bContinue Then ActiveDocument.Selection.CharRight() MoveByColumns(-nLen) ActiveDocument.Selection.NewLine() MoveByColumns(nLen) End If GetCurrentPosition(strLastPos) End If End If End While End Sub ' Isolate the given str so that everything after it is placed on the next line Sub IsolateOnRight(ByVal str) Dim strLastPos, strRight, nCurrentLine, nCurrentColumn, nLen strLastPos = InitializePosition() While ActiveDocument.Selection.FindText(str & ".+$", _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) And GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes ActiveDocument.Selection.CharLeft() If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText(str & ".+$", _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) ' Get the length of the found string ' (which may have been a regular expression) ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.FindText(str, vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) nLen = Len(ActiveDocument.Selection.Text) ' Now that we have the length, we need to redo the search and go on ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.FindText(str & ".+$", _ vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) strRight = LTrimTabs(Mid(ActiveDocument.Selection.Text, nLen + 1)) ' Handle braces a bit differently If (str = "{") Or (str = "}") Then ' If it's a closing brace, and the code after it contains ' a semicolon, leave it alone (ie. variable definition). If (str = "}") Then ActiveDocument.Selection.EndOfLine(True) If (InStr(1, ActiveDocument.Selection.Text, ";", vbTextCompare) _ > 0) Then strRight = "" ' we found it so move on to the next match End If ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.CharRight() End If ' If we're isolating a brace make sure the matching brace ' isn't on the same line If (strRight <> "") Then ActiveDocument.Selection.CharLeft() nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ExecuteCommand("Edit.GotoBrace") If ActiveDocument.Selection.CurrentLine = nCurrentLine Then ActiveDocument.Selection.MoveTo( _ nCurrentLine, nCurrentColumn + 1) strRight = "" ' we found it so move on to the next match Else ActiveDocument.Selection.MoveTo( _ nCurrentLine, nCurrentColumn) ActiveDocument.Selection.FindText( _ str & ".+$", vsFindOptions.vsFindOptionsRegularExpression + vsFindOptions.vsFindOptionsMatchCase) End If End If End If If (strRight <> "") And _ (Left(strRight, 1) <> "/") And _ (strRight <> ",") And _ (strRight <> ";") And _ (strRight <> "\") Then ActiveDocument.Selection.CharLeft() MoveByColumns(nLen) ActiveDocument.Selection.NewLine() End If End If End While End Sub ' Place the given strOperator (of nLen REAL characters) ' between spaces (if needed) Sub FixOperator(ByVal strOperator, ByVal nLen) Dim strLastPos, strFind strLastPos = InitializePosition() ' Add one space between the operator While ActiveDocument.Selection.FindText("[A-Z,a-z,0-9,\),_,\]]" & _ strOperator & "[A-Z,a-z,0-9,\(,_,\*,"",',&]", vsFindOptions.vsFindOptionsRegularExpression) And _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes ActiveDocument.Selection.CharLeft() If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("[A-Z,a-z,0-9,\),_,\]]" & _ strOperator & "[A-Z,a-z,0-9,\(,_,\*,"",',&]", vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.CharRight() ActiveDocument.Selection.Text = " " MoveByColumns(nLen) ActiveDocument.Selection.Text = " " End If End While strLastPos = InitializePosition() ' Fix any C++ "operator" member functions which were broken above While ActiveDocument.Selection.FindText("operator " & strOperator & " ", _ vsFindOptions.vsFindOptionsRegularExpression) And GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("operator " & strOperator & " ", _ vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.CharRight() ActiveDocument.Selection.Backspace() MoveByColumns(-nLen) ActiveDocument.Selection.Backspace() End If End While End Sub ' Fix "<" and ">" operators found inside for, while, and if statements. Function FixLessThanAndGreaterThanOperators() ' Fix "for" loops FixLessThanOrGreaterThanOperator("^:b*for \(.*;.*[A-Z,a-z,0-9,), ]+\<[^<=]") FixLessThanOrGreaterThanOperator("^:b*for \(.*;.*[A-Z,a-z,0-9,), ]+\>[^>=]") ' Fix "while" loops FixLessThanOrGreaterThanOperator("^:b*while \(.*[A-Z,a-z,0-9,), ]+\<[^<=]") FixLessThanOrGreaterThanOperator("^:b*while \(.*[A-Z,a-z,0-9,), ]+\>[^>=]") ' Fix "if" statements FixLessThanOrGreaterThanOperator("^:b*if \(.*[A-Z,a-z,0-9,), ]+\<[^<=]") FixLessThanOrGreaterThanOperator("^:b*if \(.*[A-Z,a-z,0-9,), ]+\>[^>=]") End Function ' Fix "<" or ">" operator based on the given search condition. ' It assumes the condition will yield one or more characters before ' the operator and only one character after it. Function FixLessThanOrGreaterThanOperator(ByVal strSearch) Dim strLastPos, strFound strLastPos = InitializePosition() While ActiveDocument.Selection.FindText(strSearch, vsFindOptions.vsFindOptionsRegularExpression + _ vsFindOptions.vsFindOptionsMatchCase) And GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharLeft() ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the search since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText(strSearch, vsFindOptions.vsFindOptionsRegularExpression + _ vsFindOptions.vsFindOptionsMatchCase) strFound = ActiveDocument.Selection.Text ' Add a space before it (if needed) If Mid(strFound, Len(strFound) - 2, 1) <> " " Then strFound = Left(strFound, Len(strFound) - 2) & " " & _ Right(strFound, 2) End If ' Add a space after it (if needed) If Right(strFound, 1) <> " " Then strFound = Left(strFound, Len(strFound) - 1) & " " & _ Right(strFound, 1) End If ActiveDocument.Selection.Text = strFound End If End While End Function ' Append a space after the given strOperator (if it needs it) Sub AppendSpace(ByVal strOperator) Dim strLastPos, nCurrentLine, nCurrentColumn strLastPos = InitializePosition() While ActiveDocument.Selection.FindText(strOperator & _ "[A-Z,a-z,0-9,\(,\-,_,\*,"",',&]", vsFindOptions.vsFindOptionsRegularExpression) And _ GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharLeft() nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) ActiveDocument.Selection.FindText(strOperator & _ "[A-Z,a-z,0-9,\(,\-,_,\*,"",',&]", vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.CharLeft() MoveByColumns(Len(strOperator)) ActiveDocument.Selection.Text = " " End If End While End Sub ' Run the SmartIndent command (Alt+F8) on function blocks only. Function SmartIndentFunctionBlocks() Dim strLastPos, nColumn, cBeforeBrace strLastPos = InitializePosition() While ActiveDocument.Selection.FindText("{") And _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("{") ' Go to matching brace and reformat tabs DTE.ExecuteCommand("Edit.GotoBraceExtend") nColumn = ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.SmartFormat() ActiveDocument.Selection.CharRight() If ActiveDocument.Selection.CurrentColumn > nColumn Then ' If SmartFormat indents the block (by mistake), unindent it ActiveDocument.Selection.CharLeft() DTE.ExecuteCommand("Edit.GotoBraceExtend") ActiveDocument.Selection.Unindent() End If End If End While End Function ' Since Microsoft's "SmartFormat" is not smart enough to indent case ' statements inside the switch body, we'll do it here. ' (Thanks to Jim Cooper) Function IndentSwitchBody() Dim nSwitchLine, nFirstLine, nLastLine, strLastPos, iLine strLastPos = InitializePosition() While ActiveDocument.Selection.FindText("switch", _ vsFindOptions.vsFindOptionsMatchWholeWord + vsFindOptions.vsFindOptionsMatchCase) And GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then nSwitchLine = ActiveDocument.Selection.CurrentLine ' Now find the opening brace and make sure it's on the next line If ActiveDocument.Selection.FindText("{") And _ Not ShouldIgnore() And _ (ActiveDocument.Selection.CurrentLine = nSwitchLine + 1) Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("{") ' Find next line in file, since earlier code put '{' on ' a line by itself nFirstLine = ActiveDocument.Selection.CurrentLine + 1 ' Go to matching brace and reformat tabs ExecuteCommand("Edit.GotoBrace") ' Find previous line in file, since earlier code put '}' on ' line by itself nLastLine = ActiveDocument.Selection.CurrentLine ' Move to the line after the opening brace ActiveDocument.Selection.GoToLine(nFirstLine, 1) ' Select everything between the braces and indent it For iLine = nFirstLine To nLastLine - 1 ActiveDocument.Selection.LineDown(True) Next ActiveDocument.Selection.Indent() End If End If End While End Function ' Remove any lines that are considered extraneous (usually blank ones). Function RemoveExtraneousLines() Dim strLastPos, nCurrentLine, nCurrentColumn, nLastLine, bContinue strLastPos = InitializePosition() RemoveExtraneousLines = True ' Remove any blank lines that fall below any open braces ("{") While ActiveDocument.Selection.FindText("{") And _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("{") nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Go to matching brace ExecuteCommand("Edit.GotoBrace") ' Check if it's on the same line bContinue = (nCurrentLine <> ActiveDocument.Selection.CurrentLine) ExecuteCommand("Edit.GotoBrace") ' If the matching brace is on the same line, proceed to the next brace If bContinue Then ActiveDocument.Selection.LineDown() ' Cut any blank lines below the { Do While True ActiveDocument.Selection.StartOfLine() ActiveDocument.Selection.EndOfLine(True) If LTrimTabs(ActiveDocument.Selection.Text) <> "" Then Exit Do End If ' Get the last line of the document ActiveDocument.Selection.EndOfDocument() nLastLine = ActiveDocument.Selection.CurrentLine ' Remove the extra line ActiveDocument.Selection.MoveTo(nCurrentLine + 1, 1) ExecuteCommand("LineCut") ' Make sure we haven't hit the bottom of the file and that LineCut worked ActiveDocument.Selection.EndOfDocument() If ActiveDocument.Selection.CurrentLine = nLastLine Then Exit Do End If ActiveDocument.Selection.MoveTo(nCurrentLine + 1, 1) Loop End If ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) End If End While strLastPos = InitializePosition() ' Remove any blank lines right above any closing braces ("}") While ActiveDocument.Selection.FindText("}") And _ GetCurrentPosition(strLastPos) ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("}") ActiveDocument.Selection.CharLeft() ' Cut blank lines above the } Do While True ActiveDocument.Selection.LineUp() ActiveDocument.Selection.StartOfLine() ActiveDocument.Selection.EndOfLine(True) nCurrentLine = ActiveDocument.Selection.CurrentLine If LTrimTabs(ActiveDocument.Selection.Text) <> "" Then If ActiveDocument.Selection.CurrentLine > 1 Then ActiveDocument.Selection.LineDown() End If ActiveDocument.Selection.StartOfLine() ActiveDocument.Selection.FindText("}") strLastPos = ActiveDocument.Selection.CurrentLine & "," & _ ActiveDocument.Selection.CurrentColumn ActiveDocument.Selection.LineDown() ActiveDocument.Selection.StartOfLine() Exit Do End If ' Get the last line of the document ActiveDocument.Selection.EndOfDocument() nLastLine = ActiveDocument.Selection.CurrentLine ' Remove the extra line ActiveDocument.Selection.MoveTo(nCurrentLine, 1) ExecuteCommand("LineCut") ' Make sure LineCut worked -- if not something's really messed up ActiveDocument.Selection.EndOfDocument() If ActiveDocument.Selection.CurrentLine = nLastLine Then ShowError("OutOfMemory") RemoveExtraneousLines = False Exit Function End If ActiveDocument.Selection.MoveTo(nCurrentLine, 1) Loop End If End While End Function ' Remove all spaces and tabs found in the current selection Function RemoveSpacesInSelection() Dim iPos, ch, strNoSpaces For iPos = 1 To Len(ActiveDocument.Selection.Text) ch = Mid(ActiveDocument.Selection.Text, iPos, 1) If ch <> " " And ch <> vbTab Then strNoSpaces = strNoSpaces + ch End If Next ActiveDocument.Selection.Text = strNoSpaces End Function ' Fix any code with exponential notation (ie. 3.4e-2) which was ' broken when the + and - operators were fixed above (by FixOperator). Function FixExponents() While ActiveDocument.Selection.FindText("[0-9,\.]e [\+\!\-] [0-9]", _ vsFindOptions.vsFindOptionsRegularExpression) RemoveSpacesInSelection() End While End Function ' Break any lines containing multiple statements (separated by semicolons) Function BreakLinesWithMultipleStatements() Dim strLastPos, nCurrentLine, nCurrentColumn strLastPos = InitializePosition() ' Search for multiple semicolons on the same line Do While ActiveDocument.Selection.FindText(";.+;", vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.CharLeft() If Not GetCurrentPosition(strLastPos) Then Exit Do End If nCurrentLine = ActiveDocument.Selection.CurrentLine nCurrentColumn = ActiveDocument.Selection.CurrentColumn ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.MoveTo(nCurrentLine, nCurrentColumn) ActiveDocument.Selection.FindText(";.+;", vsFindOptions.vsFindOptionsRegularExpression) nCurrentLine = ActiveDocument.Selection.CurrentLine ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, True) ' If found, check that the semicolons don't belong to a for loop If (InStr(1, ActiveDocument.Selection.Text, "for (", _ vbTextCompare) > 0) Then ActiveDocument.Selection.MoveTo(nCurrentLine + 1, 1) Else If ActiveDocument.Selection.Text <> "" Then ActiveDocument.Selection.CharRight() End If ActiveDocument.Selection.CharRight() ActiveDocument.Selection.NewLine() End If End If Loop End Function ' Make sure the first C++ comment of every line has a space after it. Function InsertSpaceAfterFirstInLineComment() Dim strLastPos, nCurrentLine strLastPos = InitializePosition() While ActiveDocument.Selection.FindText("//[A-Z,a-z,0-9]", vsFindOptions.vsFindOptionsRegularExpression) _ And GetCurrentPosition(strLastPos) ActiveDocument.Selection.CharLeft() ' Check if we're inside a comment or between quotes If Not ShouldIgnore() Then ' Repeat the action since ShouldIgnore puts the cursor at the ' beginning of the line ActiveDocument.Selection.FindText("//[A-Z,a-z,0-9]", vsFindOptions.vsFindOptionsRegularExpression) ActiveDocument.Selection.CharRight() ActiveDocument.Selection.CharLeft() ActiveDocument.Selection.Text = " " End If End While End Function ' Display a message box if bDebug is true Sub DebugBox(ByVal strMessage) Dim bDebug bDebug = False If bDebug Then MsgBox(strMessage) End If End Sub End Module
|
|
|
|

|
I got the error:
(11): Namespace or type 'VCProjectEngine' for the Imports 'Microsoft.VisualStudio.VCProjectEngine' cannot be found.
I removed that, but discovered rather than make the code nicer, it messed it up.
|
|
|
|

|
Now that I upgraded to .net I think its wonderful - but... this is one macro that I really miss - I have to load up a VC6 just to run the macro. Anybody have a port or a converter to convert vc6 macros to vc.net? big booboo on m$ part.
|
|
|
|

|
I think a reference to "VCProjectEngine.dll" has to be added to the macro project in Visual Studio .NET 2003.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
A great macro for reformatting C++ source code.
| Type | Article |
| Licence | |
| First Posted | 16 Nov 1999 |
| Views | 258,688 |
| Bookmarked | 77 times |
|
|