So I finally found a way to do in-memory snippets.
The solution can be divided into two parts:
- The completion session with the known completion dropdown
- The snippet session, which allows switching between literals and so on
1 Provide custom completion
For the first part, I used this example of the AsyncCompletion.
2 Starting expansion session with in-memory snippet
For the snippet session I found a method on IVsExpansion
called InsertSpecificExpansion
(see documentation)
This allows starting an expansion session with an in-memory XMLDOMNode. To be able to use this with my custom in memory snippet structure I had to do the following:
- Create a serializable C#-Model for the Visual Studio Snippet Schema
- Parse my custom snippets to that VS-Model
- Use XML Serializer to create a IXMLDOMNode
3 Link the parts together
In order to link the two parts, I used the following approach: When a CompletionItem is chosen from the list, I cancel the regular completion and instead perform a ExpansionSession.
First I had to add an additional Property to the CompletionItem
so that the ExpansionSession later can access the XMLNode:
completionItem.Properties.AddProperty("SnippetXML", snippetXMLNode);
This can later be used by the ExpansionSession to provide the node
Parameter of InsertSpecificExpansion
In CommitManager.TryCommit
I first start the ExpansionSession and mark the CompletionSession as handled so no further actions are done:
// use IVsEditorAdaptersFactoryService to get access to IVsTextview
var vsTextView = VsEditorAdapter.GetViewAdapter(session.TextView);
// start a snippet session using in-memory XML rather than .xml files
ExpansionClient.StartExpansion(vsTextView, item);
// we handled the completion by starting an expansion session so no other handlers should participate
return CommitResult.Handled;
The ExpansionClient
is an implementation of IOleCommandTarget
and IVsExpansionClient
. The Expansion follows the approach described here but the difference is it calls InsertSpecificExpansion
instead of InsertNamedExpansion
.
I hope this may help anyone with the same problem. At some point, I will add a complete example on GitHub.