Example #1
0
        public void SetTextView(IVsTextView textViewAdapter)
        {
            m_vsTextView = textViewAdapter;
            //get the text manager from the service provider
            IVsTextManager2 textManager = (IVsTextManager2)languageService.GetService(typeof(SVsTextManager));

            textManager.GetExpansionManager(out m_exManager);
            // m_exSession = null;
        }
Example #2
0
        private void GetSnippets(Guid languageGuid,
                                 ref ArrayList expansionsList)
        {
            IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));

            if (textManager != null)
            {
                IVsTextManager2 textManager2 = (IVsTextManager2)textManager;
                if (textManager2 != null)
                {
                    IVsExpansionManager expansionManager = null;
                    textManager2.GetExpansionManager(out expansionManager);
                    if (expansionManager != null)
                    {
                        // Tell the environment to fetch all of our snippets.
                        IVsExpansionEnumeration expansionEnumerator = null;
                        expansionManager.EnumerateExpansions(languageGuid,
                                                             0,    // return all info
                                                             null, // return all types
                                                             0,    // return all types
                                                             1,    // include snippets without types
                                                             0,    // do not include duplicates
                                                             out expansionEnumerator);
                        if (expansionEnumerator != null)
                        {
                            // Cache our expansions in a VsExpansion array
                            uint        count          = 0;
                            uint        fetched        = 0;
                            VsExpansion expansionInfo  = new VsExpansion();
                            IntPtr[]    pExpansionInfo = new IntPtr[1];

                            // Allocate enough memory for one VSExpansion structure. This memory is filled in by the Next method.
                            pExpansionInfo[0] = Marshal.AllocCoTaskMem(Marshal.SizeOf(expansionInfo));

                            expansionEnumerator.GetCount(out count);
                            for (uint i = 0; i < count; i++)
                            {
                                expansionEnumerator.Next(1, pExpansionInfo, out fetched);
                                if (fetched > 0)
                                {
                                    // Convert the returned blob of data into a structure that can be read in managed code.
                                    expansionInfo = (VsExpansion)Marshal.PtrToStructure(pExpansionInfo[0], typeof(VsExpansion));

                                    if (!String.IsNullOrEmpty(expansionInfo.shortcut))
                                    {
                                        expansionsList.Add(expansionInfo);
                                    }
                                }
                            }
                            Marshal.FreeCoTaskMem(pExpansionInfo[0]);
                        }
                    }
                }
            }
        }
Example #3
0
 public PythonSnippetManager(
     [Import(typeof(SVsServiceProvider))] IServiceProvider site,
     [Import] IVsEditorAdaptersFactoryService editorAdaptersFactoryService
     )
 {
     _site = site ?? throw new ArgumentNullException(nameof(site));
     _editorAdaptersFactoryService = editorAdaptersFactoryService ?? throw new ArgumentNullException(nameof(editorAdaptersFactoryService));
     _textManager = site.GetService <SVsTextManager, IVsTextManager2>();
     _textManager.GetExpansionManager(out _vsExpansionMgr);
     _expansionMgr = _vsExpansionMgr as IExpansionManager;
 }
Example #4
0
        //</Snippet29>

        //<Snippet30>
        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);
        }
