/// <summary> /// Marks a region of code for extraction. It pastes the correct comment characters for the /// file type at the top and bottom of the region. If the user has selected to add 'TODO' comments /// and the editor for this file type supports commenting regions, it will also prompt /// the user for a TODO comment and place that comment above the region of code to be /// marked for extraction. /// </summary> public void Exec(EnvDTE.vsCommandExecOption executeOption, ref object varIn, ref object varOut) { try { // First, get ahold of the necessary items to get the data we need CommentPair comments = GetCurrentComments(); if (comments == null) { return; } // Get the document EnvDTE.EditPoint startPoint, endPoint; EnvDTE.TextDocument textDocument = m_applicationObject.ActiveDocument.Object("TextDocument") as EnvDTE.TextDocument; if (textDocument != null) { if (textDocument.Selection.BottomPoint.AtStartOfLine && textDocument.Selection.IsActiveEndGreater) { // People whom select a whole section of text often also get the first // not-character of the next line (because that's how windows mouse-selection // works!). They only want to go around the highlighted section... textDocument.Selection.CharLeft(true, 1); } textDocument.Selection.Insert(comments.BeginComment + "\n", (int)EnvDTE.vsInsertFlags.vsInsertFlagsInsertAtStart); textDocument.Selection.Insert("\n" + comments.EndComment, (int)EnvDTE.vsInsertFlags.vsInsertFlagsInsertAtEnd); // Store away the selection for use after the TODO comment // is added. Create new EditPoint objects here because they // cause the editor to keep track of the markers in the text, even // when the selection changes. startPoint = textDocument.Selection.TopPoint.CreateEditPoint(); endPoint = textDocument.Selection.BottomPoint.CreateEditPoint(); MaybeAddTodoComment(textDocument.Selection); // Restore the selection textDocument.Selection.MoveToPoint(startPoint, false); textDocument.Selection.MoveToPoint(endPoint, true); // Perform the selection hiding (code collapse) only if the editor is not // in auto-select mode and if the user has enabled it in the tools options // page for the academic toolset. This is done last because some language // services move the Top and Bottom points of the Selection around when // performing an outline. if (EditorSupportsHideSelection() && ((bool)((EnvDTE.Properties)m_applicationObject.get_Properties("Assignment Manager", "Code Extractor")).Item("Collapse").Value)) { textDocument.Selection.TopPoint.CreateEditPoint().OutlineSection(textDocument.Selection.BottomPoint); } } } catch (System.Exception /*e*/) { } }
/// <summary> /// This command is available if both the file type is valid and if the document /// contains a selection of non-zero size. /// </summary> public void QueryStatus(ref EnvDTE.vsCommandStatus status) { // If there is no supported extension, remove it. If it's supported, but there's no // document selection currently, then disable it (gray-out). CommentPair comments = GetCurrentComments(); if (comments == null) { status = EnvDTE.vsCommandStatus.vsCommandStatusInvisible | EnvDTE.vsCommandStatus.vsCommandStatusUnsupported; } else { EnvDTE.TextDocument textDocument = m_applicationObject.ActiveDocument.Object("TextDocument") as EnvDTE.TextDocument; if (m_applicationObject.ActiveWindow.Document == m_applicationObject.ActiveDocument) { if (textDocument == null) { // Never can happen because of GetCurrentComments' implementation throw new Exception(); } if (textDocument.Selection.TopPoint.AbsoluteCharOffset == textDocument.Selection.BottomPoint.AbsoluteCharOffset) { status = EnvDTE.vsCommandStatus.vsCommandStatusUnsupported; } else { status = EnvDTE.vsCommandStatus.vsCommandStatusEnabled | EnvDTE.vsCommandStatus.vsCommandStatusSupported; } } else { status = EnvDTE.vsCommandStatus.vsCommandStatusUnsupported; } } }
/// <summary> /// Loops through each of the items in the project, attempting to extract any sections of code /// marked. /// </summary> /// <param name="dte"> Pointer to Object Model in which all actions should be performed </param> private bool ExtractItems(EnvDTE.ProjectItems projSourceItems, EnvDTE._DTE dte, EnvDTE.ProjectItems projDestItems) { EnvDTE.ProjectItem projItem = null; EnvDTE.TextDocument textDoc = null; EnvDTE.Properties extractorProperties = null; Extensions extensions = null; CommentPair comments = null; EnvDTE.Window w = null; bool fSuccess = true; int i, nItems, nLastIndex; string strExtension; extractorProperties = m_application.get_Properties("Assignment Manager", "Code Extractor"); if (extractorProperties == null) { throw new Exception("The Academic Code Extractor is not properly installed and configured."); } extensions = extractorProperties.Item("Extensions").Object as Extensions; if (extensions == null) { throw new Exception("The Academic Code Extractor is not properly installed and configured."); } nItems = projDestItems.Count; for (i = 1; i <= nItems; i++) { projItem = projDestItems.Item(i); try { if (projItem.ProjectItems.Count > 0) { ExtractItems(projSourceItems.Item(i).ProjectItems, dte, projItem.ProjectItems); } // Note that this will *actually* be happening in an invisible // out-of-process instance of VS, so the user will not be // subjected to appearing / disappearing windows. w = projItem.Open(EnvDTE.Constants.vsViewKindTextView); textDoc = w.Document.Object("TextDocument") as EnvDTE.TextDocument; strExtension = projItem.get_FileNames(1); nLastIndex = strExtension.LastIndexOf('.'); if (nLastIndex == -1) { w.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo); continue; // We have no capacity for files with no extension. } strExtension = strExtension.Remove(0, nLastIndex + 1); // Trim off the 'name.' part of 'name.ext' comments = extensions[strExtension]; if (comments == null) { w.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo); continue; // This file has no associated extension type. Ignore it. } fSuccess &= ExtractText(textDoc, comments.BeginComment, comments.EndComment, projSourceItems); w.Close(EnvDTE.vsSaveChanges.vsSaveChangesYes); } catch (Exception /*e*/) { // If we end up here, that simply means that the file // has no text. Since we obviously don't want to remove the // textual tags from a file with no comments... if (w != null) { w.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo); } } } return(fSuccess); }