Procédure pas à pas : Implémentation d’extraits de CodeWalkthrough: Implementing Code Snippets

Vous pouvez créer des extraits de code et les inclure dans une extension de l’éditeur afin que les utilisateurs de l’extension de les ajouter à leur propre code.You can create code snippets and include them in an editor extension so that users of the extension can add them to their own code.

Un extrait de code est un fragment de code ou autre texte qui peut être incorporé dans un fichier.A code snippet is a fragment of code or other text that can be incorporated in a file. Pour afficher tous les extraits de code qui ont été inscrits pour les langages de programmation particuliers, sur le outils menu, cliquez sur Gestionnaire des extraits de Code.To view all snippets that have been registered for particular programming languages, on the Tools menu, click Code Snippet Manager. Pour insérer un extrait de code dans un fichier, avec le bouton sur lequel vous souhaitez l’extrait de code, cliquez sur insérer un extrait ou entourer, recherchez l’extrait de code, puis double-cliquez dessus.To insert a snippet in a file, right-click where you want the snippet, click Insert Snippet or Surround With, locate the snippet you want, and then double-click it. Appuyez sur TAB ou MAJ + TAB pour modifier les parties pertinentes de l’extrait de code et appuyez sur entrée ou ÉCHAP pour l’accepter.Press TAB or SHIFT+TAB to modify the relevant parts of the snippet and then press ENTER or ESC to accept it. Pour plus d’informations, consultez Extraits de code.For more information, see Code Snippets.

Un extrait de code est contenu dans un fichier XML qui porte l’extension de nom de fichier .snippet.A code snippet is contained in an XML file that has the .snippet file name extension. Un extrait de code peut contenir des champs qui sont mis en surbrillance après avoir inséré l’extrait de code afin que l’utilisateur peut rechercher et les modifier.A snippet can contain fields that are highlighted after the snippet is inserted so that the user can find and change them. Un fichier d’extrait de code fournit également des informations pour le Gestionnaire des extraits de Code afin qu’il peut afficher le nom de l’extrait de code dans la catégorie appropriée.A snippet file also provides information for the Code Snippet Manager so that it can display the snippet name in the correct category. Pour plus d’informations sur le schéma de l’extrait de code, consultez référence du schéma des extraits de Code.For information about the snippet schema, see Code Snippets Schema Reference.

Cette procédure pas à pas explique comment accomplir ces tâches :This walkthrough teaches how to accomplish these tasks:

  1. Créez et inscrivez les extraits de code pour une langue spécifique.Create and register code snippets for a specific language.

  2. Ajouter le insérer un extrait commande à un menu contextuel.Add the Insert Snippet command to a shortcut menu.

  3. Implémenter l’expansion de l’extrait de code.Implement snippet expansion.

    Cette procédure pas à pas est basée sur procédure pas à pas : affichage de saisie semi-automatique des instructions.This walkthrough is based on Walkthrough: Displaying Statement Completion.

PrérequisPrerequisites

À partir de Visual Studio 2015, vous n’installez pas le Kit de développement logiciel Visual Studio à partir du centre de téléchargement.Starting in Visual Studio 2015, you do not install the Visual Studio SDK from the download center. Il est inclus comme une fonctionnalité facultative dans le programme d’installation de Visual Studio.It is included as an optional feature in Visual Studio setup. Vous pouvez également installer le kit SDK VS ultérieurement.You can also install the VS SDK later on. Pour plus d’informations, consultez l’installation de Visual Studio SDK.For more information, see Installing the Visual Studio SDK.

Création et enregistrement d’extraits de CodeCreating and Registering Code Snippets

En règle générale, les extraits de code sont associés à un service de langage enregistré.Typically, code snippets are associated with a registered language service. Toutefois, vous n’avez pas à implémenter un LanguageService pour inscrire des extraits de code.However, you do not have to implement a LanguageService to register code snippets. Au lieu de cela, spécifiez simplement un GUID dans le fichier d’index extrait et ensuite utiliser le même GUID dans le ProvideLanguageCodeExpansionAttribute que vous ajoutez à votre projet.Instead, just specify a GUID in the snippet index file and then use the same GUID in the ProvideLanguageCodeExpansionAttribute that you add to your project.

