Beispiel #1
0
 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;
 }
Beispiel #5
0
        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;
            }
        }
Beispiel #6
0
        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;
            }
        }
Beispiel #7
0
 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
                }
            }
        }