public CommandProcessor(MainPackage package) { this.package = package; this.dte = (DTE)this.GetService(typeof(SDTE)); this.options = this.package.Options; this.options.Applied += (s, e) => this.ApplyOptions(); this.ApplyOptions(); }
public BuildTimer(MainPackage package) { this.package = package; this.dte = (DTE)this.GetService(typeof(SDTE)); // We must hold a reference to the returned BuildEvents instance. Otherwise, we won't get callbacks/events. // https://social.msdn.microsoft.com/Forums/vstudio/en-US/1d5da1f9-fb03-4d78-804b-d708557d3331/advisebuildstatuscallback?forum=vsx this.buildEvents = this.dte.Events.BuildEvents; this.buildEvents.OnBuildBegin += this.BuildEvents_OnBuildBegin; this.buildEvents.OnBuildDone += this.BuildEvents_OnBuildDone; this.buildEvents.OnBuildProjConfigBegin += this.BuildEvents_OnBuildProjConfigBegin; this.buildEvents.OnBuildProjConfigDone += this.BuildEvents_OnBuildProjConfigDone; }
public static void CommentSelection(DTE dte, MainPackage package, bool comment) { TextDocumentHandler handler = new TextDocumentHandler(dte); if (handler.HasNonEmptySelection) { Language language = handler.Language; bool useVsIndentation = GetCommentStyle( language, package.Options.UseVsStyleCommentIndentation, false, out string beginDelimiter, out string endDelimiter); // The Edit.CommentSelection and Edit.UncommentSelection commands do 95% of what I want. // However, I want to add/remove a space after the opening (and before the closing) delimiter, // and I prefer that single-line comments be indented to match the code. So I'll fallback to the // VS commands for any languages I don't have custom logic for. bool useSingleLineStyle = string.IsNullOrEmpty(endDelimiter); bool useSingleLineVsIndentation = comment && useSingleLineStyle && useVsIndentation; string commandName = comment ? "Comment Selection" : "Uncomment Selection"; if (string.IsNullOrEmpty(beginDelimiter) || useSingleLineVsIndentation) { // Nest the undo contexts for the VS command and our additional logic. handler.Execute( commandName, () => { ExecuteVsCommentCommand(dte, comment); if (!string.IsNullOrEmpty(beginDelimiter) && useSingleLineVsIndentation) { UpdateSelectedText(handler, commandName, lines => lines.AddCommentSpace(beginDelimiter)); } }); } else if (useSingleLineStyle) { UpdateSelectedText(handler, commandName, lines => lines.Comment(comment, beginDelimiter)); } else { UpdateSelectedText(handler, commandName, lines => lines.Comment(comment, beginDelimiter, endDelimiter)); } } }
public ToggleFilesHandler(DTE dte, MainPackage package) { this.dte = dte; this.document = dte.ActiveDocument; this.package = package; }
public bool CanExecute(Command command) { try { bool result = false; if (this.dte != null) { switch (command) { // These require a text selection. case Command.SortLines: case Command.Trim: case Command.Statistics: case Command.StreamText: case Command.ExecuteText: case Command.CheckSpelling: result = new TextDocumentHandler(this.dte).HasNonEmptySelection; break; // These require a text selection for specific languages. case Command.CommentSelection: case Command.UncommentSelection: result = CommentHandler.CanCommentSelection(this.dte, command == Command.CommentSelection); break; // These require a document using a supported language. case Command.AddRegion: case Command.CollapseAllRegions: case Command.ExpandAllRegions: result = RegionHandler.IsSupportedLanguage(this.ActiveLanguage); break; // These require an open document with a backing file on disk. case Command.ExecuteFile: case Command.ToggleReadOnly: string fileName = this.GetDocumentFileName(); result = File.Exists(fileName); break; case Command.GenerateGuid: result = new TextDocumentHandler(this.dte).CanSetSelectedText; break; case Command.ToggleFiles: result = ToggleFilesHandler.IsSupportedLanguage(this.ActiveLanguage); break; case Command.ListAllProjectProperties: result = ProjectHandler.GetSelectedProjects(this.dte, null); break; case Command.ViewBaseConverter: case Command.ViewTasks: result = true; break; case Command.SortMembers: result = new MemberSorter(this.dte, false).CanFindMembers; break; case Command.AddToDoComment: result = CommentHandler.CanAddToDoComment(this.dte); break; } } return(result); } catch (Exception ex) { MainPackage.LogException(ex); throw; } }
public void Execute(Command command) { try { if (this.dte != null) { switch (command) { case Command.AddRegion: RegionHandler.AddRegion(this.dte, Options.SplitValues(this.package.Options.PredefinedRegions)); break; case Command.CheckSpelling: this.CheckSpelling(); break; case Command.CollapseAllRegions: RegionHandler.CollapseAllRegions(this.dte, this.ActiveLanguage, this.package); break; case Command.CommentSelection: case Command.UncommentSelection: CommentHandler.CommentSelection(this.dte, this.package, command == Command.CommentSelection); break; case Command.ExecuteFile: this.ExecuteFile(); break; case Command.ExecuteText: this.ExecuteText(); break; case Command.ExpandAllRegions: RegionHandler.ExpandAllRegions(this.dte, this.ActiveLanguage); break; case Command.GenerateGuid: this.GenerateGuid(); break; case Command.ListAllProjectProperties: ProjectHandler.ListAllProjectProperties(this.dte); break; case Command.SortLines: this.SortLines(); break; case Command.Statistics: this.Statistics(); break; case Command.StreamText: this.StreamText(); break; case Command.ToggleFiles: ToggleFilesHandler toggleFilesHandler = new ToggleFilesHandler(this.dte, this.package); toggleFilesHandler.ToggleFiles(); break; case Command.ToggleReadOnly: this.ToggleReadOnly(); break; case Command.Trim: this.Trim(); break; case Command.ViewBaseConverter: this.ViewToolWindow(typeof(BaseConverterWindow)); break; case Command.SortMembers: this.SortMembers(); break; case Command.AddToDoComment: CommentHandler.AddToDoComment(this.dte); break; case Command.ViewTasks: this.ViewToolWindow(typeof(Tasks.TasksWindow)); break; } } } catch (Exception ex) { MainPackage.LogException(ex); throw; } }
public CommandProcessor(MainPackage package) { ThreadHelper.ThrowIfNotOnUIThread(); this.package = package; this.dte = (DTE)this.GetService(typeof(SDTE)); }
// Collapses all regions in the current document public static void CollapseAllRegions(DTE dte, Language language, MainPackage package, bool showErrors = true) { if (IsSupportedLanguage(language)) { dte.SuppressUI = true; // Disable UI while we do this try { // Outling must be enabled. If Outlining is turned off then the rest of this method will get stuck in an infinite loop. // It can be turned off by default from the C# advanced text editor properties, or it can be turned off by running // the Edit.StopOutlining command (e.g., in the Command window or via Edit -> Outlining -> Stop Outlining). // If the Edit.StartAutomaticOutlining command is available, then that means outlining needs to be turned back on. const string StartOutliningCommand = "Edit.StartAutomaticOutlining"; EnvDTE.Command command = dte.Commands.Item(StartOutliningCommand); if (command.IsAvailable) { dte.ExecuteCommand(StartOutliningCommand); } const string ToggleOutliningExpansion = "Edit.ToggleOutliningExpansion"; command = dte.Commands.Item(ToggleOutliningExpansion); const int MaxAttempts = 3; int maxAttempts = command.IsAvailable ? MaxAttempts : 0; string regionBeginRegex = GetRegionBeginRegex(language); // Sometimes VS can't collapse some regions, so we'll try the whole operation a few times if necessary. bool failedToCollapse = true; for (int attempt = 1; attempt <= maxAttempts && failedToCollapse; attempt++) { failedToCollapse = false; ExpandAllRegions(dte, language); // Force the expansion of all regions TextSelection selection = (TextSelection)dte.ActiveDocument.Selection; // Hook up to the ActiveDocument's selection selection.EndOfDocument(); // Shoot to the end of the document // Find the first occurence of #region from the end of the document to the start of the document. int currentFindOffset = 0; int previousFindOffset = int.MaxValue; const int FindOptions = (int)vsFindOptions.vsFindOptionsBackwards + (int)vsFindOptions.vsFindOptionsMatchCase + (int)vsFindOptions.vsFindOptionsRegularExpression; while (selection.FindText(regionBeginRegex, FindOptions)) { currentFindOffset = selection.TopPoint.AbsoluteCharOffset; if (currentFindOffset >= previousFindOffset) { // I don't want to get stuck in an infinite loop. I'd rather throw if something unexpected happens. throw new InvalidOperationException(string.Format( "FindText did not go backward! Previous offset: {0}; Current offset: {1}.", previousFindOffset, currentFindOffset)); } // We can ignore matches where #region is used inside a string or single line comment. // However, this still won't detect if it's used inside a multiline comment with the opening // delimiter on another line. selection.SelectLine(); string lineText = selection.Text ?? string.Empty; // Make sure the region begin token is the first non-whitespace on the line. Match match = Regex.Match(lineText.TrimStart(), regionBeginRegex); if (match.Success && match.Index == 0) { // The SelectLine call above will leave the end anchor on the next line. If there's no blank line between // a #region line and an XML doc comment after it, then having the end anchor on the line with the // XML doc comment will cause the comment to collapse instead of the #region. So we'll avoid that // by moving back to the find offset. selection.MoveToAbsoluteOffset(currentFindOffset); // Try to increase the chances that the ToggleOutliningExpansion command will be available. selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText); // Collapse this #region. Sometimes VS reports that the Edit.ToggleOutliningExpansion command // isn't available even though it should be. Poke it and give it a little bit of time to sync up. if (!command.IsAvailable) { const int WaitMilliseconds = 20; System.Threading.Thread.Sleep(WaitMilliseconds); int tempOffset = selection.TopPoint.AbsoluteCharOffset; selection.CharRight(); selection.MoveToAbsoluteOffset(tempOffset); System.Threading.Thread.Sleep(WaitMilliseconds); } if (command.IsAvailable) { // If #region is found in a multiline comment, then this will collapse the enclosing block. dte.ExecuteCommand(ToggleOutliningExpansion); } else { // We couldn't collapse a #region. failedToCollapse = true; } } // Move to the start of the last FindText match, so we can continue searching backward from there. selection.MoveToAbsoluteOffset(currentFindOffset); previousFindOffset = currentFindOffset; } selection.StartOfDocument(); // All done, head back to the start of the doc } if (failedToCollapse && package != null && showErrors) { package.ShowMessageBox( "Some regions couldn't be collapsed because Visual Studio's Edit.ToggleOutliningExpansion command wasn't available.", true); } } finally { dte.SuppressUI = false; // Reenable the UI } } }