VS Code inline completion feature in SyntaxEditor?

SyntaxEditor for WPF Forum

Posted 6 months ago by Kai Nguyen
Version: 23.1.3
Avatar

Hi,

I want to achieve something similar in the SyntaxEditor like the VS Code inline completion feature where a ghost text shows up after the text cursor as a code suggestion. Is there any way to achieve this with the SyntaxEditor?

I've read a bit about Adornments and I suspect I might have to tinker with something like the Intraline Adornment. I'm a beginner so the documentation is a bit confusing for me on how to implement that feature so if someone could help out I'd really appreciate it!

[Modified 6 months ago]

Comments (8)

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

While we haven't made a sample for that as of yet, you'd probably want to use our intra-text adornments feature.  The QuickStart sample in the AdornmentsIntraTextNotes folder of our samples app shows an example of that kind of thing.  It shows how to inject a custom control inline with text that moves as editing occurs around it.

For your scenario, you'd be injecting a TextBlock instead of a button and you'd probably "tag" a zero-length range at the caret offset.  The tag is wrap gets used to trigger an adornment, which is explained in much more detail in the documentation.

The code line to use for making an ITextVersionRange for your scenario (similar to what's in the above sample's MainControl.OnAddNoteButtonClick method) would need be something like the following, since the sample doesn't allow zero-length tags:

var versionRange = new TextSnapshotRange(editor.ActiveView.CurrentSnapshot,
  editor.ActiveView.Selection.CaretOffset).ToVersionRange(TextRangeTrackingModes.DeleteWhenSurrounded);

I hope that helps get you started!


Actipro Software Support

Posted 6 months ago by Kai Nguyen
Avatar

Hi,

Thank you for providing me with resources! From my understanding, the AdornmentManagerProvider is what provides the adornment managers that are responsible for displaying the adornments in a document. So far the examples have shown them being used/registered as a language service. Can the adornments be used without being registered as a language service?

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Adornments and many other features of SyntaxEditor are all based on a language service model, and are only available through that mechanism.  This is because a syntax language can be assigned to one or more SyntaxEditor instances, and each SyntaxEditor can itself show multiple views.  The language service model allows features like adornments to be supplied to all views in any SyntaxEditor that uses the related syntax language.  If you only wanted the adornments on a specific SyntaxEditor instance, you could make a custom syntax language (only used by that SyntaxEditor) that just had the related adornment manager provider service on it.


Actipro Software Support

Posted 6 months ago by Kai Nguyen
Avatar

Hello,

I've had a look at the QuickStart sample in your AdornmentsIntraTextNotes folder. I was wondering how/when is the overrride method AddAdornment in the IntraTextNoteAdornmentManager being called? I tested implementing this sample in my own solution to test it out, but the adornments within the AddAdornment method is never displayed. Do I have to explicitly call AddAdornment in my main control?

Posted 6 months ago by Kai Nguyen
Avatar

The adornments seems to be rendering now but only after I've created an instance of my intra text manager in my main control. I thought this wasn't necessary since I had registered my intra text manager as a language service, maybe something else is wrong?

In any case, another problem I'm facing is that if I have a TextBlock that contains multiple lines of code and I insert it into the editor, say in the middle of a function block for example, the TextBlock is inserted but doesn't push down the code below it. I'd like for it to create additional space in the editor lines for the entire TextBlock so that the text that comes after the TextBlock gets pushed down accordingly but I'm not sure how to achieve this. I haven't set any width or height for the TextBlock so that it sizes dynamically with the content inside of it. Maybe that has something to do with this?

Another problem is that if I have a TextBlock with multiple lines of code and they contain indentations, the indentations only start from the caret position, which is where the TextBlock starts and not to the very left of the editor which is ideally where I want it to start. I'm not sure how to achieve this behavior either.

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

IntraTextAdornmentManagerBase-based adornment managers like IntraTextNoteAdornmentManager are set up to watch for text ranges to be tagged with a specific tag type.  In this case, IntraTextNoteTag is the tag type being watched.  As soon as you tag a range of text with IntraTextNoteTag, the adornment manager will find the tag and call AddAdornment.

In the AdornmentsIntraTextNotes sample's MainControl.OnAddNoteButtonClick, you can see how a tag is created and added to the tagger.  That's all that needs to be done, since it triggers AddAdornment to be called.

As long as the IntraTextNoteSyntaxLanguage is set up with the two services listed in its constructor, everything should work.  You shouldn't need to create an adornment manager in the MainControl.

For sizing intra-text adornments, that sample's IntraTextNoteTag class has Size and Baseline properties.  Those would need to be set appropriately and can affect the height of the overall viewline.  SyntaxEditor will try to alignt the baseline of our own rendered text with the baseline you give for the adornment.

For the multiple lines of code with indentation question, perhaps an intra-text adornment is not the best option in that scenario.  For that, you might want to do an intra-line adornment.  There are a couple samples on that kind of thing and documentation.


Actipro Software Support

Posted 6 months ago by Kai Nguyen
Avatar

I have an IEditorView in my code that represents the active view of my syntax editor which for now can only be referenced in my main control. In the main control I register the manager and the tagger like this.

view.SyntaxEditor.Document.Language.RegisterService(new AdornmentManagerProvider<IntraTextAdornmentManager>(typeof(IntraTextAdornmentManager)));
view.SyntaxEditor.Document.Language.RegisterService(new CodeDocumentTaggerProvider<IntraTextTagger>(typeof(IntraTextTagger)));

Alternatively I have also written it like this and tested it. Not sure if it makes any difference.

view.SyntaxEditor.ActiveView.SyntaxEditor.Document.Language.RegisterService(new AdornmentManagerProvider<IntraTextAdornmentManager>(typeof(IntraTextAdornmentManager)));
view.SyntaxEditor.ActiveView.SyntaxEditor.Document.Language.RegisterService(new CodeDocumentTaggerProvider<IntraTextTagger>(typeof(IntraTextTagger)));

When doing this the adornments don't seem to render unless I create an instance of the manager in my main control. Is there something wrong with this approach?

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

You might need for those services to be registered on the ISyntaxLanguage prior to the language being assigned to the document.  Whereas right now you are registering them after the language is already applied to the document.

Use this general kind of logic:

  1. Create ISyntaxLanguage object.
  2. Register all services.
  3. Set ISyntaxLanguage instance to the SyntaxEditor's Document.Language property.

Please try that and see if it helps.


Actipro Software Support

The latest build of this product (v24.1.2) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.