Bagikan melalui


Panduan: Menerapkan cuplikan kode

Anda dapat membuat cuplikan kode dan menyertakannya dalam ekstensi editor sehingga pengguna ekstensi dapat menambahkannya ke kode mereka sendiri.

Cuplikan kode adalah fragmen kode atau teks lain yang dapat dimasukkan dalam file. Untuk melihat semua cuplikan yang telah didaftarkan untuk bahasa pemrograman tertentu, pada menu Alat , klik Manajer Cuplikan Kode. Untuk menyisipkan cuplikan dalam file, klik kanan tempat Anda menginginkan cuplikan, klik Sisipkan Cuplikan, atau Kelilingi Dengan, temukan cuplikan yang Anda inginkan, lalu klik dua kali. Tekan Tab atau Shift+Tab untuk mengubah bagian cuplikan yang relevan lalu tekan Enter atau Esc untuk menerimanya. Untuk informasi selengkapnya, lihat Cuplikan kode.

Cuplikan kode terkandung dalam file XML yang memiliki ekstensi nama file .snippet*. Cuplikan dapat berisi bidang yang disorot setelah cuplikan disisipkan sehingga pengguna dapat menemukan dan mengubahnya. File cuplikan juga menyediakan informasi untuk Code Snippet Manager sehingga dapat menampilkan nama cuplikan dalam kategori yang benar. Untuk informasi tentang skema cuplikan, lihat Referensi skema cuplikan kode.

Panduan ini mengajarkan cara menyelesaikan tugas-tugas ini:

  1. Buat dan daftarkan cuplikan kode untuk bahasa tertentu.

  2. Tambahkan perintah Sisipkan Cuplikan ke menu pintasan.

  3. Menerapkan ekspansi cuplikan.

    Panduan ini didasarkan pada Panduan: Penyelesaian pernyataan tampilan.

Membuat dan mendaftarkan cuplikan kode

Biasanya, cuplikan kode dikaitkan dengan layanan bahasa terdaftar. Namun, Anda tidak perlu menerapkan LanguageService untuk mendaftarkan cuplikan kode. Sebagai gantinya, cukup tentukan GUID dalam file indeks cuplikan lalu gunakan GUID yang sama dalam ProvideLanguageCodeExpansionAttribute yang Anda tambahkan ke proyek Anda.

Langkah-langkah berikut menunjukkan cara membuat cuplikan kode dan mengaitkannya dengan GUID tertentu.

  1. Buat struktur direktori berikut:

    %InstallDir%\TestSnippets\Snippets\1033\

    di mana %InstallDir% adalah folder penginstalan Visual Studio. (Meskipun jalur ini biasanya digunakan untuk menginstal cuplikan kode, Anda dapat menentukan jalur apa pun.)

  2. Di folder \1033\, buat file .xml dan beri nama TestSnippets.xml. (Meskipun nama ini biasanya digunakan untuk file indeks cuplikan, Anda dapat menentukan nama apa pun selama memiliki ekstensi nama file .xml .) Tambahkan teks berikut, lalu hapus GUID tempat penampung dan tambahkan GUID Anda sendiri.

    <?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. Buat file di folder cuplikan , beri nama uji.snippet, lalu tambahkan teks berikut:

    <?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>
    

    Langkah-langkah berikut menunjukkan cara mendaftarkan cuplikan kode.