Example #5
0
        /// <include file='doc\ExpansionProvider.uex' path='docs/doc[@for="ExpansionProvider.DisplayExpansionBrowser"]/*' />
        public virtual bool DisplayExpansionBrowser(IVsTextView view, string prompt, string[] types, bool includeNullType, string[] kinds, bool includeNullKind)
        {
            if (this.expansionActive)
            {
                this.EndTemplateEditing(true);
            }

            if (this.source.IsCompletorActive)
            {
                this.source.DismissCompletor();
            }

            this.view = view;
            IServiceProvider site    = this.source.LanguageService.Site;
            IVsTextManager2  textmgr = site.GetService(typeof(SVsTextManager)) as IVsTextManager2;

            if (textmgr == null)
            {
                return(false);
            }

            IVsExpansionManager exmgr;

            textmgr.GetExpansionManager(out exmgr);
            Guid languageSID = this.source.LanguageService.GetLanguageServiceGuid();
            int  hr          = 0;

            if (exmgr != null)
            {
                hr = exmgr.InvokeInsertionUI(view,                               // pView
                                             this,                               // pClient
                                             languageSID,                        // guidLang
                                             types,                              // bstrTypes
                                             (types == null) ? 0 : types.Length, // iCountTypes
                                             includeNullType ? 1 : 0,            // fIncludeNULLType
                                             kinds,                              // bstrKinds
                                             (kinds == null) ? 0 : kinds.Length, // iCountKinds
                                             includeNullKind ? 1 : 0,            // fIncludeNULLKind
                                             prompt,                             // bstrPrefixText
                                             ">"                                 //bstrCompletionChar
                                             );
                if (NativeMethods.Succeeded(hr))
                {
                    return(true);
                }
            }

            return(false);
        }
        public CommandFilter(IVsTextView textViewAdapter, ITextView textView, VsTextViewCreationListener provider)
        {
            _vsTextView = textViewAdapter;
            _textView   = textView;
            _provider   = provider;

            // Get the text manager from the service provider
            IVsTextManager2 textManager = (IVsTextManager2)_provider._serviceProvider.GetService(typeof(SVsTextManager));

            textManager.GetExpansionManager(out _exManager);
            _exSession = null;

            // Add the command to the command chain
            textViewAdapter.AddCommandFilter(this, out _nextCommandHandler);
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == VSConstants.VSStd2K)
            {
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET || nCmdID == (uint)VSConstants.VSStd2KCmdID.SURROUNDWITH)
                {
                    IVsTextManager2     textManager = (IVsTextManager2)this.serviceProvider.GetService(typeof(SVsTextManager));
                    IVsExpansionManager expansionManager;
                    if (VSConstants.S_OK == textManager.GetExpansionManager(out expansionManager))
                    {
                        expansionManager.InvokeInsertionUI(
                            vsTextView,
                            this,
                            GuidList.guidSpringLanguage,
                            new string[] { "Expansion" },
                            1,
                            0,
                            null,
                            0,
                            1,
                            "Insert Snippet",
                            string.Empty);
                    }

                    return(VSConstants.S_OK);
                }

                if (this.expansionSession != null)
                {
                    // Handle VS Expansion (Code Snippets) keys
                    if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                    {
                        if (expansionSession.GoToNextExpansionField(0) == VSConstants.S_OK)
                        {
                            return(VSConstants.S_OK);
                        }
                    }
                    else if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKTAB))
                    {
                        if (expansionSession.GoToPreviousExpansionField() == VSConstants.S_OK)
                        {
                            return(VSConstants.S_OK);
                        }
                    }
                    else if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.CANCEL))
                    {
                        if (expansionSession.EndCurrentExpansion(0) == VSConstants.S_OK)
                        {
                            expansionSession = null;

                            return(VSConstants.S_OK);
                        }
                    }
                }

                // Handle Edit.ListMembers or Edit.CompleteWord commands
                if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.SHOWMEMBERLIST ||
                     nCmdID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD))
                {
                    if (completionSession != null)
                    {
                        completionSession.Dismiss();
                    }

                    ShowCompletion();

                    return(VSConstants.S_OK);
                }

                // Handle Enter/Tab commit keys
                if (completionSession != null && (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                {
                    if (completionSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        completionSession.Commit();
                    }
                    else
                    {
                        completionSession.Dismiss();
                    }

                    return(VSConstants.S_OK);
                }

                // Handle Code Snippets after pressing the Tab key without completion
                if (completionSession == null && (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                {
                    IVsTextManager2    expansionManager   = (IVsTextManager2)this.serviceProvider.GetService(typeof(SVsTextManager));
                    SnippetsEnumerable snippetsEnumerator = new SnippetsEnumerable(expansionManager, GuidList.guidSpringLanguage);

                    SnapshotPoint           currentPoint = (this.textView.Caret.Position.BufferPosition) - 1;
                    ITextStructureNavigator navigator    = this.textStructureNavigatorSelectorService.GetTextStructureNavigator(this.textView.TextBuffer);
                    TextExtent extent   = navigator.GetExtentOfWord(currentPoint);
                    string     shortcut = this.textView.TextSnapshot.GetText(extent.Span);

                    // Search a snippet that matched the token text
                    VsExpansion expansion = snippetsEnumerator.FirstOrDefault(e => e.title == shortcut);
                    if (expansion.title != null)
                    {
                        // Set the location where the snippet will be inserted
                        int startLine, startColumn, endLine, endColumn;

                        this.vsTextView.GetCaretPos(out startLine, out endColumn);
                        startColumn = endColumn - expansion.title.Length;
                        endLine     = startLine;

                        // Insert the snippet
                        InsertCodeExpansion(expansion, startLine, startColumn, endLine, endColumn);

                        return(VSConstants.S_OK);
                    }
                }

                // Hanlde other keys
                if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR))
                {
                    char typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);

                    if (completionSession == null)
                    {
                        // Handle trigger keys
                        // Check if the typed char is a trigger
                        if (IsTriggerKey(typedChar))
                        {
                            var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                            ShowCompletion();

                            return(result);
                        }
                    }
                    else
                    {
                        // Handle commit keys
                        // Check if the typed char is a commit key
                        if (IsCommitKey(typedChar))
                        {
                            SpringCompletion selectedCompletion = completionSession.SelectedCompletionSet.SelectionStatus.Completion as SpringCompletion;
                            if (completionSession.SelectedCompletionSet.SelectionStatus.IsSelected &&
                                selectedCompletion != null && selectedCompletion.Type != null &&
                                selectedCompletion.Type.Value == SpringCompletionType.Namespace)
                            {
                                completionSession.Commit();
                            }
                            else
                            {
                                completionSession.Dismiss();
                            }

                            var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                            // Check we should trigger completion after comitting the previous session (for example, after typing dot '.')
                            if (IsTriggerKey(typedChar))
                            {
                                ShowCompletion();
                            }

                            return(result);
                        }
                        else
                        {
                            var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                            completionSession.Filter();
                            return(result);
                        }
                    }
                }

                // redo the filter if there is a deletion
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                    nCmdID == (uint)VSConstants.VSStd2KCmdID.DELETE)
                {
                    var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                    if (completionSession != null && !completionSession.IsDismissed)
                    {
                        completionSession.Filter();
                    }

                    return(result);
                }
            }

            // we haven't handled this command so pass it onto the next target
            return(this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
Example #8
0
        public IEnumerator <VsExpansion> GetEnumerator()
        {
            IVsExpansionManager expansionManager;

            ErrorHandler.ThrowOnFailure(_textManager.GetExpansionManager(out expansionManager));

            IVsExpansionEnumeration enumerator;
            int onlyShortcut = (this.ShortcutOnly ? 1 : 0);

            ErrorHandler.ThrowOnFailure(expansionManager.EnumerateExpansions(_languageGuid, onlyShortcut, null, 0, 0, 0, out enumerator));

            ExpansionBuffer buffer = new ExpansionBuffer();
            GCHandle        handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            try {
                int  hr = VSConstants.S_OK;
                uint fetched;
                while (VSConstants.S_OK == (hr = enumerator.Next(1, new IntPtr[] { handle.AddrOfPinnedObject() }, out fetched)))
                {
                    buffer = (ExpansionBuffer)handle.Target;
                    try {
                        handle.Free();
                        if (IntPtr.Zero != buffer.shortcutPtr)
                        {
                            VsExpansion expansion = new VsExpansion();
                            expansion.shortcut = Marshal.PtrToStringBSTR(buffer.shortcutPtr);
                            if (IntPtr.Zero != buffer.descriptionPtr)
                            {
                                expansion.description = Marshal.PtrToStringBSTR(buffer.descriptionPtr);
                            }
                            if (IntPtr.Zero != buffer.pathPtr)
                            {
                                expansion.path = Marshal.PtrToStringBSTR(buffer.pathPtr);
                            }
                            if (IntPtr.Zero != buffer.titlePtr)
                            {
                                expansion.title = Marshal.PtrToStringBSTR(buffer.titlePtr);
                            }
                            yield return(expansion);

                            handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                        }
                    } finally {
                        if (IntPtr.Zero != buffer.descriptionPtr)
                        {
                            Marshal.FreeBSTR(buffer.descriptionPtr);
                            buffer.descriptionPtr = IntPtr.Zero;
                        }
                        if (IntPtr.Zero != buffer.pathPtr)
                        {
                            Marshal.FreeBSTR(buffer.pathPtr);
                            buffer.pathPtr = IntPtr.Zero;
                        }
                        if (IntPtr.Zero != buffer.shortcutPtr)
                        {
                            Marshal.FreeBSTR(buffer.shortcutPtr);
                            buffer.shortcutPtr = IntPtr.Zero;
                        }
                        if (IntPtr.Zero != buffer.titlePtr)
                        {
                            Marshal.FreeBSTR(buffer.titlePtr);
                            buffer.titlePtr = IntPtr.Zero;
                        }
                    }
                }
                ErrorHandler.ThrowOnFailure(hr);
            } finally {
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }
Example #9
0
        /// <summary>
        /// Executes a specified command or displays help for a command.
        /// </summary>
        /// <param name="pguidCmdGroupRef">Pointer to unique identifier of the command group; can be NULL to specify the standard group.</param>
        /// <param name="nCmdID">The command to be executed. This command must belong to the group specified with pguidCmdGroup.</param>
        /// <param name="nCmdexecopt">Values taken from the OLECMDEXECOPT enumeration, which describe how the object should execute the command.</param>
        /// <param name="pvaIn">Pointer to a VARIANTARG structure containing input arguments. Can be NULL.</param>
        /// <param name="pvaOut">Pointer to a VARIANTARG structure to receive command output. Can be NULL.</param>
        /// <returns>This method supports the standard return values E_FAIL and E_UNEXPECTED, as well as the following:
        ///            S_OK
        ///                The command was executed successfully.
        ///            OLECMDERR_E_UNKNOWNGROUP
        ///                The pguidCmdGroup parameter is not NULL but does not specify a recognized command group.
        ///            OLECMDERR_E_NOTSUPPORTED
        ///                The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup.
        ///            OLECMDERR_E_DISABLED
        ///                The command identified by nCmdID is currently disabled and cannot be executed.
        ///            OLECMDERR_E_NOHELP
        ///                The caller has asked for help on the command identified by nCmdID, but no help is available.
        ///            OLECMDERR_E_CANCELED
        ///                The user canceled the execution of the command.</returns>
        public int Exec(ref Guid pguidCmdGroupRef, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            //the snippet picker code starts here
            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET)
            {
                IVsTextManager2 textManager = (IVsTextManager2)languageService.GetService(typeof(SVsTextManager));

                textManager.GetExpansionManager(out m_exManager);

                IVsExpansionEnumeration expansionEnumerator = null;
                int ret = m_exManager.EnumerateExpansions(Guids.LuaLanguageService,
                                                          0,          // return all info
                                                          null,       // return all types
                                                          0,          // return all types
                                                          1,          // include snippets without types
                                                          0,          // do not include duplicates
                                                          out expansionEnumerator);

                uint count = 0;
                if (expansionEnumerator != null)
                {
                    expansionEnumerator.GetCount(out count);
                }
                if (count == 0)
                {
                    RegisterCodeSnippets();
                    return(VSConstants.S_OK);
                }
                m_exManager.InvokeInsertionUI(
                    m_vsTextView,
                    this,          //the expansion client
                    Guids.LuaLanguageService,
                    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
                    "Lua",         //the text to show in the prompt
                    string.Empty); //only the ENTER key causes insert

                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 != 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);
                    }
                }
            }
            //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_exSession == null && nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            //{
            //    //get the word that was just added
            //    CaretPosition pos = m_vsTextView.Caret.Position;
            //    TextExtent word = languageService.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;
            //}

