microsoft / VSExtensibility

A repo for upcoming changes to extensibility in Visual Studio, the new extensibility model, and language server protocol.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Changing caret position

LeeMSilver opened this issue · comments

According to the comments in the EditAsync() definition:
'Initiates an edit request in the host Visual Studio process, enabling the extension
to atomically request one or more Microsoft.VisualStudio.Extensibility.Editor.ITextDocumentSnapshot
edits, caret position changes, or other state changes.'

Is it documented how to make caret position changes?

The selection (caret) is part of https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.extensibility.editor.itextviewsnapshot?view=vs-extensibility so apply edits to its editable version (ITextViewSnapshot.AsEditable())

'... so apply edits to its editable version (ITextViewSnapshot.AsEditable())'

Are you saying that the Delete/Insert/Replace methods affect the selection (caret)? (the comments in ITextDocumentEditor do not indicate this.

Even if so, I sometimes need to set the caret independent of the above methods - to a position not affected by the above methods.

@LeeMSilver, editing text document implicitly affects caret position, for example inserting some text at the caret will move the caret to the end of the inserted text:

await this.Extensibility.Editor().EditAsync(
    batch =>
    {
        textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
    },
    cancellationToken);

You can use ITextViewSnapshot.AsEditable().SetSelections() to set the caret explicitly to a different position, e.g. this code would insert some text, but keep the caret at the original position:|

await this.Extensibility.Editor().EditAsync(
    batch =>
    {
        var caret = textView.Selection.Extent.Start;
        textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
        textView.AsEditable(batch).SetSelections([new Selection(activePosition: caret, anchorPosition: caret, insertionPosition: caret)]);
    },
    cancellationToken);

Thanks - that's exactly what I am looking for.

Is it documented anywhere that AsEditable is also an extension-method for ITextViewSnapshot besides being an extension-method for ITextViewSnapshot.Document?

If I had known this I would not have needed to ask the question.

@LeeMSilver fair point about documentation. I'm tracking this issue internally.

@LeeMSilver, editing text document implicitly affects caret position, for example inserting some text at the caret will move the caret to the end of the inserted text:

await this.Extensibility.Editor().EditAsync(
    batch =>
    {
        textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
    },
    cancellationToken);

You can use ITextViewSnapshot.AsEditable().SetSelections() to set the caret explicitly to a different position, e.g. this code would insert some text, but keep the caret at the original position:|

await this.Extensibility.Editor().EditAsync(
    batch =>
    {
        var caret = textView.Selection.Extent.Start;
        textView.Document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
        textView.AsEditable(batch).SetSelections([new Selection(activePosition: caret, anchorPosition: caret, insertionPosition: caret)]);
    },
    cancellationToken);

I just tried this code but it did not work. The caret is not preserved.

Even though sometimes it seems to work, in reality, if the user presses up/down, the keyboard real anchor is at the end of the file and not at the caret position specified/displayed.

I can even see two caret markers:
A blue caret (the caret position I specified in SetSelections)
image

A red caret (the one the keyboard/VS is really responding to).
image

@olegtk is there something I'm missing or could it be a bug in the API?