Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3174)

Unified Diff: docs/windows_visual_studio_macros.md

Issue 1309473002: WIP: Migrate Wiki content over to src/docs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: docs/windows_visual_studio_macros.md
diff --git a/docs/windows_visual_studio_macros.md b/docs/windows_visual_studio_macros.md
new file mode 100644
index 0000000000000000000000000000000000000000..fd2ffa04abcf89e37fdd04f61ad1533b13436634
--- /dev/null
+++ b/docs/windows_visual_studio_macros.md
@@ -0,0 +1,656 @@
+# Random Visual Studio macros
+
+
+
+The following macros can aid your workflow under the full (non-Express, i.e. paid) versions of Visual Studio 2010 and earlier. Unfortunately, Visual Studio 2012 and later <a href='http://social.msdn.microsoft.com/Forums/vstudio/en-US/d8410838-085b-4647-8c42-e31b669c9f11/macros-in-visual-studio-11-developer-preview?forum=vsx'>do not support macros</a>. You should try <a href='http://chromium.github.io/vs-chromium/'>the <b>vs-chromium</b> Visual Studio Extension which provides similar functionality</a>.
Bons 2015/08/20 20:16:51 delete since all builds are with ninja, now.
+
+Note: Syntax highlighting is wrong, there's nothing to do about it.
+
+## How to install one
+ * Verify that you have the non-Express version of Visual Studio 2010 or earlier
+ * Menu: Tools, Macros, Macro Explorer
+ * Double click on `MyMacros`
+ * Double click on `Module1`, that will open the Macros editor
+ * Paste whatever code you want there inside the `Module` section. You may want to create one module per macro to keep it sane.
+
+
+## How to bind
+Once you've added a macro, you can double click it in the Macro Explorer to execute it, but it's often convenient to bind it.
+ * Keyboard
+ * Menu Tools, Options
+ * Navigate to Environment, Keyboard
+ * Type `MyMacros` or your macro name, select the one you want.
+ * Press the key to bind in the bottom, press Assign.
+ * Toolbar
+ * Menu Tools, Customize
+ * Tab Commands
+ * Select `Macros` on the left
+ * Drag the macro name on the right to a toolbar
+ * The text will be awfully long, right click on the new button and edit the Name property
+
+
+## Automatically grab chromium child processes
+
+Hint: Bind `AttachChromium()` to a toolbar button and enable the "Debug Location" toolbar to navigate between processes.
+```
+Public Sub AttachToProcesses(ByVal process_name As String, ByVal AttachIfCmdLineContains As String)
+ ' Attaches to a process by its name. If a command line argument is needed, looks for it.'
+ Dim pids As New System.Collections.Generic.List(Of Integer)
+ Dim pids_debugged As New System.Collections.Generic.List(Of Integer)
+ For Each debugged As EnvDTE.Process In DTE.Debugger.DebuggedProcesses
+ pids_debugged.Add(debugged.ProcessID)
+ Next
+ Dim processes As System.Diagnostics.Process() = System.Diagnostics.Process.GetProcessesByName(process_name)
+ For Each proc As System.Diagnostics.Process In processes
+ If proc.MainModule.FileName().ToLower().Contains(AttachIfCmdLineContains.ToLower()) Then
+ pids.Add(proc.Id)
+ End If
+ Next
+ For Each proc As EnvDTE.Process In DTE.Debugger.LocalProcesses
+ If Not pids_debugged.Contains(proc.ProcessID) And pids.Contains(proc.ProcessID) Then
+ proc.Attach()
+ End If
+ Next
+End Sub
+
+Sub AttachChromium()
+ ' Attaches to the chrome.exe processes that has \code\ in their command line'
+ ' argument or binary path.'
+ AttachToProcesses("chrome", System.IO.Path.GetDirectoryName(System.IO.Path.GetDirectoryName(DTE.Solution.FullName)) & "\build\")
+End Sub
+```
+
+Note that Visual Studio 2012 and later <a href='http://social.msdn.microsoft.com/Forums/vstudio/en-US/d8410838-085b-4647-8c42-e31b669c9f11/macros-in-visual-studio-11-developer-preview?forum=vsx'>do not support macros</a>. The functionality of this macro is <a href='http://chromium.github.io/vs-chromium/#attach-to-chrome'>included in the vs-chromium plug-in</a>.
+
+## Format comments to 80 cols
+
+Hint: Bind `FormatComment()` to Alt-F.
+```
+Sub FormatComment()
+ ' Make comments fit 80 cols.'
+ Dim sel As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
+ Dim text As String = sel.Text
+ Dim CommentMarker As String = "//"
+
+ ' InStr() is one-based'
+ Dim commentColumn As Integer = InStr(text, CommentMarker)
+ ' Substring() is zero-based'
+ Dim prefix As String = text.Substring(0, commentColumn - 1) + CommentMarker + " "
+ ' Take in account the length of the comment marker and the space. The maximum is 81'
+ ' and not 80; column starts at 1 and not 0. InStr() is 1 based too.'
+ Dim maxline As Integer = 81 - commentColumn - CommentMarker.Length
+
+ ' Remove comment marker'
+ text = System.Text.RegularExpressions.Regex.Replace(text, "^ *// *", "", System.Text.RegularExpressions.RegexOptions.Multiline)
+ ' Remove \r\n to put all the text on one line'
+ text = System.Text.RegularExpressions.Regex.Replace(text, " *[" + vbLf + "]+ *", " ")
+ text = text.Trim()
+
+ Dim newtext As String = ""
+
+ While text <> ""
+ ' InStrRev() is one-based'
+ Dim pos As Integer = InStrRev(text, " ", maxline)
+ If pos = 0 Then
+ pos = text.Length
+ End If
+
+ ' Substring() is zero-based'
+ Dim line As String = text.Substring(0, pos).Trim()
+ newtext += prefix + line + vbLf
+ text = text.Substring(pos)
+ End While
+
+ sel.Insert(newtext, vsInsertFlags.vsInsertFlagsContainNewText)
+End Sub
+```
+
+Note that [clang-format can auto-format code (including comments) with excellent adherence to the Chromium style guide](ClangFormat.md). It is probably a better bet than the above macro.
+
+## Remove trailing white spaces
+Add this sub to your EnvironmentEvents. When your .cc/.cpp/.c/.h is saved, trailing white spaces are removed automatically. No longer need to worry about presubmit giving nits.
+
+```
+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(".cc") _
+ 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
+```
+
+Note that [clang-format can auto-format code (including comments) with excellent adherence to the Chromium style guide](ClangFormat.md). It is probably a better bet than the above macro.
+
+## Alternate between source and header file
+
+Hint: Bind `SwitchOfSourceFile()` to Alt-O.
+```
+Function TryOpenProjectItem(ByVal project_items As ProjectItems, ByVal item As String) As Boolean
+ TryOpenProjectItem = False
+ If project_items Is Nothing Then
+ Exit Function
+ End If
+ For Each project_item As EnvDTE.ProjectItem In project_items
+ If Strings.StrComp(project_item.Name, item, CompareMethod.Text) = 0 Then
+ ' Found!'
+ project_item.Open().Activate()
+ TryOpenProjectItem = True
+ End If
+ If project_item.SubProject Is Nothing Then
+ TryOpenProjectItem = TryOpenProjectItem(project_item.ProjectItems, item)
+ Else
+ TryOpenProjectItem = TryOpenProjectItem(project_item.SubProject.ProjectItems, item)
+ End If
+ If TryOpenProjectItem = True Then
+ Exit Function
+ End If
+ Next
+End Function
+
+' Will find the file if it is:'
+' - beside in the same directory,'
+' - in "opened documents",'
+' - in the same project'
+' - TODO(maruel): Try in includes?'
+Public Function TryOpen(ByVal FileName As String, ByVal Path As String, ByVal project As EnvDTE.Project) As Boolean
+ TryOpen = False
+ ' Try to open the file in same folder.'
+ Try
+ DTE.Documents.Open(Path + FileName, "Text")
+ TryOpen = True
+ Exit Function
+ Catch
+ End Try
+
+ ' Search document in the same project.'
+ If Not project Is Nothing Then
+ TryOpen = TryOpenProjectItem(project.ProjectItems, FileName)
+ End If
+
+ ' Search opened documents.'
+ For Each myDocument As EnvDTE.Document In DTE.Documents
+ If Strings.StrComp(myDocument.Name, FileName, CompareMethod.Text) = 0 Then
+ Try
+ myDocument.Activate()
+ TryOpen = True
+ Exit Function
+ Catch
+ End Try
+ End If
+ Next
+End Function
+
+' Shortcut.'
+Public Function TryOpen(ByVal FilePathName As String) As Boolean
+ TryOpen = TryOpen(System.IO.Path.GetFileName(FilePathName), System.IO.Path.GetFullPath(FilePathName), Nothing)
+End Function
+
+' Will cycle thru .cc, .cpp, .h and .inl file extensions'
+Public Sub SwitchOfSourceFile()
+ ' For source looping. It\'s not extension in the true meaning.'
+ Dim supportedExts As String() = {"-inl.h", ".cc", ".cpp", ".h", ".hpp", ".inl"}
+
+ Dim origFile As String
+ Dim origFilePath As String
+ Dim project As EnvDTE.Project
+ Try
+ origFile = DTE.ActiveDocument.Name
+ origFilePath = DTE.ActiveDocument.Path
+ project = DTE.ActiveDocument.ProjectItem.ContainingProject
+ Catch
+ Exit Sub
+ End Try
+
+ ' This is touchy here because we want to support both ".h" and "-inl.h" so we have to find the right extension first.'
+ For indexExt As Integer = 0 To supportedExts.Length - 1
+ Dim ext As String = supportedExts(indexExt)
+ If origFile.Length > ext.Length Then
+ If origFile.Substring(origFile.Length - ext.Length) = ext Then
+ Dim FileToOpen As String = origFile.Substring(0, origFile.Length - ext.Length)
+ ' Try the rest'
+ For indexTry As Integer = 0 To supportedExts.Length - 2
+ Dim trueIndex As Integer = (indexExt + indexTry + 1) Mod supportedExts.Length
+ If TryOpen(FileToOpen + supportedExts(trueIndex), origFilePath, project) Then
+ ' We succeeded'
+ Exit Sub
+ End If
+ Next
+ ' We failed.'
+ Exit For
+ End If
+ End If
+ Next
+ ' We failed.'
+End Sub
+```
+
+
+## Run the currently selected google test
+See the function's description.
+```
+Sub RunCurrentGTest()
+ ' From the active source file, find the test that the user wants to run'
+ ' based on the current cursor position. Set the project containing this'
+ ' source file as the startup project, changes the command line to run'
+ ' only this test, compile the project and starts it under the debugger.'
+ ' Doesn\'t change any breakpoint.'
+ Dim ActiveDoc As Document = DTE.ActiveDocument
+
+ ' Try to guess the test to run.'
+ Dim TestGroup As String = ""
+ Dim TestName As String = ""
+ Dim selection As TextSelection = CType(ActiveDoc.Selection(), TextSelection)
+ Dim toppoint As EditPoint = selection.TopPoint.CreateEditPoint()
+ Dim bottompoint As EditPoint = selection.BottomPoint.CreateEditPoint()
+ Dim ranges As TextRanges = selection.TextRanges
+ Dim line As Integer = selection.TopPoint.Line
+ ' selection.FindPattern() is crummy.'
+ While line <> 0
+ selection.GotoLine(line)
+ selection.SelectLine()
+ Dim match As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(selection.Text, "TEST[_F]*\((.*),(.*)\)")
+ If Not match Is System.Text.RegularExpressions.Match.Empty Then
+ TestGroup = match.Groups.Item(1).Value.Trim()
+ TestName = match.Groups.Item(2).Value.Trim()
+ Exit While
+ End If
+ line = line - 1
+ End While
+ ' Cheap way to try to restore the old selection. Isn\'t 100% correct.'
+ selection.MoveToLineAndOffset(toppoint.Line, toppoint.LineCharOffset)
+ selection.MoveToLineAndOffset(bottompoint.Line, bottompoint.LineCharOffset, True)
+
+ ' From the current active document, find the project and the active configuration.'
+ Dim Proj As Project = ActiveDoc.ProjectItem.ContainingProject
+ Dim config As Configuration = Proj.ConfigurationManager.ActiveConfiguration
+
+ ' Fix the command line argument.'
+ Dim CmdLine As EnvDTE.Property = config.Properties.Item("CommandArguments")
+ If TestGroup <> "" Then
+ CmdLine.Value = "--gtest_filter=" & TestGroup & "." & TestName
+ Else
+ ' Run all'
+ CmdLine.Value = ""
+ End If
+
+ ' Set it as startup project.'
+ Dim SoluBuild As SolutionBuild = DTE.Solution.SolutionBuild
+ Dim StartupProject As String
+ StartupProject = Proj.UniqueName
+ SoluBuild.StartupProjects = StartupProject
+
+ ' Build it.'
+ SoluBuild.BuildProject(config.ConfigurationName, Proj.UniqueName, True)
+
+ ' Start it.'
+ DTE.Debugger.Go()
+End Sub
+```
+
+## Add a definition in a .cc file for the currently selected method/variable declarations.
+Select a class method or member variable declaration, then run this macro to add empty definitions in the corresponding .cc file.
+Hint: Bind AddDefinitionForSelectedDeclaration() to Alt-D
+```
+Public Sub AddDefinitionForSelectedDeclaration()
+ ' Get the function declaration text.'
+ Dim sel As TextSelection = DTE.ActiveDocument.Selection
+ Dim text = sel.Text.Trim()
+
+ Dim className = ClassNameFinder()
+
+ Dim funcDef = text
+ ' Remove comments first, since they mess up the rest of the regexes.'
+ funcDef = Regex.Replace(funcDef, "//.*$", "", RegexOptions.Multiline)
+ ' Try to put declarations all on the same line.'
+ funcDef = Regex.Replace(funcDef, "([^;]) *\n *", "$1 ", RegexOptions.Singleline)
+ ' Replace the identifier with ClassName::identifier.'
+ funcDef = Regex.Replace(funcDef, "^(.*) ([^ ()]+;|[^ ()]+ *\()", _
+ "$1 " + className + "::$2", RegexOptions.Multiline)
+ ' Convert ; to {} for functions.'
+ funcDef = Regex.Replace(funcDef, "\) *;", ") {" + vbLf + "}" + vbLf)
+ ' Remove leading whitespace, static/virtual.'
+ funcDef = Regex.Replace(funcDef, "^ *", "", RegexOptions.Multiline)
+ funcDef = Regex.Replace(funcDef, "static *", "// static" + vbLf)
+ funcDef = Regex.Replace(funcDef, "virtual *", "")
+ ' Collapse empty lines.'
+ funcDef = Regex.Replace(funcDef, vbLf + vbLf + "+", vbLf + vbLf)
+
+ ' Switch to source file and append defs at the end.'
+ GoToCCFile()
+ sel = DTE.ActiveDocument.Selection
+ sel.EndOfDocument()
+ sel.Insert(funcDef)
+End Sub
+
+' If the current document is an .h file, try to switch to the .cc file of the same name.'
+Sub GoToCCFile()
+ Dim origFile = DTE.ActiveDocument.FullName()
+ If Regex.IsMatch(origFile, "\.h$") Then
+ Dim altFile = Regex.Replace(origFile, "\.h$", ".cpp")
+ If Not My.Computer.FileSystem.FileExists(altFile) Then
+ altFile = Regex.Replace(origFile, "\.h$", ".cc")
+ End If
+ DTE.Documents.Open(altFile, "Text")
+ End If
+End Sub
+
+' Finds which class the cursor is inside of, and returns the class name.'
+' Note: This is indent based. Your class bodies must be indented, and the closing'
+' "};" must line up with the initial "class".'
+' ex: class Foo {\nclass Bar {\n <cursor>...'
+' returns: "Foo::Bar"''
+Private Function ClassNameFinder() As String
+ Dim sel As TextSelection = DTE.ActiveDocument.Selection
+ Dim origPos = sel.ActivePoint.AbsoluteCharOffset
+ Dim endLine = sel.CurrentLine
+
+ sel.MoveToAbsoluteOffset(1, True)
+ Dim pos = 0
+ Dim text = sel.Text
+ Dim className = ClassNameFinderInternal(text)
+ sel.MoveToAbsoluteOffset(origPos)
+
+ If className.Length > 0 Then
+ className = className.Substring(2)
+ End If
+ Return className
+End Function
+
+' Helper function for ClassNameFinder. Returns the full class name that doesn\'t'
+' have matching close braces in the given text string.'
+Private Function ClassNameFinderInternal(ByRef text As String) As String
+ Dim className = ""
+ While text.Length > 0
+ Dim match = Regex.Match(text, "^( *)class ([^ \n\r{:;]+)[^\n\r;]*$", RegexOptions.Multiline)
+ If match.Success Then
+ Dim indentString = match.Groups.Item(1).Value
+ Dim newClass = "::" + match.Groups.Item(2).Value
+ text = text.Substring(match.Index + match.Length)
+
+ match = Regex.Match(text, "^" + indentString + "};", RegexOptions.Multiline)
+ If match.Success Then
+ text = text.Substring(match.Index + match.Length)
+ Else
+ className += newClass + ClassNameFinderInternal(text)
+ End If
+ Else
+ text = ""
+ Exit While
+ End If
+ End While
+
+ Return className
+End Function
+
+
+```
+
+## Open all the files of a given change list.
+Specify which change list you want to open all files of, and this macro will find it if it lies in the same svn repository as the currently opened solution. If it can't find it there, it will prompt you to specify the path of the root of your client view.
+
+```
+Sub OpenChangeListFiles()
+ ' Open all the files of a given change list.'
+ Dim change_list_name As String = InputBox("Enter the change list name." + vbNewLine + "(with an optional repo folder path prefix)")
+ If String.IsNullOrEmpty(change_list_name) Then
+ Exit Sub
+ End If
+ Dim solution As Solution = DTE.Solution
+ ' Try to get the source root path starting from the solution path and search upward in the folder hierarchy.'
+ Dim source_root_path As String
+ If Not solution Is Nothing And Not String.IsNullOrEmpty(solution.FullName) Then
+ source_root_path = GetRepositoryRootFolder(solution.FullName)
+ End If
+ If source_root_path Is Nothing Or String.IsNullOrEmpty(source_root_path) Then
+ ' We couldn\'t find the root ourselves, ask the user.'
+ source_root_path = InputBox("Can't find a solution file path." + vbNewLine + "Please specify the root of your source tree.")
+ If String.IsNullOrEmpty(source_root_path) Then
+ Exit Sub
+ End If
+ End If
+    ' If we provided one or more \ in change_list_name, we want to check a subdirectory of the root path.'
+    ' This is useful if we have another repository in our solution.'
+    Dim change_list_path() As String = Split(change_list_name, "\")
+    If change_list_path.Length > 1 Then
+        source_root_path += "\" + String.Join("\", change_list_path, 0, change_list_path.Length - 1)
+        change_list_name = change_list_path(change_list_path.Length - 1)
+    End If
+ ' Look for the CL file in the appropriate folder.'
+ Dim change_list_file As String = source_root_path + "\.svn\gcl_info\changes\" + change_list_name
+ If Not IO.File.Exists(change_list_file) Then
+ ' OK, give one last chance to the user to specify the appropriate path for the CL.'
+ source_root_path = InputBox("Can't find CL: '" + change_list_name + "', under " + source_root_path + vbNewLine + "Specify the proper root folder one last time:")
+ If String.IsNullOrEmpty(source_root_path) Then
+ Exit Sub
+ End If
+ change_list_file = source_root_path + "\.svn\gcl_info\changes\" + change_list_name
+ If Not IO.File.Exists(change_list_file) Then
+ MsgBox("Can't find CL: '" + change_list_name + "', under " + source_root_path)
+ Exit Sub
+ End If
+ End If
+ ' Now load its content.'
+ Dim change_list_content As String
+ Try
+ change_list_content = IO.File.ReadAllText(change_list_file, Text.Encoding.GetEncoding(1252))
+ Catch e As Exception
+ MsgBox("Exception: " + e.Message())
+ Exit Sub
+ End Try
+ ' Match the lines where the paths of the opened files can be found.'
+ Dim pattern As String = "M\s*(.*)$"
+ Dim regex As New Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.Multiline)
+ Dim matches As Text.RegularExpressions.MatchCollection = regex.Matches(change_list_content)
+ Dim match
+ For Each match In matches
+ ' And now we can open each and everyone of them.'
+ Dim file_path As String = match.Groups(1).ToString()
+ Dim full_path As String = source_root_path + "\" + Left(file_path, file_path.Length() - 1)
+ If IO.File.Exists(full_path) Then
+ DTE.ItemOperations.OpenFile(full_path)
+ End If
+ Next
+End Sub
+
+Private Function GetRepositoryRootFolder(ByVal solution_path As String) As String
+ Try
+ ' We look for a change in the svn: root path in the .svn/entries file.'
+ ' This means we have reached view root or changed repo.'
+ Dim solution_folder As String = IO.Directory.GetParent(solution_path).ToString()
+ Dim svn_root_path As String = GetSvnRootPath(solution_folder)
+ If String.IsNullOrEmpty(svn_root_path) Then
+ ' We don'\t seem to be within a repo if we can\'t get the SVN root path.'
+ Return ""
+ End If
+ ' We need to keep the previous path, since we need to stop once we found a bad parent.'
+ Dim previous_path As String = solution_folder
+ While True
+ Dim next_path As String = IO.Directory.GetParent(previous_path).ToString()
+ Dim current_svn_root_path As String = GetSvnRootPath(next_path)
+ ' As long as we have the same svn root path, we are in the same repo, continue.'
+ If current_svn_root_path = svn_root_path Then
+ previous_path = next_path
+ Else
+ Exit While
+ End If
+ End While
+ Return previous_path
+ Catch e As Exception
+ MsgBox("Exception: " + e.Message())
+ End Try
+ Return Nothing
+End Function
+
+Private Function GetSvnRootPath(ByVal client_path As String) As String
+ ' First make sure we are within a repo.'
+ Dim svn_folder As String = client_path + "\.svn"
+ If Not IO.Directory.Exists(svn_folder) Then
+ Return ""
+ End If
+ ' Then there MUST be an entries file in there.'
+ Dim entries_file As String = svn_folder + "\entries"
+ If Not IO.File.Exists(entries_file) Then
+ Return ""
+ End If
+ ' Read the content of the file and find the svn root, and return it.'
+ Dim entries_content As String = IO.File.ReadAllText(entries_file, Text.Encoding.GetEncoding(1252))
+ Dim pattern As String = "svn:(.*)$"
+ Dim regex As New Text.RegularExpressions.Regex(pattern, Text.RegularExpressions.RegexOptions.Multiline)
+ Dim matches As Text.RegularExpressions.MatchCollection = regex.Matches(entries_content)
+ Return matches.Item(1).ToString()
+End Function
+
+
+```
+
+
+## Only build startup project
+
+Stolen from Boris, thanks!
+```
+Sub BuildStartupProject()
+ Dim sb As SolutionBuild = DTE.Solution.SolutionBuild
+ Dim projName As String = sb.StartupProjects(0)
+ DTE.ExecuteCommand("View.Output")
+ sb.BuildProject(sb.ActiveConfiguration.Name, projName, False)
+End Sub
+```
+
+
+## Use WinDbg as your debugger
+I fully regret writing this macro as it didn't pass the "time wasted to write it"/"utility" ratio. But I'm really too proud.
+
+```
+Sub WinbgStartupProject()
+ ' Use the right one:
+ Dim windbg As String = "C:\program files\Debugging Tools for Windows (x86)\windbg.exe"
+ 'Dim windbg As String = "C:\program files\Debugging Tools for Windows (x64)\windbg.exe"
+
+ Dim project_name As String = CType(DTE.Solution.SolutionBuild.StartupProjects(0), String)
+ Dim project As EnvDTE.Project = FindProjects(DTE.Solution.Projects, project_name)
+ Dim config As Configuration = project.ConfigurationManager.ActiveConfiguration
+ ' Hack to remove file:///
+ Dim target_path As String = config.OutputGroups.Item(1).FileURLs(0).ToString().Remove(0, 8)
+ Dim arguments As String = config.Properties.Item("CommandArguments").Value
+ 'MsgBox(windbg & " -o " & target_path & " " & arguments)
+ System.Diagnostics.Process.Start(windbg, "-o " & target_path & " " & arguments)
+End Sub
+
+Function FindProjectItems(ByVal project_items As EnvDTE.ProjectItems, ByVal project_name As String) As EnvDTE.Project
+ FindProjectItems = Nothing
+ For Each project_item As EnvDTE.ProjectItem In project_items
+ If Not project_item.SubProject Is Nothing Then
+ FindProjectItems = FindProject(project_item.SubProject, project_name)
+ If Not FindProjectItems Is Nothing Then Exit Function
+ End If
+ Next
+End Function
+
+Function FindProject(ByVal project As EnvDTE.Project, ByVal project_name As String) As EnvDTE.Project
+ If project.UniqueName = project_name Then
+ FindProject = project
+ Exit Function
+ End If
+ If Not project.ProjectItems Is Nothing Then
+ FindProject = FindProjectItems(project.ProjectItems, project_name)
+ If Not FindProject Is Nothing Then Exit Function
+ End If
+End Function
+
+Function FindProjects(ByVal projects As EnvDTE.Projects, ByVal project_name As String) As EnvDTE.Project
+ ' You never thought it'd be so complex to find a project. The VS extensibility team
+ ' stole me an hour of my life I will never get back.
+ FindProjects = Nothing
+ For Each project As EnvDTE.Project In projects
+ FindProjects = FindProject(project, project_name)
+ If Not FindProjects Is Nothing Then Exit Function
+ Next
+End Function
+```
+
+
+## Indent to open-paren on line-wrap
+
+This macro is slightly different than the rest. You'll need to put it in your EnvironmentEvents project rather than Module, since it runs on every keypress.
+
+What it does is indent your cursor up to the level of the open-paren on the previous line when you hit Enter.
+
+```
+ Public Sub keypress(ByVal key As String, ByVal sel As TextSelection, ByVal completion As Boolean, ByRef cancel As Boolean) _
+ Handles TextDocumentKeyPressEvents.BeforeKeyPress
+ If (Not completion And key = vbCr) Then
+ Dim textDocument As TextDocument = DTE.ActiveDocument.Object("TextDocument")
+ Dim startPoint As EditPoint = textDocument.StartPoint.CreateEditPoint()
+ startPoint.MoveToLineAndOffset(sel.ActivePoint.Line, 1)
+ Dim text = startPoint.GetText(sel.ActivePoint.LineCharOffset - 1)
+ Dim pos = findUnclosedParenIndent(text)
+
+ If pos <> -1 Then
+ Dim commentPos = text.IndexOf("//")
+ If commentPos = -1 Or commentPos > pos Then
+ sel.Insert(vbLf)
+ sel.DeleteWhitespace()
+ sel.PadToColumn(pos + 2)
+ cancel = True
+ End If
+ End If
+ End If
+ End Sub
+
+ Public Function findUnclosedParenIndent(ByRef text As String) As Integer
+ findUnclosedParenIndent = -1
+
+ Dim parens As Char() = "()".ToCharArray()
+ Dim lastPos = text.Length
+ Dim numClosed = 0
+
+ While True
+ Dim pos = text.LastIndexOfAny(parens, lastPos - 1)
+
+ If pos = -1 Then
+ Exit While
+ End If
+
+ If text(pos) = ")" Then
+ numClosed += 1
+ Else
+ If numClosed = 0 Then
+ findUnclosedParenIndent = pos
+ Exit While
+ End If
+ numClosed -= 1
+ End If
+
+ lastPos = pos
+ End While
+ End Function
+```
+
+## Add other useful macros here
+Feel free to edit this page to add other useful macros.

Powered by Google App Engine
This is Rietveld 408576698