mrlacey/CollapseComments

Extension makes the Undo/Redo unusable [there's a fix]

Closed this issue · 4 comments

Installed product versions

  • Visual Studio 2022 CE
  • CollapseComments v 2.5.1

Description

If I do:
Ctrl + M, Ctrl + M (collapsing everything)
I see only one entry in the Undo history

Ctrl + M, Ctrl + L (expanding everything)
this correctly adds only one entry in the Undo history

Ctrl + M, Ctrl + C (collapsing only the comments)
this correctly adds 100 entries in the Undo history if I have 100 functions in the code.

CollapseComments works very nicely, thanks a lot for that!,

but then every comments section that is collapsed adds one entry in the undo/redo history.

This not only is annoying and it makes the undo redo history useless, but also it makes VS unusable too, or very slow to say the least, if you try to undo like 20 of those undo entries.

There are two solutions for that.


### SOLUTION 1:
The simple workaround I used was to use this extension by Sergey Vlasov:
Disable Outlining Undo

reported in ide - Visual Studio _ exclude outlining from undo_redo stack - Stack Overflow

To have had the outlining actions go into the undo/redo history has always been a strong nuisance of Visual Studio for me (and clearly not only me).


In this extension the value of DefaultTextViewOptions.OutliningUndoOptionId is simply set to false.
Here is roughly a possible code equivalent to that of the 'Disable Outlining Undo' extension (using ChatGPT)

using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Formatting;

public class MyTextViewCreationListener : TextViewCreationListener
{
    public override void TextViewCreated(ITextView textView)
    {
        if (textView.Options is IEditorOptions editorOptions)
        {
            //getting the value
            object outliningUndoOptionId = textView.Options.GetOptionValue(DefaultTextViewOptions.OutliningUndoOptionId);
            int outliningUndoOptionIdValue = (int)outliningUndoOptionId;

            //setting the value to disable undo for outlines
            editorOptions.SetOptionValue(DefaultTextViewOptions.OutliningUndoOptionId, false);
        }
    }
}

Registering the TextViewCreationListener listener:

using Microsoft.VisualStudio.Shell;

protected override void Initialize()
{
    base.Initialize();

    var textViewCreationListener = new MyTextViewCreationListener();
    var textViewCreationService = GetService(typeof(ITextViewCreationListener)) as ITextViewCreationListener;

    if (textViewCreationService != null)
    {
        textViewCreationService.TextViewCreated += textViewCreationListener.TextViewCreated;
    }
}

A different implementation of this could be to simply to derive from
as explained in here and by MS here
Something on the line of (didn't test it):

using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;

[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.PrimaryDocument)]
internal sealed class MyWpfTextViewCreationListener : IWpfTextViewCreationListener
{
    public void TextViewCreated(IWpfTextView textView)
    {
        try
        {
            if (textView.Options.IsOptionDefined<bool>(DefaultTextViewOptions.OutliningUndoOptionId, false))
            {
                textView.Options.SetOptionValue<bool>(DefaultTextViewOptions.OutliningUndoOptionId, false);
            }
        }
        catch (Exception)
        {
        }
    }
}


If this idea would be integrated in the 'Collapse Comments' extension then it would be a good idea to re-enable the undo/redo stack after the outlining were concluded, or even better to restore the value of 'DefaultTextViewOptions.OutliningUndoOptionId' to the one it had before the collapsing operation was started.






### SOLUTION 2:
Even better would probably be to gather the entire action in a single undo/redo entry in the undo/redo history.

The raw code for this is (again using ChatGPT):

# References to add:
#   Microsoft.VisualStudio.Shell.17.0.dll
#   Microsoft.VisualStudio.Text.Data.17.0.dll
#   Microsoft.VisualStudio.Text.Logic.17.0.dll



using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.TextManager.Interop;

public class GroupUndoRedoExtension
{
    private IWpfTextView _textView;
    private IEditorOperations _editorOperations;

    public GroupUndoRedoExtension(IWpfTextView textView, IEditorOperationsFactoryService editorOperationsFactory)
    {
        _textView = textView;
        _editorOperations = editorOperationsFactory.GetEditorOperations(_textView);
    }

    public void GroupActions()
    {
        // Start a compound action to group multiple actions
        _editorOperations.BeginCompositeUndo();

        // Perform the individual actions
        // Example: Insert text at the current caret position
        _editorOperations.InsertText("Hello, World!");

        // End the compound action to group the actions
        _editorOperations.EndCompositeUndo();
    }
}



Sorry for using ChatGPT actually.


I hope this helps, and maybe it will be integrated one day in this extension.

Thanks for reporting this, I didn't even realize that collapsing (or expanding) regions created entries in the undo/redo stack. I thought they were only created when file content was changed.

Fix coming in v2.6

v2.6 (released yesterday) added a new configurable option:

image

With this set to False, it will not create undo entries when anything is collapsed or expanded.

Personally I'd suggest False as default because nobody would want dozens of undo CollapseComments entries, unless they'd grouped into one.

But it works, I checked, and I'm very happy with that.