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; }
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]); } } } } }
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; }
//</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); }
/// <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)); }
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(); } } }
/// <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); }