Untuk mendaftarkan cuplikan kode untuk GUID tertentu

  1. Buka proyek CompletionTest. Untuk informasi tentang cara membuat proyek ini, lihat Panduan: Penyelesaian pernyataan tampilan.

  2. Dalam proyek, tambahkan referensi ke rakitan berikut:

    • Microsoft.VisualStudio.TextManager.Interop

    • Microsoft.VisualStudio.TextManager.Interop.8.0

    • microsoft.msxml

  3. Dalam proyek, buka file source.extension.vsixmanifest .

  4. Pastikan tab Aset berisi jenis konten VsPackage dan Project diatur ke nama proyek.

  5. Pilih proyek CompletionTest dan di jendela Properti atur Hasilkan File Pkgdef ke true. Simpan proyeknya.

  6. Tambahkan kelas statis SnippetUtilities ke proyek.

    static class SnippetUtilities
    
  7. Di kelas SnippetUtilities, tentukan GUID dan berikan nilai yang Anda gunakan dalam file SnippetsIndex.xml .

    internal const string LanguageServiceGuidStr = "00000000-0000-0000-0000-00000000";
    
  8. Tambahkan ke ProvideLanguageCodeExpansionAttributeTestCompletionHandler kelas . Atribut ini dapat ditambahkan ke kelas publik atau internal (non-statis) dalam proyek. (Anda mungkin harus menambahkan using direktif untuk namespace Microsoft.VisualStudio.Shell.)

    [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
    
  9. Buat dan jalankan proyek. Dalam instans eksperimental Visual Studio yang dimulai ketika proyek dijalankan, cuplikan yang baru saja Anda daftarkan harus ditampilkan di Code Snippets Manager di bawah bahasa TestSnippets .

Tambahkan perintah Sisipkan Cuplikan ke menu pintasan

Perintah Sisipkan Cuplikan tidak disertakan pada menu pintasan untuk file teks. Oleh karena itu, Anda harus mengaktifkan perintah .

Untuk menambahkan perintah Sisipkan Cuplikan ke menu pintasan

  1. TestCompletionCommandHandler Buka file kelas.

    Karena kelas ini mengimplementasikan IOleCommandTarget, Anda dapat mengaktifkan perintah Sisipkan CuplikanQueryStatus dalam metode . Sebelum Anda mengaktifkan perintah, periksa apakah metode ini tidak dipanggil di dalam fungsi otomatisasi karena ketika perintah Sisipkan Cuplikan diklik, metode ini menampilkan antarmuka pengguna pemilih cuplikan (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);
    }
    
  2. Buat dan jalankan proyek. Dalam instans eksperimental, buka file yang memiliki ekstensi nama file .zzz lalu klik kanan di mana saja di dalamnya. Perintah Sisipkan Cuplikan akan muncul di menu pintasan.

Menerapkan ekspansi cuplikan di UI Pemilih Cuplikan

Bagian ini menunjukkan cara menerapkan ekspansi cuplikan kode sehingga UI pemilih cuplikan ditampilkan saat Sisipkan Cuplikan diklik pada menu pintasan. Cuplikan kode juga diperluas saat pengguna mengetikkan pintasan cuplikan kode lalu menekan Tab.

Untuk menampilkan UI pemilih cuplikan dan untuk mengaktifkan navigasi dan penerimaan cuplikan pasca-penyisipan, gunakan Exec metode . Penyisipan itu sendiri ditangani oleh OnItemChosen metode .

Implementasi ekspansi cuplikan kode menggunakan antarmuka warisan Microsoft.VisualStudio.TextManager.Interop . Saat Anda menerjemahkan dari kelas editor saat ini ke kode warisan, ingatlah bahwa antarmuka warisan menggunakan kombinasi nomor baris dan nomor kolom untuk menentukan lokasi dalam buffer teks, tetapi kelas saat ini menggunakan satu indeks. Oleh karena itu, jika buffer memiliki tiga baris yang masing-masing memiliki 10 karakter (ditambah baris baru, yang dihitung sebagai satu karakter), karakter keempat pada baris ketiga berada di posisi 27 dalam implementasi saat ini, tetapi berada di baris 2, posisi 3 dalam implementasi lama.

Untuk menerapkan ekspansi cuplikan

  1. Ke file yang berisi TestCompletionCommandHandler kelas , tambahkan arahan berikut using .

    using Microsoft.VisualStudio.Text.Operations;
    using MSXML;
    using System.ComponentModel.Composition;
    
  2. Buat kelas mengimplementasikan TestCompletionCommandHandlerIVsExpansionClient antarmuka.

    internal class TestCompletionCommandHandler : IOleCommandTarget, IVsExpansionClient
    
  3. TestCompletionCommandHandlerProvider Di kelas , impor ITextStructureNavigatorSelectorService.

    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  4. Tambahkan beberapa bidang privat untuk antarmuka ekspansi kode dan IVsTextView.

    IVsTextView m_vsTextView;
    IVsExpansionManager m_exManager;
    IVsExpansionSession m_exSession;
    
  5. Di konstruktor TestCompletionCommandHandler kelas, atur bidang berikut.

    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);
    }
    
  6. Untuk menampilkan pemilih cuplikan saat pengguna mengklik perintah Sisipkan Cuplikan , tambahkan kode berikut ke Exec metode . (Untuk membuat penjelasan ini lebih mudah dibaca, Exec()kode yang digunakan untuk penyelesaian pernyataan tidak ditampilkan; sebaliknya, blok kode ditambahkan ke metode yang ada.) Tambahkan blok kode berikut setelah kode yang memeriksa karakter.

    //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;
    }
    
  7. Jika cuplikan memiliki bidang yang dapat dinavigasi, sesi ekspansi tetap terbuka sampai ekspansi diterima secara eksplisit; jika cuplikan tidak memiliki bidang, sesi ditutup dan dikembalikan sebagai null oleh InvokeInsertionUI metode . Exec Dalam metode , setelah kode UI pemilih cuplikan yang Anda tambahkan di langkah sebelumnya, tambahkan kode berikut untuk menangani navigasi cuplikan (ketika pengguna menekan Tab atau Shift+Tab setelah penyisipan cuplikan).

    //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;
            }
        }
    }
    
  8. Untuk menyisipkan cuplikan kode saat pengguna mengetik pintasan yang sesuai lalu menekan Tab, tambahkan kode ke Exec metode . Metode privat yang menyisipkan cuplikan akan ditampilkan di langkah selanjutnya. Tambahkan kode berikut setelah kode navigasi yang Anda tambahkan di langkah sebelumnya.

    //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;
    }
    
  9. Terapkan metode IVsExpansionClient antarmuka. Dalam implementasi ini, satu-satunya metode yang menarik adalah EndExpansion dan OnItemChosen. Metode lain seharusnya hanya mengembalikan 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;
    }
    
  10. Mengimplementasikan metode OnItemChosen. Metode pembantu yang benar-benar menyisipkan ekspansi dibahas di langkah selanjutnya. menyediakan TextSpan informasi baris dan kolom, yang bisa Anda dapatkan dari IVsTextView.

    public int OnItemChosen(string pszTitle, string pszPath)
    {
        InsertAnyExpansion(null, pszTitle, pszPath);
        return VSConstants.S_OK;
    }
    
  11. Metode privat berikut menyisipkan cuplikan kode, berdasarkan pintasan atau pada judul dan jalur. Kemudian memanggil InsertNamedExpansion metode dengan cuplikan.

    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;
    }
    

Membangun dan menguji ekspansi cuplikan kode

Anda dapat menguji apakah ekspansi cuplikan berfungsi dalam proyek Anda.

  1. Bangun solusinya. Saat Anda menjalankan proyek ini di debugger, instans kedua Visual Studio dimulai.

  2. Buka file teks dan ketik beberapa teks.

  3. Klik kanan di suatu tempat dalam teks lalu klik Sisipkan Cuplikan.

  4. UI pemilih cuplikan akan muncul dengan pop-up yang bertuliskan Bidang penggantian pengujian. Klik dua kali pop-up.

    Cuplikan berikut harus disisipkan.

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

    Jangan tekan Enter atau Esc.

  5. Tekan Tab dan Geser+Tab untuk beralih antara "pertama" dan "detik".

  6. Terima penyisipan dengan menekan Enter atau Esc.

  7. Di bagian teks yang berbeda, ketik "uji" lalu tekan Tab. Karena "pengujian" adalah pintasan cuplikan kode, cuplikan harus dimasukkan lagi.