Les étapes suivantes montrent comment créer des extraits de code et les associer avec un GUID spécifique.The following steps demonstrate how to create code snippets and associate them with a specific GUID.

  1. Créez la structure de répertoire suivante :Create the following directory structure:

    %INSTALLDIR%\TestSnippets\Snippets\1033\%InstallDir%\TestSnippets\Snippets\1033\

    % INSTALLDIR% est le dossier d’installation de Visual Studio.where %InstallDir% is the Visual Studio installation folder. (Bien que ce chemin d’accès est généralement utilisé pour installer des extraits de code, vous pouvez spécifier n’importe quel chemin d’accès.)(Although this path is typically used to install code snippets, you can specify any path.)

  2. Dans le dossier \1033, créez un fichier .xml et nommez-le TestSnippets.xml.In the \1033\ folder, create an .xml file and name it TestSnippets.xml. (Bien que ce nom est généralement utilisé pour un fichier d’index extrait de code, vous pouvez spécifier n’importe quel nom tant qu’il a une extension de nom de fichier .xml.) Ajoutez le texte suivant, puis supprimer l’espace réservé GUID et d’ajouter vos propres.(Although this name is typically used for a snippet index file, you can specify any name as long as it has an .xml file name extension.) Add the following text, and then delete the placeholder GUID and add your own.

    <?xml version="1.0" encoding="utf-8" ?>  
    <SnippetCollection>  
        <Language Lang="TestSnippets" Guid="{00000000-0000-0000-0000-000000000000}">  
            <SnippetDir>  
                <OnOff>On</OnOff>  
                <Installed>true</Installed>  
                <Locale>1033</Locale>  
                <DirPath>%InstallRoot%\TestSnippets\Snippets\%LCID%\</DirPath>  
                <LocalizedName>Snippets</LocalizedName>  
            </SnippetDir>  
        </Language>  
    </SnippetCollection>  
    
  3. Créez un fichier dans le dossier d’extrait de code, nommez-le test.snippet, puis ajoutez le texte suivant :Create a file in the snippet folder, name it test.snippet, and then add the following text:

    <?xml version="1.0" encoding="utf-8" ?>  
    <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">  
        <CodeSnippet Format="1.0.0">  
            <Header>  
                <Title>Test replacement fields</Title>  
                <Shortcut>test</Shortcut>  
                <Description>Code snippet for testing replacement fields</Description>  
                <Author>MSIT</Author>  
                <SnippetTypes>  
                    <SnippetType>Expansion</SnippetType>  
                </SnippetTypes>  
            </Header>  
            <Snippet>  
                <Declarations>  
                    <Literal>  
                      <ID>param1</ID>  
                        <ToolTip>First field</ToolTip>  
                        <Default>first</Default>  
                    </Literal>  
                    <Literal>  
                        <ID>param2</ID>  
                        <ToolTip>Second field</ToolTip>  
                        <Default>second</Default>  
                    </Literal>  
                </Declarations>  
                <References>  
                   <Reference>  
                       <Assembly>System.Windows.Forms.dll</Assembly>  
                   </Reference>  
                </References>  
                <Code Language="TestSnippets">  
                    <![CDATA[MessageBox.Show("$param1$");  
         MessageBox.Show("$param2$");]]>  
                </Code>    
            </Snippet>  
        </CodeSnippet>  
    </CodeSnippets>  
    

    Les étapes suivantes montrent comment inscrire les extraits de code.The following steps show how to register the code snippets.

Pour inscrire des extraits de code pour un GUID spécifiqueTo register code snippets for a specific GUID

  1. Ouvrez le CompletionTest projet.Open the CompletionTest project. Pour plus d’informations sur la création de ce projet, consultez procédure pas à pas : affichage de saisie semi-automatique des instructions.For information about how to create this project, see Walkthrough: Displaying Statement Completion.

  2. Dans le projet, ajoutez des références aux assemblys suivants :In the project, add references to the following assemblies:

    • Microsoft.VisualStudio.TextManager.InteropMicrosoft.VisualStudio.TextManager.Interop

    • Microsoft.VisualStudio.TextManager.Interop.8.0Microsoft.VisualStudio.TextManager.Interop.8.0

    • Microsoft.MSXMLmicrosoft.msxml

  3. Dans le projet, ouvrez le fichier source.extension.vsixmanifest.In the project, open the source.extension.vsixmanifest file.

  4. Assurez-vous que le actifs onglet contient un VsPackage type et que du contenu projet est définie sur le nom du projet.Make sure that the Assets tab contains a VsPackage content type and that Project is set to the name of the project.

  5. Sélectionnez le projet CompletionTest et dans la fenêtre Propriétés, définissez générer un fichier Pkgdef à true.Select the CompletionTest project and in the Properties window set Generate Pkgdef File to true. Enregistrez le projet.Save the project.

  6. Ajouter un mappage statique SnippetUtilities classe au projet.Add a static SnippetUtilities class to the project.

    static class SnippetUtilities
    
    Module SnippetUtilities
    
  7. Dans la classe SnippetUtilities, définir un GUID et lui donner la valeur que vous avez utilisé dans le fichier SnippetsIndex.xml.In the SnippetUtilities class, define a GUID and give it the value that you used in the SnippetsIndex.xml file.

    internal const string LanguageServiceGuidStr = "00000000-0000-0000-0000-00000000";
    
    Friend Const LanguageServiceGuidStr As String = "00000000-0000-0000-0000-00000000"
    
  8. Ajouter le ProvideLanguageCodeExpansionAttribute à la TestCompletionHandler classe.Add the ProvideLanguageCodeExpansionAttribute to the TestCompletionHandler class. Cet attribut peut être ajouté à toute classe (non statique) publique ou interne dans le projet.This attribute can be added to any public or internal (non-static) class in the project. (Vous devrez peut-être ajouter un using instruction pour l’espace de noms Microsoft.VisualStudio.Shell.)(You may have to add a using statement for the Microsoft.VisualStudio.Shell namespace.)

    [ProvideLanguageCodeExpansion(
    SnippetUtilities.LanguageServiceGuidStr,
    "TestSnippets", //the language name
    0,              //the resource id of the language
    "TestSnippets", //the language ID used in the .snippet files
    @"%InstallRoot%\TestSnippets\Snippets\%LCID%\TestSnippets.xml",
        //the path of the index file
    SearchPaths = @"%InstallRoot%\TestSnippets\Snippets\%LCID%\",
    ForceCreateDirs = @"%InstallRoot%\TestSnippets\Snippets\%LCID%\")]
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
    <ProvideLanguageCodeExpansion(
    SnippetUtilities.LanguageServiceGuidStr,
    "TestSnippets",
    0,
    "TestSnippets",
    "%InstallRoot%\TestSnippets\Snippets\%LCID%\SnippetsIndex.xml",
    SearchPaths:="%InstallRoot%\TestSnippets\Snippets\%LCID%\",
    ForceCreateDirs:="%InstallRoot%\TestSnippets\Snippets\%LCID%\")>
    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
  9. Générez et exécutez le projet.Build and run the project. Dans l’instance expérimentale de Visual Studio démarre lorsque le projet est exécuté, l’extrait de code que vous venez d’enregistrer doit être affiché dans le Gestionnaire des extraits de Code sous le TestSnippets language.In the experimental instance of Visual Studio that starts when the project is run, the snippet you just registered should be displayed in the Code Snippets Manager under the TestSnippets language.

Ajout de la commande d’insertion extrait de code dans le Menu contextuelAdding the Insert Snippet Command to the Shortcut Menu

Le insérer un extrait commande n’est pas incluse dans le menu contextuel pour un fichier texte.The Insert Snippet command is not included on the shortcut menu for a text file. Par conséquent, vous devez activer la commande.Therefore, you must enable the command.

Pour ajouter la commande Insérer un extrait dans le menu contextuelTo add the Insert Snippet command to the shortcut menu

  1. Ouvrez le TestCompletionCommandHandler fichier de classe.Open the TestCompletionCommandHandler class file.

    Étant donné que cette classe implémente IOleCommandTarget, vous pouvez activer la insérer un extrait dans le QueryStatus (méthode).Because this class implements IOleCommandTarget, you can activate the Insert Snippet command in the QueryStatus method. Avant d’activer la commande, vérifiez que cette méthode n’est pas en cours appelée à l’intérieur d’une fonction d’automation, car lorsque le insérer un extrait commande est activée, il affiche l’interface utilisateur du sélecteur extrait (IU).Before you enable the command, check that this method is not being called inside an automation function because when the Insert Snippet command is clicked, it will display the snippet picker user interface (UI).

    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        if (!VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
        {
            if (pguidCmdGroup == VSConstants.VSStd2K && cCmds > 0)
            {
                // make the Insert Snippet command appear on the context menu 
                if ((uint)prgCmds[0].cmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET)
                {
                    prgCmds[0].cmdf = (int)Constants.MSOCMDF_ENABLED | (int)Constants.MSOCMDF_SUPPORTED;
                    return VSConstants.S_OK;
                }
            }
        }
    
        return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
    Public Function QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As UInteger, ByVal prgCmds As OLECMD(), ByVal pCmdText As IntPtr) As Integer Implements IOleCommandTarget.QueryStatus
        If Not VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider) Then
            If pguidCmdGroup = VSConstants.VSStd2K AndAlso cCmds > 0 Then
                ' make the Insert Snippet command appear on the context menu 
                If CUInt(prgCmds(0).cmdID) = CUInt(VSConstants.VSStd2KCmdID.INSERTSNIPPET) Then
                    prgCmds(0).cmdf = CInt(Constants.MSOCMDF_ENABLED) Or CInt(Constants.MSOCMDF_SUPPORTED)
                    Return VSConstants.S_OK
                End If
            End If
        End If
    
        Return m_nextCommandHandler.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText)
    End Function
    
  2. Générez et exécutez le projet.Build and run the project. Dans l’instance expérimentale, ouvrez un fichier qui porte l’extension de nom de fichier .zzz et ensuite avec le bouton droit n’importe où dans celui-ci.In the experimental instance, open a file that has the .zzz file name extension and then right-click anywhere in it. Le insérer un extrait commande doit apparaître dans le menu contextuel.The Insert Snippet command should appear on the shortcut menu.

Implémentation d’Expansion de l’extrait de code dans le sélecteur d’extrait de l’interface utilisateurImplementing Snippet Expansion in the Snippet Picker UI

Cette section montre comment implémenter l’expansion d’extrait de code afin que le sélecteur d’extrait de l’interface utilisateur est affiché lorsque insérer un extrait est sélectionné dans le menu contextuel.This section shows how to implement code snippet expansion so that the snippet picker UI is displayed when Insert Snippet is clicked on the shortcut menu. Un extrait de code est également développé lorsqu’un utilisateur tape le raccourci d’extrait de code, puis appuie sur TAB.A code snippet is also expanded when a user types the code-snippet shortcut and then presses TAB.

Pour afficher le sélecteur d’extrait de l’interface utilisateur et activer la navigation et l’acceptation de l’extrait de code après d’insertion, utilisez la Exec (méthode).To display the snippet picker UI and to enable navigation and post-insertion snippet acceptance, use the Exec method. L’insertion est gérée par le OnItemChosen (méthode).The insertion itself is handled by the OnItemChosen method.

L’implémentation d’expansion d’extrait de code utilise hérité Microsoft.VisualStudio.TextManager.Interop interfaces.The implementation of code snippet expansion uses legacy Microsoft.VisualStudio.TextManager.Interop interfaces. Lorsque vous traduisez des classes d’éditeur actuel pour le code hérité, n’oubliez pas que les interfaces hérités utilisent une combinaison de numéros de ligne et de colonne pour spécifier les emplacements dans une mémoire tampon de texte, mais les classes actuels utilisent un seul index.When you translate from the current editor classes to the legacy code, remember that the legacy interfaces use a combination of line numbers and column numbers to specify locations in a text buffer, but the current classes use one index. Par conséquent, si une mémoire tampon a trois lignes, chacune d’elles possède dix caractères (plus un saut de ligne, qui comptent comme caractère de 1), le quatrième caractère sur la troisième ligne est à la position 27 dans l’implémentation actuelle, mais il est à la ligne 2, placez 3 dans l’ancienne implémentation.Therefore, if a buffer has three lines each of which has ten characters (plus a newline, which counts as 1 character), the fourth character on the third line is at position 27 in the current implementation, but it is at line 2, position 3 in the old implementation.

Pour implémenter l’expansion de l’extrait de codeTo implement snippet expansion

  1. Dans le fichier qui contient le TestCompletionCommandHandler de classe, ajoutez le code suivant using instructions.To the file that contains the TestCompletionCommandHandler class, add the following using statements.

    using Microsoft.VisualStudio.Text.Operations;
    using MSXML;
    using System.ComponentModel.Composition;
    
    Imports Microsoft.VisualStudio.Text.Operations
    Imports MSXML
    
  2. Rendre le TestCompletionCommandHandler classe implémentent la IVsExpansionClient interface.Make the TestCompletionCommandHandler class implement the IVsExpansionClient interface.

    internal class TestCompletionCommandHandler : IOleCommandTarget, IVsExpansionClient
    
    <ProvideLanguageCodeExpansion(
    SnippetUtilities.LanguageServiceGuidStr,
    "TestSnippets",
    0,
    "TestSnippets",
    "%InstallRoot%\TestSnippets\Snippets\%LCID%\SnippetsIndex.xml",
    SearchPaths:="%InstallRoot%\TestSnippets\Snippets\%LCID%\",
    ForceCreateDirs:="%InstallRoot%\TestSnippets\Snippets\%LCID%\")>
    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
        Implements IVsExpansionClient
    
  3. Dans le TestCompletionCommandHandlerProvider classe, importez le ITextStructureNavigatorSelectorService.In the TestCompletionCommandHandlerProvider class, import the ITextStructureNavigatorSelectorService.

    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    <Import()>
    Friend Property NavigatorService As ITextStructureNavigatorSelectorService
    
  4. Ajouter des champs privés pour les interfaces d’extension de code et le IVsTextView.Add some private fields for the code expansion interfaces and the IVsTextView.

    IVsTextView m_vsTextView;
    IVsExpansionManager m_exManager;
    IVsExpansionSession m_exSession;
    
    Dim m_vsTextView As IVsTextView
    Dim m_exManager As IVsExpansionManager
    Dim m_exSession As IVsExpansionSession
    
  5. Dans le constructeur de la TestCompletionCommandHandler de classe, définissez les champs suivants.In the constructor of the TestCompletionCommandHandler class, set the following fields.

    internal TestCompletionCommandHandler(IVsTextView textViewAdapter, ITextView textView, TestCompletionHandlerProvider provider)
    {
        this.m_textView = textView;
        m_vsTextView = textViewAdapter;
        m_provider = provider;
        //get the text manager from the service provider
        IVsTextManager2 textManager = (IVsTextManager2)m_provider.ServiceProvider.GetService(typeof(SVsTextManager));
        textManager.GetExpansionManager(out m_exManager);
        m_exSession = null;
    
        //add the command to the command chain
        textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
    }
    
    Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal provider As TestCompletionHandlerProvider)
        Me.m_textView = textView
        Me.m_provider = provider
        Me.m_vsTextView = textViewAdapter
    
        Dim textManager As IVsTextManager2 = DirectCast(m_provider.ServiceProvider.GetService(GetType(SVsTextManager)), IVsTextManager2)
        textManager.GetExpansionManager(m_exManager)
        m_exSession = Nothing
    
        'add the command to the command chain
        textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
    End Sub
    
  6. Pour afficher le sélecteur d’extrait de code lorsque l’utilisateur clique sur le insérer un extrait de commande, ajoutez le code suivant à la Exec (méthode).To display the snippet picker when the user clicks the Insert Snippet command, add the following code to the Exec method. (Pour rendre cette explication plus lisible, le code de Exec() qui est utilisé pour la saisie semi-automatique des instructions n’est pas indiqué ; au lieu de cela, les blocs de code sont ajoutés à la méthode existante). Ajoutez le bloc de code suivant après le code qui vérifie si un caractère.(To make this explanation more readable, the Exec() code that is used for statement completion is not shown; instead, blocks of code are added to the existing method.) Add the following block of code after the code that checks for a character.

    //code previously written for Exec
    if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
    {
        typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
    }
    //the snippet picker code starts here
    if (nCmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET)
    {
        IVsTextManager2 textManager = (IVsTextManager2)m_provider.ServiceProvider.GetService(typeof(SVsTextManager));
    
        textManager.GetExpansionManager(out m_exManager);
    
        m_exManager.InvokeInsertionUI(
            m_vsTextView,
            this,      //the expansion client
            new Guid(SnippetUtilities.LanguageServiceGuidStr),
            null,       //use all snippet types
            0,          //number of types (0 for all)
            0,          //ignored if iCountTypes == 0
            null,       //use all snippet kinds
            0,          //use all snippet kinds
            0,          //ignored if iCountTypes == 0
            "TestSnippets", //the text to show in the prompt
            string.Empty);  //only the ENTER key causes insert 
    
        return VSConstants.S_OK;
    }
    
    'code previously written for Exec
    If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
        typedChar = ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn)))
    End If
    'the snippet picker code starts here
    If nCmdID = CUInt(VSConstants.VSStd2KCmdID.INSERTSNIPPET) Then
        Dim textManager As IVsTextManager2 = DirectCast(m_provider.ServiceProvider.GetService(GetType(SVsTextManager)), IVsTextManager2)
    
        textManager.GetExpansionManager(m_exManager)
        m_exManager.InvokeInsertionUI(
            m_vsTextView,
            Me,
            New Guid(SnippetUtilities.LanguageServiceGuidStr),
            Nothing,
            0,
            0,
            Nothing,
            0,
            0,
            "TestSnippets",
            String.Empty)
        Return VSConstants.S_OK
    End If
    
  7. Si un extrait de code comporte des champs qui peuvent être parcourus, la session d’expansion est maintenue ouverte jusqu'à ce que l’expansion est acceptée explicitement ; Si l’extrait de code ne comporte aucun champ, la session est fermée et qu’elle est retournée en tant que null par le InvokeInsertionUI (méthode).If a snippet has fields that can be navigated, the expansion session is kept open until the expansion is explicitly accepted; if the snippet has no fields, the session is closed and is returned as null by the InvokeInsertionUI method. Dans le Exec (méthode), après le sélecteur d’extrait de code de l’interface utilisateur que vous avez ajouté à l’étape précédente, ajoutez le code suivant pour gérer la navigation de l’extrait de code (lorsque l’utilisateur appuie sur TAB ou MAJ + TAB après l’insertion d’extrait de code).In the Exec method, after the snippet picker UI code that you added in the previous step, add the following code to handle snippet navigation (when the user presses TAB or SHIFT+TAB after snippet insertion).

    //the expansion insertion is handled in OnItemChosen
    //if the expansion session is still active, handle tab/backtab/return/cancel
    if (m_exSession != null)
    {
        if (nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKTAB)
        {
            m_exSession.GoToPreviousExpansionField();
            return VSConstants.S_OK;
        }
        else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
        {
    
            m_exSession.GoToNextExpansionField(0); //false to support cycling through all the fields
            return VSConstants.S_OK;
        }
        else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.CANCEL)
        {
            if (m_exSession.EndCurrentExpansion(0) == VSConstants.S_OK)
            {
                m_exSession = null;
                return VSConstants.S_OK;
            }
        }
    }
    
    'the expansion insertion is handled in OnItemChosen
    'if the expansion session is still active, handle tab/backtab/return/cancel
    If m_exSession IsNot Nothing Then
        If nCmdID = CUInt(VSConstants.VSStd2KCmdID.BACKTAB) Then
            m_exSession.GoToPreviousExpansionField()
            Return VSConstants.S_OK
        ElseIf nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) Then
            m_exSession.GoToNextExpansionField(0)
            'false to support cycling through all the fields
            Return VSConstants.S_OK
        ElseIf nCmdID = CUInt(VSConstants.VSStd2KCmdID.[RETURN]) OrElse nCmdID = CUInt(VSConstants.VSStd2KCmdID.CANCEL) Then
            If m_exSession.EndCurrentExpansion(0) = VSConstants.S_OK Then
                m_exSession = Nothing
                Return VSConstants.S_OK
            End If
        End If
    End If
    
  8. Pour insérer l’extrait de code lorsque l’utilisateur tape le raccourci correspondant, puis appuie sur TAB, ajoutez le code à le Exec (méthode).To insert the code snippet when the user types the corresponding shortcut and then presses TAB, add code to the Exec method. La méthode privée qui insère l’extrait de code apparaît dans une étape ultérieure.The private method that inserts the snippet will be shown in a later step. Ajoutez le code suivant après le code de navigation que vous avez ajouté à l’étape précédente.Add the following code after the navigation code that you added in the previous step.

    //neither an expansion session nor a completion session is open, but we got a tab, so check whether the last word typed is a snippet shortcut 
    if (m_session == null && m_exSession == null && nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
    {
        //get the word that was just added 
        CaretPosition pos = m_textView.Caret.Position;
        TextExtent word = m_provider.NavigatorService.GetTextStructureNavigator(m_textView.TextBuffer).GetExtentOfWord(pos.BufferPosition - 1); //use the position 1 space back
        string textString = word.Span.GetText(); //the word that was just added
        //if it is a code snippet, insert it, otherwise carry on
        if (InsertAnyExpansion(textString, null, null))
            return VSConstants.S_OK;
    }
    
    'neither an expansion session nor a completion session is open, but we got a tab, so check whether the last word typed is a snippet shortcut 
    If m_session Is Nothing AndAlso m_exSession Is Nothing AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) Then
        'get the word that was just added 
        Dim pos As CaretPosition = m_textView.Caret.Position
        Dim word As TextExtent = m_provider.NavigatorService.GetTextStructureNavigator(m_textView.TextBuffer).GetExtentOfWord(pos.BufferPosition - 1)
        Dim textString As String = word.Span.GetText()
        'if it is a code snippet, insert it, otherwise carry on
        If InsertAnyExpansion(textString, Nothing, Nothing) Then
            Return VSConstants.S_OK
        End If
    End If
    
  9. Implémenter les méthodes de la IVsExpansionClient interface.Implement the methods of the IVsExpansionClient interface. Dans cette implémentation, les seules méthodes dignes d’intérêt sont EndExpansion et OnItemChosen.In this implementation, the only methods of interest are EndExpansion and OnItemChosen. Les autres méthodes doivent simplement retourner S_OK.The other methods should just return S_OK.

    public int EndExpansion()
    {
        m_exSession = null;
        return VSConstants.S_OK;
    }
    
    public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts)
    {
        return VSConstants.S_OK;
    }
    
    public int GetExpansionFunction(IXMLDOMNode xmlFunctionNode, string bstrFieldName, out IVsExpansionFunction pFunc)
    {
        pFunc = null;
        return VSConstants.S_OK;
    }
    
    public int IsValidKind(IVsTextLines pBuffer, TextSpan[] ts, string bstrKind, out int pfIsValidKind)
    {
        pfIsValidKind = 1;
        return VSConstants.S_OK;
    }
    
    public int IsValidType(IVsTextLines pBuffer, TextSpan[] ts, string[] rgTypes, int iCountTypes, out int pfIsValidType)
    {
        pfIsValidType = 1;
        return VSConstants.S_OK;
    }
    
    public int OnAfterInsertion(IVsExpansionSession pSession)
    {
        return VSConstants.S_OK;
    }
    
    public int OnBeforeInsertion(IVsExpansionSession pSession)
    {
        return VSConstants.S_OK;
    }
    
    public int PositionCaretForEditing(IVsTextLines pBuffer, TextSpan[] ts)
    {
        return VSConstants.S_OK;
    }
    
    Public Function EndExpansion() As Integer Implements IVsExpansionClient.EndExpansion
        m_exSession = Nothing
        Return VSConstants.S_OK
    End Function
    
    Public Function FormatSpan(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan()) As Integer Implements IVsExpansionClient.FormatSpan
        Return VSConstants.S_OK
    End Function
    
    Public Function GetExpansionFunction(ByVal xmlFunctionNode As IXMLDOMNode, ByVal bstrFieldName As String, ByRef pFunc As IVsExpansionFunction) As Integer Implements IVsExpansionClient.GetExpansionFunction
        pFunc = Nothing
        Return VSConstants.S_OK
    End Function
    
    Public Function IsValidKind(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan(), ByVal bstrKind As String, ByRef pfIsValidKind As Integer) As Integer Implements IVsExpansionClient.IsValidKind
        pfIsValidKind = 1
        Return VSConstants.S_OK
    End Function
    
    Public Function IsValidType(ByVal pBuffer As IVsTextLines, ByVal ts() As TextSpan, ByVal rgTypes() As String, ByVal iCountTypes As Integer, ByRef pfIsValidType As Integer) As Integer Implements IVsExpansionClient.IsValidType
        pfIsValidType = 1
        Return VSConstants.S_OK
    End Function
    
    Public Function OnAfterInsertion(ByVal pSession As IVsExpansionSession) As Integer Implements IVsExpansionClient.OnAfterInsertion
        Return VSConstants.S_OK
    End Function
    
    Public Function OnBeforeInsertion(ByVal pSession As IVsExpansionSession) As Integer Implements IVsExpansionClient.OnBeforeInsertion
        Return VSConstants.S_OK
    End Function
    
    Public Function PositionCaretForEditing(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan()) As Integer Implements IVsExpansionClient.PositionCaretForEditing
        Return VSConstants.S_OK
    End Function
    
  10. Implémentez la méthode OnItemChosen.Implement the OnItemChosen method. La méthode d’assistance qui insère en fait les expansions est abordée dans une étape ultérieure.The helper method that actually inserts the expansions will be covered in a later step. Le TextSpan fournit des informations de ligne et de colonne, que vous pouvez obtenir à partir de la IVsTextView.The TextSpan provides line and column information, which you can get from the IVsTextView.

    public int OnItemChosen(string pszTitle, string pszPath)
    {
        InsertAnyExpansion(null, pszTitle, pszPath);
        return VSConstants.S_OK;
    }
    
    Public Function OnItemChosen(ByVal pszTitle As String, ByVal pszPath As String) As Integer Implements IVsExpansionClient.OnItemChosen
        InsertAnyExpansion(Nothing, pszTitle, pszPath)
        Return VSConstants.S_OK
    End Function
    
  11. La méthode privée suivante insère un extrait de code, basé sur le raccourci ou sur le titre et le chemin d’accès.The following private method inserts a code snippet, based either on the shortcut or on the title and path. Il appelle ensuite la InsertNamedExpansion méthode avec l’extrait de code.It then calls the InsertNamedExpansion method with the snippet.

    private bool InsertAnyExpansion(string shortcut, string title, string path)
    {
        //first get the location of the caret, and set up a TextSpan
        int endColumn, startLine;
        //get the column number from  the IVsTextView, not the ITextView
        m_vsTextView.GetCaretPos(out startLine, out endColumn);
    
        TextSpan addSpan = new TextSpan();
        addSpan.iStartIndex = endColumn;
        addSpan.iEndIndex = endColumn;
        addSpan.iStartLine = startLine;
        addSpan.iEndLine = startLine;
    
        if (shortcut != null) //get the expansion from the shortcut
        {
            //reset the TextSpan to the width of the shortcut, 
            //because we're going to replace the shortcut with the expansion
            addSpan.iStartIndex = addSpan.iEndIndex - shortcut.Length;
    
            m_exManager.GetExpansionByShortcut(
                this,
                new Guid(SnippetUtilities.LanguageServiceGuidStr),
                shortcut,
                m_vsTextView,
                new TextSpan[] { addSpan },
                0,
                out path,
                out title);
    
        }
        if (title != null && path != null)
        {
            IVsTextLines textLines;
            m_vsTextView.GetBuffer(out textLines);
            IVsExpansion bufferExpansion = (IVsExpansion)textLines;
    
            if (bufferExpansion != null)
            {
                int hr = bufferExpansion.InsertNamedExpansion(
                    title,
                    path,
                    addSpan,
                    this,
                    new Guid(SnippetUtilities.LanguageServiceGuidStr),
                    0,
                   out m_exSession);
                if (VSConstants.S_OK == hr)
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    Private Function InsertAnyExpansion(ByVal shortcut As String, ByVal title As String, ByVal path As String) As Boolean
        Dim endColumn As Integer, startLine As Integer
        'get the column number from  the IVsTextView, not the ITextView
        m_vsTextView.GetCaretPos(startLine, endColumn)
    
        Dim addSpan As New TextSpan()
        addSpan.iStartIndex = endColumn
        addSpan.iEndIndex = endColumn
        addSpan.iStartLine = startLine
        addSpan.iEndLine = startLine
    
        'get the expansion from the shortcut
        If shortcut IsNot Nothing Then
            'reset the TextSpan to the width of the shortcut, because we're going to replace the shortcut with the expansion
            addSpan.iStartIndex = addSpan.iEndIndex - shortcut.Length
    
            m_exManager.GetExpansionByShortcut(
                Me,
                New Guid(SnippetUtilities.LanguageServiceGuidStr),
                shortcut,
                m_vsTextView,
                New TextSpan() {addSpan},
                0,
                path,
                title)
        End If
        If title IsNot Nothing AndAlso path IsNot Nothing Then
            Dim textLines As IVsTextLines = Nothing
            m_vsTextView.GetBuffer(textLines)
            Dim bufferExpansion As IVsExpansion = DirectCast(textLines, IVsExpansion)
    
            If bufferExpansion IsNot Nothing Then
                Dim hr As Integer = bufferExpansion.InsertNamedExpansion(
                    title,
                    path,
                    addSpan,
                    Me,
                    New Guid(SnippetUtilities.LanguageServiceGuidStr),
                    0,
                    m_exSession)
                If VSConstants.S_OK = hr Then
                    Return True
                End If
            End If
        End If
        Return False
    End Function
    

Génération et test d’extension extrait de CodeBuilding and Testing Code Snippet Expansion

Vous pouvez tester si l’expansion de l’extrait de code fonctionne dans votre projet.You can test whether snippet expansion works in your project.

  1. Générez la solution.Build the solution. Lorsque vous exécutez ce projet dans le débogueur, une deuxième instance de Visual Studio est instanciée.When you run this project in the debugger, a second instance of Visual Studio is instantiated.

  2. Ouvrir un fichier texte et tapez du texte.Open a text file and type some text.

  3. Cliquez quelque part dans le texte, puis cliquez sur insérer un extrait.Right-click somewhere in the text and then click Insert Snippet.

  4. Le sélecteur d’extrait de l’interface utilisateur doit apparaître avec une fenêtre contextuelle qui indique que tester des champs de remplacement.The snippet picker UI should appear with a pop-up that says Test replacement fields. Double-cliquez sur le menu contextuel.Double-click the pop-up.

    L’extrait de code suivant doit être inséré.The following snippet should be inserted.

    MessageBox.Show("first");  
    MessageBox.Show("second");  
    

    N’appuyez pas sur entrée ou ÉCHAP.Do not press ENTER or ESC.

  5. Appuyez sur TAB et MAJ + TAB pour basculer entre la « première » et « seconde ».Press TAB and SHIFT+TAB to toggle between "first" and "second".

  6. Accepter l’insertion en appuyant sur entrée ou ÉCHAP.Accept the insertion by pressing either ENTER or ESC.

  7. Dans une autre partie du texte, tapez « test » et appuyez sur TAB.In a different part of the text, type "test" and then press TAB. Étant donné que « test » est le raccourci d’extrait de code, l’extrait de code doit être inséré à nouveau.Because "test" is the code-snippet shortcut, the snippet should be inserted again.

Étapes suivantesNext Steps