#if SUPPORT_REFACTOR
            string commandId = VSIDECommands.GetCommandId(pguidCmdGroupRef, nCmdID);

            if (!string.IsNullOrEmpty(commandId))
            {
                // refactor and undo are not working anyway.
                {
                    //Refactor command
                    if (VSIDECommands.IsRightClick(pguidCmdGroupRef, nCmdID))
                    {
                        SetRefactorMenuBars();
                        return(ExecVsHandler(ref pguidCmdGroupRef, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                    }

                    //Undo command
                    if (commandId == "cmdidUndo")
                    {
                        var luaUndoService = languageService.GetService(typeof(ILuaUndoService)) as ILuaUndoService;
                        if (luaUndoService != null)
                        {
                            luaUndoService.Undo();
                        }

                        return(ExecVsHandler(ref pguidCmdGroupRef, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                    }
                }
            }
#endif
            return(ExecVsHandler(ref pguidCmdGroupRef, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            // Handle VS commands to support code snippets

            if (pguidCmdGroup == VSConstants.VSStd2K)
            {
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET || nCmdID == (uint)VSConstants.VSStd2KCmdID.SURROUNDWITH)
                {
                    IVsTextManager2     textManager = (IVsTextManager2)this.serviceProvider.GetService(typeof(SVsTextManager));
                    IVsExpansionManager expansionManager;
                    if (VSConstants.S_OK == textManager.GetExpansionManager(out expansionManager))
                    {
                        expansionManager.InvokeInsertionUI(
                            vsTextView,
                            this,
                            Constants.IronPythonLanguageServiceGuid,
                            null,
                            0,
                            1,
                            null,
                            0,
                            1,
                            "Insert Snippet",
                            string.Empty);
                    }

                    return(VSConstants.S_OK);
                }

                if (this.expansionSession != null)
                {
                    // Handle VS Expansion (Code Snippets) keys
                    if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                    {
                        if (expansionSession.GoToNextExpansionField(0) == VSConstants.S_OK)
                        {
                            return(VSConstants.S_OK);
                        }
                    }
                    else if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKTAB))
                    {
                        if (expansionSession.GoToPreviousExpansionField() == VSConstants.S_OK)
                        {
                            return(VSConstants.S_OK);
                        }
                    }
                    else if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.CANCEL))
                    {
                        if (expansionSession.EndCurrentExpansion(0) == VSConstants.S_OK)
                        {
                            expansionSession = null;

                            return(VSConstants.S_OK);
                        }
                    }
                }

                // Handle Edit.ListMembers or Edit.CompleteWord commands
                if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.SHOWMEMBERLIST || nCmdID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD))
                {
                    if (activeSession != null)
                    {
                        activeSession.Dismiss();
                    }

                    ShowCompletion();

                    return(VSConstants.S_OK);
                }

                // Handle Enter/Tab commit keys
                if (activeSession != null && (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                {
                    if (activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        activeSession.Commit();
                    }
                    else
                    {
                        activeSession.Dismiss();
                    }

                    return(VSConstants.S_OK);
                }

                // Handle Code Snippets after pressing the Tab key without completion
                if (activeSession == null && (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB))
                {
                    using (var systemState = new SystemState())
                    {
                        // Get the current line text until the cursor
                        var line = this.textView.GetTextViewLineContainingBufferPosition(this.textView.Caret.Position.BufferPosition);
                        var text = this.textView.TextSnapshot.GetText(line.Start.Position, this.textView.Caret.Position.BufferPosition - line.Start.Position);

                        // Create a tokenizer for the text
                        var tokenizer = new Tokenizer(text.ToCharArray(), true, systemState, new CompilerContext(string.Empty, new QuietCompilerSink()));

                        // Get the last token in the text
                        Token currentToken, lastToken = null;
                        while ((currentToken = tokenizer.Next()).Kind != TokenKind.NewLine)
                        {
                            lastToken = currentToken;
                        }

                        if (lastToken != null && lastToken.Kind != TokenKind.Constant)
                        {
                            var expansionManager   = (IVsTextManager2)this.serviceProvider.GetService(typeof(SVsTextManager));
                            var snippetsEnumerator = new SnippetsEnumerator(expansionManager, Constants.IronPythonLanguageServiceGuid);

                            // Search a snippet that matched the token text
                            var expansion = snippetsEnumerator.FirstOrDefault(e => e.title == lastToken.Value.ToString());

                            if (expansion.title != null)
                            {
                                // Set the location where the snippet will be inserted
                                int startLine, startColumn, endLine, endColumn;

                                this.vsTextView.GetCaretPos(out startLine, out endColumn);
                                startColumn = endColumn - expansion.title.Length;
                                endLine     = startLine;

                                // Insert the snippet
                                InsertCodeExpansion(expansion, startLine, startColumn, endLine, endColumn);

                                return(VSConstants.S_OK);
                            }
                        }
                    }
                }

                // Hanlde other keys
                if ((nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR))
                {
                    char typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);

                    if (activeSession == null)
                    {
                        // Handle trigger keys
                        // Check if the typed char is a trigger
                        if (IsTriggerKey(typedChar))
                        {
                            var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                            ShowCompletion();

                            return(result);
                        }
                    }
                    else
                    {
                        // Handle commit keys
                        // Check if the typed char is a commit key
                        if (IsCommitKey(typedChar))
                        {
                            if (activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                            {
                                activeSession.Commit();
                            }
                            else
                            {
                                activeSession.Dismiss();
                            }

                            var result = this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                            // Check we should trigger completion after comitting the previous session (for example, after typing dot '.')
                            if (IsTriggerKey(typedChar))
                            {
                                ShowCompletion();
                            }

                            return(result);
                        }
                    }
                }
            }

            // we haven't handled this command so pass it onto the next target
            return(this.nextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (VsShellUtilities.IsInAutomationFunction(_provider._serviceProvider))
            {
                return(_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }
            // Make a copy of this so we can look at it after forwarding some commands
            uint commandID = nCmdID;
            char typedChar = char.MinValue;

            // Make sure the input is a char before getting it
            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)_provider._serviceProvider.GetService(typeof(SVsTextManager));

                textManager.GetExpansionManager(out _exManager);

                _exManager.InvokeInsertionUI(
                    _vsTextView,
                    this,           //the expansion client
                    new Guid(GuidList.guidDaxLanguageService),
                    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
                    "DAX Snippets", //the text to show in the prompt
                    string.Empty);  //only the ENTER key causes insert

                return(VSConstants.S_OK);
            }

            //the expansion insertion is handled in OnItemChosen
            //if the expansion session is still active, handle tab/backtab/return/cancel
            if (_exSession != null)
            {
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKTAB)
                {
                    _exSession.GoToPreviousExpansionField();
                    return(VSConstants.S_OK);
                }
                else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
                {
                    _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 (_exSession.EndCurrentExpansion(0) == VSConstants.S_OK)
                    {
                        _exSession = 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 == null && */ _exSession == null && nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            {
                //get the word that was just added
                CaretPosition pos        = _textView.Caret.Position;
                TextExtent    word       = _provider._navigatorService.GetTextStructureNavigator(_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);
                }
            }

            // Check for a commit character
            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
                (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar)))
            {
                // Check for a a selection
                if (_session != null && !_session.IsDismissed)
                {
                    // If the selection is fully selected, commit the current session
                    if (_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        _session.Commit();
                        // Also, don't add the character to the buffer
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        // If there is no selection, dismiss the session
                        _session.Dismiss();
                    }
                }
            }

            // Pass along the command so the char is added to the buffer
            int  retVal  = _nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            bool handled = false;

            if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
            {
                if (_session == null || _session.IsDismissed) // If there is no active session, bring up completion
                {
                    this.TriggerCompletion();
                    _session.Filter();
                }
                else     // The completion session is already active, so just filter
                {
                    _session.Filter();
                }
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE || // Redo the filter if there is a deletion
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                if (_session != null && !_session.IsDismissed)
                {
                    _session.Filter();
                }
                handled = true;
            }


            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }