public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
		{
			var handled = false;
			var hresult = VSConstants.S_OK;

			if (pguidCmdGroup == VSConstants.VSStd2K)
			{
				switch ((VSConstants.VSStd2KCmdID) nCmdID)
				{
					case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
					case VSConstants.VSStd2KCmdID.COMPLETEWORD:
						handled = true;
						if (IsSessionStarted) break;
						_currentSession = StartSession();
						break;
					case VSConstants.VSStd2KCmdID.RETURN:
						if (!IsSessionStarted) break;
						handled = true;
						_currentSession.Commit();
						break;
					case VSConstants.VSStd2KCmdID.TAB:
						if (!IsSessionStarted) break;
						handled = true;
						_currentSession.Commit();
						break;
					case VSConstants.VSStd2KCmdID.CANCEL:
						if (!IsSessionStarted) break;
						handled = true;
						_currentSession.Dismiss();
						break;
				}
			}

			if (!handled) hresult = Next.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

			if (ErrorHandler.Succeeded(hresult))
			{
				if (pguidCmdGroup == VSConstants.VSStd2K)
				{
					switch ((VSConstants.VSStd2KCmdID) nCmdID)
					{
						case VSConstants.VSStd2KCmdID.TYPECHAR:
							if (IsSessionStarted) _currentSession.Filter();
							break;
						case VSConstants.VSStd2KCmdID.BACKSPACE:
							if (IsSessionStarted)
							{
								_currentSession.Dismiss();
								_currentSession = StartSession();
							}
							break;
					}
				}
			}

			return hresult;
		}
        public bool Commit()
        {
            if (_session == null)
            {
                return(false);
            }

            var isBuilder = _session.SelectedCompletionSet?.SelectionStatus?.Completion != null &&
                            _session.SelectedCompletionSet.CompletionBuilders != null &&
                            _session.SelectedCompletionSet.CompletionBuilders.Contains(_session.SelectedCompletionSet.SelectionStatus.Completion);

            // If it's a builder, we don't want to eat the enter key.
            var sendThrough = isBuilder;

            //_workspace.CurrentDocumentChanged -= WorkspaceOnCurrentDocumentChanged;
            _session.Commit();
            //_workspace.CurrentDocumentChanged += WorkspaceOnCurrentDocumentChanged;

            return(!sendThrough);
        }
예제 #3
0
        private bool SelectSingleBestCompletion(ICompletionSession session)
        {
            if (session.CompletionSets.Count != 1)
            {
                return(false);
            }
            var set = session.CompletionSets[0] as FuzzyCompletionSet;

            if (set == null)
            {
                return(false);
            }
            set.Filter();
            if (set.SelectSingleBest())
            {
                session.Commit();
                return(true);
            }
            return(false);
        }
예제 #4
0
        public virtual bool CommitCompletion()
        {
            ICompletionSession session = CompletionSession;

            if (session != null && session.SelectedCompletionSet != null && session.SelectedCompletionSet.SelectionStatus != null)
            {
                Completion completion = session.SelectedCompletionSet.SelectionStatus.Completion;
                if (completion != null && session.SelectedCompletionSet.SelectionStatus.IsSelected)
                {
                    ITrackingSpan applicableToSpan = session.SelectedCompletionSet.ApplicableTo;
                    if (applicableToSpan != null && applicableToSpan.GetSpan(applicableToSpan.TextBuffer.CurrentSnapshot).GetText() != completion.InsertionText)
                    {
                        session.Commit();
                        return(true);
                    }
                }
            }

            DismissCompletion();
            return(false);
        }
        private bool Complete(bool force)
        {
            // Handle non-existant Sessions
            if (_currentSession == null)
            {
                return(false);
            }

            // Based off of the available selection, determine if it should be dismissed (via Dismiss) or
            // output (via Commit)
            if (!_currentSession.SelectedCompletionSet.SelectionStatus.IsSelected && !force)
            {
                _currentSession.Dismiss();
                return(false);
            }
            else
            {
                _currentSession.Commit();
                return(true);
            }
        }
        public static bool TryShift(ITextView view, ICompletionBroker broker, RotationDirection direction)
        {
            try
            {
                string key = direction == RotationDirection.Right ? "{DOWN}" : "{UP}";

                if (!broker.IsCompletionActive(view))
                {
                    ICompletionSession session = broker.TriggerCompletion(view);

                    if (session == null || !session.IsStarted)
                    {
                        return(false);
                    }

                    Completion active = session.CompletionSets?[0]?.SelectionStatus?.Completion;

                    if (active != null)
                    {
                        SendKeys.SendWait(key);
                        session.Commit();

                        return(true);
                    }
                }
                else
                {
                    SendKeys.Send(key);
                    return(true);
                }
            }
            catch (Exception ex)
            {
                var outputPane = ThreadHelper.JoinableTaskContext.Factory.Run(DialPackage.GetOutputPaneAsync);
                outputPane.WriteLine("Intellisense shifter failed");
                outputPane.WriteLine(ex.ToString());
            }

            return(false);
        }
        internal void TriggerCompletionSession(bool completeWord)
        {
            Dismiss();

            _activeSession = CompletionBroker.TriggerCompletion(_textView);

            if (_activeSession != null)
            {
                if (completeWord &&
                    _activeSession.CompletionSets.Count == 1 &&
                    _activeSession.CompletionSets[0].Completions.Count == 1)
                {
                    _activeSession.Commit();
                }
                else
                {
                    AttachKeyboardFilter();
                    _activeSession.Dismissed += new EventHandler(OnSessionDismissedOrCommitted);
                    _activeSession.Committed += new EventHandler(OnSessionDismissedOrCommitted);
                }
            }
        }
예제 #8
0
        public bool ExecuteKeyboardCommand(IntellisenseKeyboardCommand command)
        {
            switch (command)
            {
            case IntellisenseKeyboardCommand.Up:
                Move(-1);
                return(true);

            case IntellisenseKeyboardCommand.Down:
                Move(1);
                return(true);

            case IntellisenseKeyboardCommand.PageUp:
                Move(-10);
                return(true);

            case IntellisenseKeyboardCommand.PageDown:
                Move(10);
                return(true);

            case IntellisenseKeyboardCommand.Enter:
                _completionSession.Commit();
                return(true);

            case IntellisenseKeyboardCommand.Escape:
                _completionSession.Dismiss();
                return(true);

            //Maybe one day we'll do something with these below
            case IntellisenseKeyboardCommand.End:
            case IntellisenseKeyboardCommand.Home:
            case IntellisenseKeyboardCommand.DecreaseFilterLevel:
            case IntellisenseKeyboardCommand.IncreaseFilterLevel:
            case IntellisenseKeyboardCommand.TopLine:
            case IntellisenseKeyboardCommand.BottomLine:
                break;
            }
            return(false);
        }
예제 #9
0
        public virtual void TriggerCompletion(ITrackingPoint triggerPoint, CompletionInfoType completionInfoType, IntellisenseInvocationType intellisenseInvocationType)
        {
            DismissCompletion();
            CompletionInfo.InfoType       = completionInfoType;
            CompletionInfo.InvocationType = intellisenseInvocationType;
            ICompletionSession session = Provider.CompletionBroker.TriggerCompletion(TextView, triggerPoint, true);

            if (session != null)
            {
                session.Committed += HandleCompletionCommitted;
                session.Dismissed += HandleCompletionDismissed;
                CompletionSession  = session;

                if (completionInfoType == CompletionInfoType.GlobalInfo &&
                    !session.IsDismissed &&
                    session.SelectedCompletionSet.SelectionStatus.IsSelected &&
                    session.SelectedCompletionSet.SelectionStatus.IsUnique)
                {
                    session.Commit();
                }
            }
        }
        public static bool TryShift(ITextView view, ICompletionBroker broker, RotationDirection direction)
        {
            try
            {
                string key = direction == RotationDirection.Right ? "{DOWN}" : "{UP}";

                if (!broker.IsCompletionActive(view))
                {
                    ICompletionSession session = broker.TriggerCompletion(view);

                    if (session == null || !session.IsStarted)
                    {
                        return(false);
                    }

                    Completion active = session.CompletionSets?[0]?.SelectionStatus?.Completion;

                    if (active != null)
                    {
                        SendKeys.SendWait(key);
                        session.Commit();

                        return(true);
                    }
                }
                else
                {
                    SendKeys.Send(key);
                    return(true);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Log(ex);
            }

            return(false);
        }
예제 #11
0
        private void StartSession(ITrackingPoint triggerPoint)
        {
            Log.Debug("Creating new completion session...");
            _broker.DismissAllSessions(_textView);
            _activeSession = _broker.CreateCompletionSession(_textView, triggerPoint, true);
            _activeSession.Properties.AddProperty(BufferProperties.SessionOriginIntellisense, "Intellisense");
            _activeSession.Dismissed += CompletionSession_Dismissed;
            _activeSession.Start();

            if (_startTabComplete == true)
            {
                var completions = _activeSession.SelectedCompletionSet.Completions;

                if (completions != null && completions.Count > 0)
                {
                    var startPoint = _activeSession.SelectedCompletionSet.ApplicableTo.GetStartPoint(_textView.TextBuffer.CurrentSnapshot).Position;
                    _tabCompleteSession = new TabCompleteSession(completions, _activeSession.SelectedCompletionSet.SelectionStatus, startPoint);
                    _activeSession.Commit();
                }

                _startTabComplete = false;
            }
        }
        bool Complete(bool force)
        {
            if (m_session == null)
            {
                return(false);
            }

            if (!m_session.SelectedCompletionSet.SelectionStatus.IsSelected && !force)
            {
                m_session.Dismiss();
                return(false);
            }

            var completion = m_session.SelectedCompletionSet.SelectionStatus.Completion;

            if (completion != null)
            {
                ALanguageCompletionSource.UserSelected(completion.InsertionText);
            }

            m_session.Commit();
            return(true);
        }
예제 #13
0
        /// <summary>
        /// Main method used to determine how to handle keystrokes within a ITextBuffer.
        /// </summary>
        /// <param name="pguidCmdGroup">The GUID of the command group.</param>
        /// <param name="nCmdId">The command ID.</param>
        /// <param name="nCmdexecopt">
        ///    Specifies how the object should execute the command. Possible values are taken from the
        ///    Microsoft.VisualStudio.OLE.Interop.OLECMDEXECOPT and Microsoft.VisualStudio.OLE.Interop.OLECMDID_WINDOWSTATE_FLAG
        ///    enumerations.
        /// </param>
        /// <param name="pvaIn">The input arguments of the command.</param>
        /// <param name="pvaOut">The output arguments of the command.</param>
        /// <returns></returns>
        public int Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            bool?isInStringArea = null;
            var  command        = (VSConstants.VSStd2KCmdID)nCmdId;

            if (VsShellUtilities.IsInAutomationFunction(_serviceProvider) ||
                IsUnhandledCommand(pguidCmdGroup, command) ||
                Utilities.IsCaretInCommentArea(_textView))
            {
                Log.DebugFormat("Non-VSStd2K command: '{0}'", ToCommandName(pguidCmdGroup, nCmdId));
                return(NextCommandHandler.Exec(ref pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut));
            }

            //make a copy of this so we can look at it after forwarding some commands
            var typedChar = char.MinValue;

            // Exit tab complete session if command is any recognized command other than tab
            if (_tabCompleteSession != null && command != VSConstants.VSStd2KCmdID.TAB && command != VSConstants.VSStd2KCmdID.BACKTAB)
            {
                _tabCompleteSession = null;
                _startTabComplete   = false;
            }

            //make sure the input is a char before getting it
            if (command == VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
                Log.DebugFormat("Typed Character: '{0}'", (typedChar == char.MinValue) ? "<null>" : typedChar.ToString());

                if (_activeSession == null &&
                    IsNotIntelliSenseTriggerWhenInStringLiteral(typedChar))
                {
                    isInStringArea = this.IsInStringArea(isInStringArea);
                    if (isInStringArea == true)
                    {
                        return(NextCommandHandler.Exec(ref pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut));
                    }
                }
            }
            else
            {
                Log.DebugFormat("Non-TypeChar command: '{0}'", ToCommandName(pguidCmdGroup, nCmdId));
            }

            switch (command)
            {
            case VSConstants.VSStd2KCmdID.RETURN:
                //check for a a selection
                if (_activeSession != null && !_activeSession.IsDismissed)
                {
                    //if the selection is fully selected, commit the current session
                    if (_activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        Log.Debug("Commit");
                        _activeSession.Commit();

                        //also, don't add the character to the buffer
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        Log.Debug("Dismiss");
                        //if there is no selection, dismiss the session
                        _activeSession.Dismiss();
                    }
                }
                break;

            case VSConstants.VSStd2KCmdID.TAB:
            case VSConstants.VSStd2KCmdID.BACKTAB:

                if (_activeSession != null && !_activeSession.IsDismissed)
                {
                    var completions = _activeSession.SelectedCompletionSet.Completions;
                    if (completions != null && completions.Count > 0)
                    {
                        var startPoint = _activeSession.SelectedCompletionSet.ApplicableTo.GetStartPoint(_textView.TextBuffer.CurrentSnapshot).Position;
                        _tabCompleteSession = new TabCompleteSession(_activeSession.SelectedCompletionSet.Completions, _activeSession.SelectedCompletionSet.SelectionStatus, startPoint);
                        _activeSession.Commit();

                        //also, don't add the character to the buffer
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        Log.Debug("Dismiss");
                        //If there are no completions, dismiss the session
                        _activeSession.Dismiss();
                    }
                }
                else if (_tabCompleteSession != null)
                {
                    if (command == VSConstants.VSStd2KCmdID.TAB)
                    {
                        _tabCompleteSession.ReplaceWithNextCompletion(_textView.TextBuffer, _textView.Caret.Position.BufferPosition.Position);
                    }
                    else
                    {
                        _tabCompleteSession.ReplaceWithPreviousCompletion(_textView.TextBuffer, _textView.Caret.Position.BufferPosition.Position);
                    }

                    //don't add the character to the buffer
                    return(VSConstants.S_OK);
                }
                else if (!Utilities.IsPrecedingTextInLineEmpty(_textView.Caret.Position.BufferPosition) && _textView.Selection.IsEmpty)
                {
                    _startTabComplete = true;
                    TriggerCompletion();

                    //don't add the character to the buffer
                    return(VSConstants.S_OK);
                }
                break;

            case VSConstants.VSStd2KCmdID.COMPLETEWORD:
                isInStringArea = this.IsInStringArea(isInStringArea);
                if (isInStringArea == true)
                {
                    return(NextCommandHandler.Exec(ref pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut));
                }

                TriggerCompletion();
                return(VSConstants.S_OK);

            default:
                break;
            }

            //check for a commit character
            if (char.IsWhiteSpace(typedChar) && _activeSession != null && !_activeSession.IsDismissed)
            {
                // If user is typing a variable, SPACE shouldn't commit the selection.
                // If the selection is fully matched with user's input, commit the current session and add the commit character to text buffer.
                if (_activeSession.SelectedCompletionSet.SelectionStatus.IsSelected &&
                    !_activeSession.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.StartsWith("$", StringComparison.InvariantCulture))
                {
                    Log.Debug("Commit");
                    _activeSession.Commit();

                    bool isCompletionFullyMatched = false;
                    _textView.TextBuffer.Properties.TryGetProperty(BufferProperties.SessionCompletionFullyMatchedStatus, out isCompletionFullyMatched);
                    if (isCompletionFullyMatched)
                    {
                        // If user types all characters in a completion and click Space, then we should commit the selection and add the Space into text buffer.
                        return(NextCommandHandler.Exec(ref pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut));
                    }

                    //Don't add the character to the buffer if this commits the selection.
                    return(VSConstants.S_OK);
                }
                else
                {
                    Log.Debug("Dismiss");
                    //if there is no selection, dismiss the session
                    _activeSession.Dismiss();
                }
            }

            bool justCommitIntelliSense = false;

            if (IsIntelliSenseTriggerDot(typedChar) && _activeSession != null && !_activeSession.IsDismissed)
            {
                var selectionStatus = _activeSession.SelectedCompletionSet.SelectionStatus;
                if (selectionStatus.IsSelected)
                {
                    // If user types the full completion text, which ends with a dot, then we should just commit IntelliSense session ignore user's last typing.
                    ITrackingSpan lastWordSpan;
                    var           currentSnapshot = _textView.TextBuffer.CurrentSnapshot;
                    _textView.TextBuffer.Properties.TryGetProperty <ITrackingSpan>(BufferProperties.LastWordReplacementSpan, out lastWordSpan);
                    if (lastWordSpan != null)
                    {
                        string lastWordText        = lastWordSpan.GetText(currentSnapshot);
                        int    completionSpanStart = lastWordSpan.GetStartPoint(currentSnapshot);
                        int    completionSpanEnd   = _textView.Caret.Position.BufferPosition;
                        var    completionText      = currentSnapshot.GetText(completionSpanStart, completionSpanEnd - completionSpanStart);
                        completionText += typedChar;
                        Log.DebugFormat("completionSpanStart: {0}", completionSpanStart);
                        Log.DebugFormat("completionSpanEnd: {0}", completionSpanEnd);
                        Log.DebugFormat("completionText: {0}", completionText);

                        if (selectionStatus.Completion.InsertionText.Equals(completionText, StringComparison.OrdinalIgnoreCase))
                        {
                            Log.Debug(String.Format("Commited by {0}", typedChar));
                            _activeSession.Commit();
                            return(VSConstants.S_OK);
                        }
                    }

                    Log.Debug("Commit");
                    _activeSession.Commit();
                    justCommitIntelliSense = true;
                }
                else
                {
                    Log.Debug("Dismiss");
                    //if there is no selection, dismiss the session
                    _activeSession.Dismiss();
                }
            }

            // Check the char at caret before pass along the command
            // If command is backspace and completion session is active, then we need to see if the char to be deleted is an IntelliSense triggering char
            // If yes, then after deleting the char, we also dismiss the completion session
            // Otherwise, just filter the completion lists
            char charAtCaret = char.MinValue;

            if (command == VSConstants.VSStd2KCmdID.BACKSPACE && _activeSession != null && !_activeSession.IsDismissed)
            {
                int caretPosition = _textView.Caret.Position.BufferPosition.Position - 1;
                if (caretPosition >= 0)
                {
                    // caretPosition == -1 means caret is at the beginning of a file, which means no characters before it.
                    ITrackingPoint caretCharPosition = _textView.TextSnapshot.CreateTrackingPoint(caretPosition, PointTrackingMode.Positive);
                    charAtCaret = caretCharPosition.GetCharacter(_textView.TextSnapshot);
                }
            }

            // 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 (IsIntellisenseTrigger(typedChar) ||
                (justCommitIntelliSense || (IsIntelliSenseTriggerDot(typedChar) && IsPreviousTokenVariable())) || // If dot just commit a session or previous token before a dot was a variable, trigger intellisense
                (char.IsWhiteSpace(typedChar) && IsPreviousTokenParameter()))                                     // If the previous token before a space was a parameter, trigger intellisense
            {
                isInStringArea = this.IsInStringArea(isInStringArea);
                if (isInStringArea == false)
                {
                    TriggerCompletion();
                }
            }
            if (!typedChar.Equals(char.MinValue) && IsFilterTrigger(typedChar))
            {
                if (_activeSession != null)
                {
                    if (_activeSession.IsStarted)
                    {
                        try
                        {
                            Log.Debug("Filter");
                            _activeSession.Filter();
                        }
                        catch (Exception ex)
                        {
                            Log.Debug("Failed to filter session.", ex);
                        }
                    }
                }
            }
            else if (command == VSConstants.VSStd2KCmdID.BACKSPACE ||
                     command == VSConstants.VSStd2KCmdID.DELETE) //redo the filter if there is a deletion
            {
                if (_activeSession != null && !_activeSession.IsDismissed)
                {
                    try
                    {
                        if (_textView.Caret.Position.BufferPosition <= _completionCaretPosition)
                        {
                            Log.Debug("Dismiss");
                            _activeSession.Dismiss();
                        }
                        else
                        {
                            Log.Debug("Filter");
                            _activeSession.Filter();
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Debug("Failed to filter session.", ex);
                    }
                }

                handled = true;
            }
            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
예제 #14
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (VsShellUtilities.IsInAutomationFunction(_serviceProvider))
            {
                return(Next.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }
            var commandID = nCmdID;
            var typedChar = char.MinValue;

            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }


            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            {
                if (_currentSession != null && !_currentSession.IsDismissed)
                {
                    if (_currentSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        _currentSession.Commit();
                        return(VSConstants.S_OK);
                    }
                    _currentSession.Dismiss();
                }
            }

            var retVal  = Next.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            var handled = false;

            switch ((VSConstants.VSStd2KCmdID)commandID)
            {
            case VSConstants.VSStd2KCmdID.COMPLETEWORD:
            case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
                if (_currentSession == null || _currentSession.IsDismissed)
                {
                    TriggerCompletion();
                }
                Filter();
                handled = true;
                break;

            case VSConstants.VSStd2KCmdID.TYPECHAR:
                if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
                {
                    if (_currentSession == null || _currentSession.IsDismissed)
                    {
                        TriggerCompletion();
                    }
                    Filter();
                    handled = true;
                }
                break;

            case VSConstants.VSStd2KCmdID.BACKSPACE:
            case VSConstants.VSStd2KCmdID.DELETE:
                TriggerCompletion(true);
                Filter();
                handled = true;
                break;
            }
            return(handled ? VSConstants.S_OK : retVal);
        }
예제 #15
0
 private bool SelectSingleBestCompletion(ICompletionSession session) {
     if (session.CompletionSets.Count != 1) {
         return false;
     }
     var set = session.CompletionSets[0] as FuzzyCompletionSet;
     if (set == null) {
         return false;
     }
     set.Filter();
     if (set.SelectSingleBest()) {
         session.Commit();
         return true;
     }
     return false;
 }
예제 #16
0
        internal void TriggerCompletionSession(bool completeWord)
        {
            Dismiss();

            _activeSession = CompletionBroker.TriggerCompletion(_textView);

            if (_activeSession != null) {
                if (completeWord &&
                    _activeSession.CompletionSets.Count == 1 &&
                    _activeSession.CompletionSets[0].Completions.Count == 1) {
                    _activeSession.Commit();
                } else {
                    AttachKeyboardFilter();
                    _activeSession.Dismissed += new EventHandler(OnSessionDismissedOrCommitted);
                    _activeSession.Committed += new EventHandler(OnSessionDismissedOrCommitted);
                }
            }
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
            {
                return(m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }
            uint commandID = nCmdID;
            char typedChar = char.MinValue;

            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }

            VSConstants.VSStd2KCmdID nCmdIDEnum = (VSConstants.VSStd2KCmdID)nCmdID;
            //System.Console.WriteLine("Keyboard command: " + nCmdIDEnum);

            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB
                /*|| (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar))*/)//this made auto complete on point or space
            {
                if (m_session != null && !m_session.IsDismissed)
                {
                    if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        m_session.Commit();
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        m_session.Dismiss();
                    }
                }
            }

            ThreadHelper.ThrowIfNotOnUIThread();
            int  retVal  = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            bool handled = false;

            if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar) || nCmdIDEnum == VSConstants.VSStd2KCmdID.COMPLETEWORD)
            {
                if (m_session == null || m_session.IsDismissed)
                {
                    TriggerCompletion();
                }
                else
                {
                    m_session.Filter();
                }
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                if (m_session != null && !m_session.IsDismissed)
                {
                    m_session.Filter();
                }
                handled = true;
            }
            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
예제 #18
0
        // !EFW - This has been throwing random null reference exceptions in VS 2019.  It's not something I've
        // been able to duplicate so I've added null checks everywhere to see if that stops it.
        private bool HandleCompletion(char commitCharacter)
        {
            ReadOnlyCollection <ICompletionSession> completionSessions = _completionBroker.GetSessions(_textView);

            if (completionSessions == null || completionSessions.Count == 0)
            {
                return(false);
            }

            ICompletionSession completionSession = completionSessions[0];

            if (completionSession == null || completionSession.IsDismissed)
            {
                return(false);
            }

            CompletionSet             completionSet   = completionSession.SelectedCompletionSet;
            CompletionSelectionStatus selectionStatus = completionSet?.SelectionStatus;

            if (!(selectionStatus?.Completion is SandcastleCompletion))
            {
                // Workaround some odd behavior in the completion when trying to enter "</".  This prevents it
                // from converting it to an XML comment ("<!--/-->").
                if (commitCharacter == '/' && selectionStatus?.Completion?.InsertionText == "!--")
                {
                    completionSession.Dismiss();
                }

                // Let other providers handle their own completions
                return(false);
            }

            string insertionText = selectionStatus.Completion.InsertionText;

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

            completionSession.Commit();

            bool passCharacterToEditor;

            switch (commitCharacter)
            {
            case '/':
            case '>':
                // If the insertion text doesn't end with '>' or '/>', allow the user to complete the item and insert
                // the closing element character by typing '/' or '>'.
                passCharacterToEditor = !insertionText.EndsWith(">");
                break;

            case ' ':
                // Only pass the space through if the completion item doesn't contain any replaceable elements
                passCharacterToEditor = insertionText.IndexOf('\xFF') < 0;
                break;

            case '\n':
            case '\t':
            default:
                // These items trigger completion, but aren't written to the output
                passCharacterToEditor = false;
                break;
            }

            return(!passCharacterToEditor);
        }
예제 #19
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (VsShellUtilities.IsInAutomationFunction(provider.ServiceProvider))
            {
                return(nextCommandHandler.Execute(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;
            bool handled             = false;
            bool completionRequested = false;

            lock (DothtmlCompletionSource.activeSessions)
            {
                session = DothtmlCompletionSource.activeSessions.FirstOrDefault();
            }

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

            //check for a commit character
            if (nCmdId == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdId == (uint)VSConstants.VSStd2KCmdID.TAB ||
                (char.IsWhiteSpace(typedChar)
                 //|| char.IsPunctuation(typedChar)
                 || typedChar == '='))
            {
                //check for a a selection
                if (session != null && session.IsStarted && !session.IsDismissed)
                {
                    var textView = session.TextView;
                    // if TAB is pressed, select the best match to commit
                    bool selectionTabOverrule = nCmdId == (uint)VSConstants.VSStd2KCmdID.TAB && !session.SelectedCompletionSet.SelectionStatus.IsSelected;

                    //if the selection is fully selected, commit the current session
                    if (session.SelectedCompletionSet.SelectionStatus.IsSelected || selectionTabOverrule)
                    {
                        var customCommit = (session.SelectedCompletionSet.SelectionStatus.Completion as SimpleDothtmlCompletion)?.CustomCommit;
                        if (customCommit != null)
                        {
                            customCommit.Commit();
                            completionRequested = customCommit.CompletionTriggerRequested;
                        }
                        else
                        {
                            session.Commit();
                        }

                        var prevChar = textView.TextBuffer.CurrentSnapshot[textView.Caret.Position.BufferPosition];
                        if (typedChar != '=' || prevChar == '\"' || prevChar == '\'')
                        {
                            handled = true;
                        }
                    }
                    else
                    {
                        //if there is no selection, dismiss the session
                        if (!session.IsDismissed)
                        {
                            session.Dismiss();
                        }
                    }
                }
            }

            // pass along the command so the char is added to the buffer
            int retVal = 0;

            if (!handled)
            {
                retVal = nextCommandHandler.Execute(ref pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut);
            }
            if ((nCmdId == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdId == (uint)VSConstants.VSStd2KCmdID.TAB) || completionRequested ||
                (!typedChar.Equals(char.MinValue) && IsTriggerChar(typedChar)))
            {
                if (session == null || session.IsDismissed) // If there is no active session, bring up completion
                {
                    this.TriggerCompletion();
                }
                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);
        }
        /// <summary>
        /// Handles a new command.
        /// </summary>
        /// <param name="CommandGroupGuid">The GUID of the command group.</param>
        /// <param name="CommandID">The command ID.</param>
        /// <param name="ExecOptions">Not used.</param>
        /// <param name="InputArgs">The input arguments of the command.</param>
        /// <param name="OutputArgs">The output arguments of the command.</param>
        /// <returns>A status code, either S_OK on a successful command exection or some other
        /// code that describes what happened if the command failed.</returns>
        public int Exec(ref Guid CommandGroupGuid, uint CommandID, uint ExecOptions, IntPtr InputArgs, IntPtr OutputArgs)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            try
            {
                // If we're in an automation function, we don't actually need to do anything.
                if (VsShellUtilities.IsInAutomationFunction(Provider.ServiceProvider))
                {
                    return(NextCommandHandler.Exec(ref CommandGroupGuid, CommandID, ExecOptions, InputArgs, OutputArgs));
                }

                // Get the character that was just typed (if there was one)
                char typedChar = char.MinValue;
                if (CommandGroupGuid == VSConstants.VSStd2K &&
                    CommandID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
                {
                    typedChar = (char)Marshal.GetObjectForNativeVariant <ushort>(InputArgs);
                }

                // Check if the user just entered a triple slash
                if (typedChar == '/' && Dte != null)
                {
                    if (UserTypedTripleSlash())
                    {
                        Logger.Debug("User entered a triple slash, handling it...");
                        HandleTripleSlash();
                        return(VSConstants.S_OK);
                    }
                }

                // Check if there's an autocomplete session open and the user just tried to accept one
                // of the autocomplete suggestions
                else if (MarkdownCompletionSession?.IsDismissed == false)
                {
                    if (CommandID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                        CommandID == (uint)VSConstants.VSStd2KCmdID.TAB)
                    {
                        if (MarkdownCompletionSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            Logger.Debug("User selected a Markdown header autocompletion suggestion.");
                            MarkdownCompletionSession.Commit();
                            return(VSConstants.S_OK);
                        }
                    }
                }

                // Handle the user pressing enter inside of a comment
                else if (CommandGroupGuid == VSConstants.VSStd2K &&
                         CommandID == (uint)VSConstants.VSStd2KCmdID.RETURN)
                {
                    if (HandleNewlineInCommentBlock())
                    {
                        Logger.Debug("User added a new line to a comment block.");
                        return(VSConstants.S_OK);
                    }
                }

                // If none of the above happened, pass the event onto the regular handler.
                int nextCommandResult = NextCommandHandler.Exec(ref CommandGroupGuid, CommandID, ExecOptions, InputArgs, OutputArgs);

                // Check to see if the user typed "#" so we need to start an autocomplete session
                if (typedChar == '#')
                {
                    string currentLine = TextView.TextSnapshot.GetLineFromPosition(
                        TextView.Caret.Position.BufferPosition.Position).GetText();
                    if (currentLine.TrimStart().StartsWith("/// #"))
                    {
                        // Create a new autocompletion session if there isn't one already
                        Logger.Debug("User entered # on a triple-slashed line, starting a new autocomplete session...");
                        if (MarkdownCompletionSession == null || MarkdownCompletionSession.IsDismissed)
                        {
                            if (StartMarkdownAutocompleteSession())
                            {
                                MarkdownCompletionSession.SelectedCompletionSet.SelectBestMatch();
                                MarkdownCompletionSession.SelectedCompletionSet.Recalculate();
                                return(VSConstants.S_OK);
                            }
                        }
                    }
                }

                // Check if there's an active autocomplete session, and the user just modified the text
                // in the editor
                else if (CommandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                         CommandID == (uint)VSConstants.VSStd2KCmdID.DELETE ||
                         char.IsLetter(typedChar))
                {
                    if (MarkdownCompletionSession?.IsDismissed == false)
                    {
                        MarkdownCompletionSession.SelectedCompletionSet.SelectBestMatch();
                        MarkdownCompletionSession.SelectedCompletionSet.Recalculate();
                        return(VSConstants.S_OK);
                    }
                }

                return(nextCommandResult);
            }
            catch (Exception ex)
            {
                Logger.Error($"Error handling command: {ex.GetType().Name} - {ex.Message}");
                Logger.Trace(ex.StackTrace);
                return(VSConstants.E_FAIL);
            }
        }
        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));
        }
예제 #22
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            try
            {
                if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
                {
                    return(m_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);
                }

                // check for the triple slash
                if (typedChar == '/' && m_dte != null)
                {
                    string currentLine = m_textView.TextSnapshot.GetLineFromPosition(
                        m_textView.Caret.Position.BufferPosition.Position).GetText();
                    if ((currentLine + "/").Trim() == "///")
                    {
                        // Calculate how many spaces
                        string        spaces    = currentLine.Replace(currentLine.TrimStart(), "");
                        TextSelection ts        = m_dte.ActiveDocument.Selection as TextSelection;
                        int           oldLine   = ts.ActivePoint.Line;
                        int           oldOffset = ts.ActivePoint.LineCharOffset;
                        ts.LineDown();
                        ts.EndOfLine();

                        CodeElement   codeElement = null;
                        FileCodeModel fcm         = m_dte.ActiveDocument.ProjectItem.FileCodeModel;
                        if (fcm != null)
                        {
                            codeElement = fcm.CodeElementFromPoint(ts.ActivePoint, vsCMElement.vsCMElementFunction);
                        }

                        if (codeElement != null && codeElement is CodeFunction)
                        {
                            CodeFunction  function = codeElement as CodeFunction;
                            StringBuilder sb       = new StringBuilder("/ <summary>\r\n" + spaces + "/// \r\n" + spaces + "/// </summary>");
                            foreach (CodeElement child in codeElement.Children)
                            {
                                CodeParameter parameter = child as CodeParameter;
                                if (parameter != null)
                                {
                                    sb.AppendFormat("\r\n" + spaces + "/// <param name=\"{0}\"></param>", parameter.Name);
                                }
                            }

                            if (function.Type.AsString != "void")
                            {
                                sb.AppendFormat("\r\n" + spaces + "/// <returns></returns>");
                            }

                            ts.MoveToLineAndOffset(oldLine, oldOffset);
                            ts.Insert(sb.ToString());
                            ts.MoveToLineAndOffset(oldLine, oldOffset);
                            ts.LineDown();
                            ts.EndOfLine();
                            return(VSConstants.S_OK);
                        }
                        else
                        {
                            ts.MoveToLineAndOffset(oldLine, oldOffset);
                            ts.Insert("/ <summary>\r\n" + spaces + "/// \r\n" + spaces + "/// </summary>");
                            ts.MoveToLineAndOffset(oldLine, oldOffset);
                            ts.LineDown();
                            ts.EndOfLine();
                            return(VSConstants.S_OK);
                        }
                    }
                }

                if (m_session != null && !m_session.IsDismissed)
                {
                    // check for a commit character
                    if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                        nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
                        typedChar == '>')
                    {
                        // check for a selection
                        // if the selection is fully selected, commit the current session
                        if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            string selectedCompletion = m_session.SelectedCompletionSet.SelectionStatus.Completion.DisplayText;
                            m_session.Commit();
                            TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection;
                            switch (selectedCompletion)
                            {
                            case "<!-->":
                                ts.CharLeft(false, 3);
                                break;

                            case "<![CDATA[>":
                                ts.CharLeft(false, 3);
                                break;

                            case "<c>":
                                ts.CharLeft(false, 4);
                                break;

                            case "<code>":
                                ts.CharLeft(false, 7);
                                break;

                            case "<example>":
                                ts.CharLeft(false, 10);
                                break;

                            case "<exception>":
                                ts.CharLeft(false, 14);
                                break;

                            case "<include>":
                                ts.CharLeft(false, 21);
                                break;

                            case "<list>":
                                ts.CharLeft(false, 7);
                                break;

                            case "<para>":
                                ts.CharLeft(false, 7);
                                break;

                            case "<param>":
                                ts.CharLeft(false, 10);
                                break;

                            case "<paramref>":
                                ts.CharLeft(false, 13);
                                break;

                            case "<permission>":
                                ts.CharLeft(false, 15);
                                break;

                            case "<remarks>":
                                ts.CharLeft(false, 10);
                                break;

                            case "<returns>":
                                ts.CharLeft(false, 10);
                                break;

                            case "<see>":
                                ts.CharLeft(false, 3);
                                break;

                            case "<seealso>":
                                ts.CharLeft(false, 3);
                                break;

                            case "<typeparam>":
                                ts.CharLeft(false, 14);
                                break;

                            case "<typeparamref>":
                                ts.CharLeft(false, 3);
                                break;

                            case "<value>":
                                ts.CharLeft(false, 8);
                                break;

                            default:
                                break;
                            }

                            // also, don't add the character to the buffer
                            return(VSConstants.S_OK);
                        }
                        else
                        {
                            // if there is no selection, dismiss the session
                            m_session.Dismiss();
                        }
                    }
                }
                else
                {
                    if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN)
                    {
                        string currentLine = m_textView.TextSnapshot.GetLineFromPosition(
                            m_textView.Caret.Position.BufferPosition.Position).GetText();
                        if (currentLine.TrimStart().StartsWith("///"))
                        {
                            TextSelection ts     = m_dte.ActiveDocument.Selection as TextSelection;
                            string        spaces = currentLine.Replace(currentLine.TrimStart(), "");
                            ts.Insert("\r\n" + spaces + "/// ");
                            return(VSConstants.S_OK);
                        }
                    }
                }

                // pass along the command so the char is added to the buffer
                int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                if (typedChar == '<')
                {
                    string currentLine = m_textView.TextSnapshot.GetLineFromPosition(
                        m_textView.Caret.Position.BufferPosition.Position).GetText();
                    if (currentLine.TrimStart().StartsWith("///"))
                    {
                        if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion
                        {
                            if (this.TriggerCompletion())
                            {
                                m_session.SelectedCompletionSet.SelectBestMatch();
                                m_session.SelectedCompletionSet.Recalculate();
                                return(VSConstants.S_OK);
                            }
                        }
                    }
                }
                else if (
                    commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                    commandID == (uint)VSConstants.VSStd2KCmdID.DELETE ||
                    char.IsLetter(typedChar))
                {
                    if (m_session != null && !m_session.IsDismissed) // the completion session is already active, so just filter
                    {
                        m_session.SelectedCompletionSet.SelectBestMatch();
                        m_session.SelectedCompletionSet.Recalculate();
                        return(VSConstants.S_OK);
                    }
                }

                return(retVal);
            }
            catch
            {
            }

            return(VSConstants.E_FAIL);
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
            {
                return(m_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);
            }

            //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 (m_session != null && !m_session.IsDismissed)
                {
                    //if the selection is fully selected, commit the current session
                    if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        m_session.Commit();
                        //also, don't add the character to the buffer
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        //if there is no selection, dismiss the session
                        m_session.Dismiss();
                    }
                }
            }

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

            if ((!typedChar.Equals(char.MinValue) && char.IsLetter(typedChar)) || char.IsWhiteSpace(typedChar)) //||typedChar=='<'
            {
                if (m_session == null || m_session.IsDismissed)                                                 // If there is no active session, bring up completion
                {
                    if (this.TriggerCompletion() && m_session != null)
                    {
                        m_session.Filter();
                    }
                }
                else     //the completion session is already active, so just filter
                {
                    m_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 (m_session != null && !m_session.IsDismissed)
                {
                    m_session.Filter();
                }
                handled = true;
            }
            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
예제 #24
0
        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);
            }

            if (typedChar == '.')
            {
                Console.WriteLine();
            }

            //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)
                    {
                        if (
                            typedChar != ':' &&
                            (typedChar != '.' || !_session.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.Contains('.')))
                        {
                            _session.Commit();
                            //also, don't add the character to the buffer
                            return(VSConstants.S_OK);
                        }
                        else
                        {
                            nCmdID = (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD;
                        }
                    }
                    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  = VSConstants.S_OK;
            bool handled = false;

            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD ||
                (!typedChar.Equals(char.MinValue) &&
                 (char.IsLetterOrDigit(typedChar) || typedChar == '<' || typedChar == ' ' || typedChar == '.' || typedChar == ':')))
            {
                if (typedChar != '\0')
                {
                    if (typedChar == '.' || typedChar == ':' || typedChar == '<')
                    {
                        if (!_textView.Selection.IsEmpty)
                        {
                            foreach (var span in _textView.Selection.SelectedSpans.OrderByDescending(x => x.Start))
                            {
                                _textView.TextBuffer.Replace(span, "");
                            }
                        }
                        _textView.TextBuffer.Insert(_textView.Caret.Position.BufferPosition.Position,
                                                    typedChar.ToString());
                    }
                    else
                    {
                        retVal = _realCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                    }
                }
                if (_session == null || _session.IsDismissed)
                // If there is no active session, bring up completion
                {
                    TriggerCompletion();
                    if (typedChar != '<' && typedChar != 0 && _session != null)
                    {
                        _session.Filter();
                    }
                }
                else
                {
                    _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();
                }
                retVal  = _nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                handled = true;
            }

            else
            {
                retVal = _nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            }
            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
        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));
            }

            uint commandID = nCmdID;
            char typedChar = char.MinValue;

            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }
            // return and tab command commit the session and return
            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            {
                if (_session != null && !_session.IsDismissed)
                {
                    if (_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        _session.Commit();
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        _session.Dismiss();
                    }
                }
            }
            // whitespace and punctuation commit the session
            if (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar))
            {
                if (_session != null && !_session.IsDismissed)
                {
                    if (_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        _session.Commit();
                    }
                    else
                    {
                        _session.Dismiss();
                    }
                }
            }

            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)
                {
                    this.TriggerCompletion();
                    if (_session != null)
                    {
                        _session.Filter();
                    }
                }
                else
                {
                    _session.Filter();
                }
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                if (_session != null && _session.IsDismissed)
                {
                    _session.Filter();
                }
                handled = true;
            }
            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
예제 #26
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (int)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                var ch = (char)(ushort)System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(pvaIn);

                if (_activeSession != null && !_activeSession.IsDismissed)
                {
                    if (_activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        var completion = _activeSession.SelectedCompletionSet.SelectionStatus.Completion;

                        string committedBy = String.Empty;
                        if (_activeSession.SelectedCompletionSet.Moniker == CompletionSource.NodejsRequireCompletionSetMoniker)
                        {
                            if (completion.InsertionText.StartsWith("'"))   // require(
                            {
                                committedBy = ")";
                            }
                            else if (completion.InsertionText.EndsWith("'"))     // require('
                            {
                                committedBy = "'";
                            }
                            else if (completion.InsertionText.EndsWith("\""))     // require("
                            {
                                committedBy = "\"";
                            }
                        }
                        else
                        {
                            committedBy = NodejsPackage.Instance != null && NodejsPackage.Instance.IntellisenseOptionsPage.OnlyTabOrEnterToCommit ?
                                          string.Empty :
                                          NodejsConstants.DefaultIntellisenseCompletionCommittedBy;
                        }

                        if (committedBy.IndexOf(ch) != -1)
                        {
                            _activeSession.Commit();
                            if ((completion.InsertionText.EndsWith("'") && ch == '\'') ||
                                (completion.InsertionText.EndsWith("\"") && ch == '"'))
                            {
                                // https://nodejstools.codeplex.com/workitem/960
                                // ' triggers the completion, but we don't want to insert the quote.
                                return(VSConstants.S_OK);
                            }
                        }
                    }
                    else if (_activeSession.SelectedCompletionSet.Moniker.Equals(CompletionSource.NodejsRequireCompletionSetMoniker) && !IsRequireIdentifierChar(ch))
                    {
                        _activeSession.Dismiss();
                    }
                    else if (!_activeSession.SelectedCompletionSet.Moniker.Equals(CompletionSource.NodejsRequireCompletionSetMoniker) && !IsIdentifierChar(ch))
                    {
                        _activeSession.Dismiss();
                    }
                }

                int res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                if (_activeSession == null || !_activeSession.SelectedCompletionSet.Moniker.Equals(CompletionSource.NodejsRequireCompletionSetMoniker))
                {
                    //Only process the char if we are not in a require completion
                    HandleChar((char)(ushort)System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(pvaIn));
                }

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

                return(res);
            }

            if (_activeSession != null)
            {
                if (pguidCmdGroup == VSConstants.VSStd2K)
                {
                    switch ((VSConstants.VSStd2KCmdID)nCmdID)
                    {
                    case VSConstants.VSStd2KCmdID.RETURN:
                        if (/*NodejsPackage.Instance.AdvancedEditorOptionsPage.EnterCommitsIntellisense*/ true &&
                            !_activeSession.IsDismissed &&
                            _activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            // If the user has typed all of the characters as the completion and presses
                            // enter we should dismiss & let the text editor receive the enter.  For example
                            // when typing "import sys[ENTER]" completion starts after the space.  After typing
                            // sys the user wants a new line and doesn't want to type enter twice.

                            bool enterOnComplete = /*NodejsPackage.Instance.AdvancedEditorOptionsPage.AddNewLineAtEndOfFullyTypedWord*/ true &&
                                                   EnterOnCompleteText();

                            _activeSession.Commit();

                            if (!enterOnComplete)
                            {
                                return(VSConstants.S_OK);
                            }
                        }
                        else
                        {
                            _activeSession.Dismiss();
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.TAB:
                        if (!_activeSession.IsDismissed)
                        {
                            _activeSession.Commit();
                            return(VSConstants.S_OK);
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.BACKSPACE:
                    case VSConstants.VSStd2KCmdID.DELETE:
                    case VSConstants.VSStd2KCmdID.DELETEWORDLEFT:
                    case VSConstants.VSStd2KCmdID.DELETEWORDRIGHT:
                        int res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                        if (_activeSession != null && !_activeSession.IsDismissed)
                        {
                            _activeSession.Filter();
                        }
                        return(res);
                    }
                }
            }
            else if (_sigHelpSession != null)
            {
                if (pguidCmdGroup == VSConstants.VSStd2K)
                {
                    switch ((VSConstants.VSStd2KCmdID)nCmdID)
                    {
                    case VSConstants.VSStd2KCmdID.BACKSPACE:
                        bool fDeleted = Backspace();
                        if (fDeleted)
                        {
                            return(VSConstants.S_OK);
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.LEFT:
                        _editOps.MoveToPreviousCharacter(false);
                        UpdateCurrentParameter();
                        return(VSConstants.S_OK);

                    case VSConstants.VSStd2KCmdID.RIGHT:
                        _editOps.MoveToNextCharacter(false);
                        UpdateCurrentParameter();
                        return(VSConstants.S_OK);

                    case VSConstants.VSStd2KCmdID.HOME:
                    case VSConstants.VSStd2KCmdID.BOL:
                    case VSConstants.VSStd2KCmdID.BOL_EXT:
                    case VSConstants.VSStd2KCmdID.EOL:
                    case VSConstants.VSStd2KCmdID.EOL_EXT:
                    case VSConstants.VSStd2KCmdID.END:
                    case VSConstants.VSStd2KCmdID.WORDPREV:
                    case VSConstants.VSStd2KCmdID.WORDPREV_EXT:
                    case VSConstants.VSStd2KCmdID.DELETEWORDLEFT:
                        _sigHelpSession.Dismiss();
                        _sigHelpSession = null;
                        break;
                    }
                }
            }
            if (pguidCmdGroup == VSConstants.VSStd2K)
            {
                switch ((VSConstants.VSStd2KCmdID)nCmdID)
                {
                case VSConstants.VSStd2KCmdID.QUICKINFO:
                    TriggerQuickInfo();
                    return(VSConstants.S_OK);

                case VSConstants.VSStd2KCmdID.PARAMINFO:
                    TriggerSignatureHelp();
                    return(VSConstants.S_OK);

                case VSConstants.VSStd2KCmdID.RETURN:
                    if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.EndCurrentExpansion(false)))
                    {
                        return(VSConstants.S_OK);
                    }
                    break;

                case VSConstants.VSStd2KCmdID.TAB:
                    if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.NextField()))
                    {
                        return(VSConstants.S_OK);
                    }
                    if (_textView.Selection.IsEmpty && _textView.Caret.Position.BufferPosition > 0)
                    {
                        if (TryTriggerExpansion())
                        {
                            return(VSConstants.S_OK);
                        }
                    }
                    break;

                case VSConstants.VSStd2KCmdID.BACKTAB:
                    if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.PreviousField()))
                    {
                        return(VSConstants.S_OK);
                    }
                    break;

                case VSConstants.VSStd2KCmdID.SURROUNDWITH:
                case VSConstants.VSStd2KCmdID.INSERTSNIPPET:
                    TriggerSnippet(nCmdID);
                    return(VSConstants.S_OK);

                case VSConstants.VSStd2KCmdID.SHOWMEMBERLIST:
                case VSConstants.VSStd2KCmdID.COMPLETEWORD:
                    ForceCompletions = true;
                    try {
                        TriggerCompletionSession((VSConstants.VSStd2KCmdID)nCmdID == VSConstants.VSStd2KCmdID.COMPLETEWORD &&
                                                 !NodejsPackage.Instance.IntellisenseOptionsPage.OnlyTabOrEnterToCommit);
                    } finally {
                        ForceCompletions = false;
                    }
                    return(VSConstants.S_OK);
                }
            }
            return(_oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
 void IWordCompletionSession.Commit()
 {
     _completionSession.Commit();
 }
예제 #28
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (int)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                var ch = (char)(ushort)System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(pvaIn);

                if (_activeSession != null && !_activeSession.IsDismissed)
                {
                    if (_activeSession.SelectedCompletionSet != null &&
                        _activeSession.SelectedCompletionSet.SelectionStatus.IsSelected &&
                        _provider.PythonService.AdvancedOptions.CompletionCommittedBy.IndexOf(ch) != -1)
                    {
                        _activeSession.Commit();
                    }
                    else if (!IsIdentifierChar(ch))
                    {
                        _activeSession.Dismiss();
                    }
                }

                int res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

                HandleChar((char)(ushort)System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(pvaIn));

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

                return(res);
            }

            if (_activeSession != null)
            {
                if (pguidCmdGroup == VSConstants.VSStd2K)
                {
                    switch ((VSConstants.VSStd2KCmdID)nCmdID)
                    {
                    case VSConstants.VSStd2KCmdID.RETURN:
                        if (_provider.PythonService.AdvancedOptions.EnterCommitsIntellisense &&
                            !_activeSession.IsDismissed &&
                            _activeSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            // If the user has typed all of the characters as the completion and presses
                            // enter we should dismiss & let the text editor receive the enter.  For example
                            // when typing "import sys[ENTER]" completion starts after the space.  After typing
                            // sys the user wants a new line and doesn't want to type enter twice.

                            bool enterOnComplete = _provider.PythonService.AdvancedOptions.AddNewLineAtEndOfFullyTypedWord &&
                                                   EnterOnCompleteText();

                            _activeSession.Commit();

                            if (!enterOnComplete)
                            {
                                return(VSConstants.S_OK);
                            }
                        }
                        else
                        {
                            _activeSession.Dismiss();
                        }

                        break;

                    case VSConstants.VSStd2KCmdID.TAB:
                        if (!_activeSession.IsDismissed)
                        {
                            _activeSession.Commit();
                            return(VSConstants.S_OK);
                        }

                        break;

                    case VSConstants.VSStd2KCmdID.BACKSPACE:
                    case VSConstants.VSStd2KCmdID.DELETE:
                    case VSConstants.VSStd2KCmdID.DELETEWORDLEFT:
                    case VSConstants.VSStd2KCmdID.DELETEWORDRIGHT:
                        int res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                        if (_activeSession != null && !_activeSession.IsDismissed)
                        {
                            _activeSession.Filter();
                        }
                        return(res);
                    }
                }
            }
            else if (_sigHelpSession != null)
            {
                if (pguidCmdGroup == VSConstants.VSStd2K)
                {
                    switch ((VSConstants.VSStd2KCmdID)nCmdID)
                    {
                    case VSConstants.VSStd2KCmdID.BACKSPACE:
                        bool fDeleted = Backspace();
                        if (fDeleted)
                        {
                            return(VSConstants.S_OK);
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.LEFT:
                        _editOps.MoveToPreviousCharacter(false);
                        UpdateCurrentParameter();
                        return(VSConstants.S_OK);

                    case VSConstants.VSStd2KCmdID.RIGHT:
                        _editOps.MoveToNextCharacter(false);
                        UpdateCurrentParameter();
                        return(VSConstants.S_OK);

                    case VSConstants.VSStd2KCmdID.HOME:
                    case VSConstants.VSStd2KCmdID.BOL:
                    case VSConstants.VSStd2KCmdID.BOL_EXT:
                    case VSConstants.VSStd2KCmdID.EOL:
                    case VSConstants.VSStd2KCmdID.EOL_EXT:
                    case VSConstants.VSStd2KCmdID.END:
                    case VSConstants.VSStd2KCmdID.WORDPREV:
                    case VSConstants.VSStd2KCmdID.WORDPREV_EXT:
                    case VSConstants.VSStd2KCmdID.DELETEWORDLEFT:
                        _sigHelpSession.Dismiss();
                        _sigHelpSession = null;
                        break;
                    }
                }
            }
            else
            {
                if (pguidCmdGroup == VSConstants.VSStd2K)
                {
                    switch ((VSConstants.VSStd2KCmdID)nCmdID)
                    {
                    case VSConstants.VSStd2KCmdID.RETURN:
                        if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.EndCurrentExpansion(false)))
                        {
                            return(VSConstants.S_OK);
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.TAB:
                        if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.NextField()))
                        {
                            return(VSConstants.S_OK);
                        }
                        if (_textView.Selection.IsEmpty && _textView.Caret.Position.BufferPosition > 0)
                        {
                            if (TryTriggerExpansion())
                            {
                                return(VSConstants.S_OK);
                            }
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.BACKTAB:
                        if (_expansionMgr != null && _expansionClient.InSession && ErrorHandler.Succeeded(_expansionClient.PreviousField()))
                        {
                            return(VSConstants.S_OK);
                        }
                        break;

                    case VSConstants.VSStd2KCmdID.SURROUNDWITH:
                    case VSConstants.VSStd2KCmdID.INSERTSNIPPET:
                        TriggerSnippet(nCmdID);
                        return(VSConstants.S_OK);
                    }
                }
            }

            return(_oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            uint cmdID     = nCmdID;
            char typedChar = char.MinValue;

            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }

            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                cmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            {
                if (completionSession != null && !completionSession.IsDismissed)
                {
                    if (completionSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        completionSession.Commit();
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        completionSession.Dismiss();
                    }
                }
            }

            int returnValue = nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

            bool isHandled = false;

            if (!typedChar.Equals(char.MinValue))
            {
                if (completionSession == null || completionSession.IsDismissed)
                {
                    TriggerCompletion();
                    if (completionSession != null)
                    {
                        completionSession.Filter();
                    }
                }
                else
                {
                    completionSession.Filter();
                }

                isHandled = true;
            }
            else if (cmdID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     cmdID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                if (completionSession != null && !completionSession.IsDismissed)
                {
                    completionSession.Filter();
                }

                isHandled = true;
            }

            if (isHandled)
            {
                return(VSConstants.S_OK);
            }

            return(returnValue);
        }
        bool Commit(bool force)
        {
            if (_currentSession == null)
            {
                return(false);
            }

            if (!_currentSession.SelectedCompletionSet.SelectionStatus.IsSelected && !force)
            {
                _currentSession.Dismiss();
                return(false);
            }
            else
            {
                string moniker = _currentSession.SelectedCompletionSet.Moniker;
                _currentSession.Commit();

                if (!EditorConfigPackage.CompletionOptions.AutoInsertDelimiters)
                {
                    return(true);
                }

                SnapshotPoint     position = TextView.Caret.Position.BufferPosition;
                ITextSnapshotLine line     = TextView.TextBuffer.CurrentSnapshot.GetLineFromPosition(position);
                string            lineText = line.GetText();

                if (moniker == "keyword" && !lineText.Contains("="))
                {
                    TextView.TextBuffer.Insert(position, " = ");

                    // Contains placeholders
                    int start = lineText.IndexOf('<');
                    int end   = lineText.IndexOf('>');

                    if (start > -1 && start < end)
                    {
                        var span = new SnapshotSpan(TextView.TextBuffer.CurrentSnapshot, Span.FromBounds(line.Start + start, line.Start + end + 1));
                        TextView.Selection.Select(span, false);
                        TextView.Caret.MoveTo(span.Start);
                        return(true);
                    }

                    if (EditorConfigPackage.Language.Preferences.AutoListMembers)
                    {
                        StartSession();
                    }
                }
                else if (moniker == "value" && !lineText.Contains(":"))
                {
                    var      document = EditorConfigDocument.FromTextBuffer(TextView.TextBuffer);
                    Property prop     = document.PropertyAtPosition(position - 1);

                    if (SchemaCatalog.TryGetKeyword(prop.Keyword.Text, out Keyword keyword) && prop.Value != null)
                    {
                        if (keyword.RequiresSeverity)
                        {
                            TextView.TextBuffer.Insert(position, ":");

                            if (EditorConfigPackage.Language.Preferences.AutoListMembers)
                            {
                                StartSession();
                            }
                        }
                    }
                }

                return(true);
            }
        }
        public int Exec(ref System.Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, System.IntPtr pvaIn, System.IntPtr pvaOut)
        {
            if (pguidCmdGroup == VSConstants.VSStd2K)
            {
                int res;

                switch ((VSConstants.VSStd2KCmdID)nCmdID)
                {
                case VSConstants.VSStd2KCmdID.TYPECHAR:
                    var ch = (char)(ushort)System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(pvaIn);
                    if (_curSession != null && !_curSession.IsDismissed)
                    {
                        if (_curSession.SelectedCompletionSet.SelectionStatus.IsSelected &&
                            IsCompletionChar(ch))
                        {
                            _curSession.Commit();
                        }
                    }

                    res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                    switch (ch)
                    {
                    case '<':
                        if (_curSession != null)
                        {
                            _curSession.Dismiss();
                        }
                        if (ErrorHandler.Succeeded(res))
                        {
                            _curSession = CompletionBroker.TriggerCompletion(_textView);
                            if (_curSession != null)
                            {
                                _curSession.Dismissed += CurSessionDismissedOrCommitted;
                                _curSession.Committed += CurSessionDismissedOrCommitted;
                            }
                        }
                        return(res);
                    }

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

                    return(res);

                case VSConstants.VSStd2KCmdID.BACKSPACE:
                    res = _oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
                    if (_curSession != null && !_curSession.IsDismissed)
                    {
                        _curSession.Filter();
                    }
                    return(res);

                case VSConstants.VSStd2KCmdID.RETURN:
                case VSConstants.VSStd2KCmdID.TAB:
                    if (_curSession != null && !_curSession.IsDismissed)
                    {
                        _curSession.Commit();
                        return(VSConstants.S_OK);
                    }
                    break;
                }
            }

            return(_oldTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
예제 #32
0
        // TODO: clean it up
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
            {
                return(m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }

            //var tid = pguidCmdGroup;
            //var t = typeof(VSConstants).GetNestedTypes().FirstOrDefault(tt => tt.GUID == tid);
            //if (t.IsEnum)
            //{
            //    try
            //    {
            //        Debug.Print("cmd: {0}: {1}", t.Name, Enum.ToObject(t, nCmdID));
            //    }
            //    catch { }
            //}

            if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97 && (
                    nCmdID == (int)VSConstants.VSStd97CmdID.GotoDefn || nCmdID == (int)VSConstants.VSStd97CmdID.FindReferences
                    ))
            {
                var doc = this.DocumentDataLoader.DocumentData;
                if (doc == null)
                {
                    this.DocumentDataLoader.ForceReload();
                    doc = this.DocumentDataLoader.DocumentData;
                }

                if (doc != null)
                {
                    var snapshot = this.DocumentDataLoader.CurrentSnapshot;

                    var pos          = m_textView.Caret.Position.BufferPosition;
                    var line         = pos.GetContainingLine();
                    var lineNumber   = line.LineNumber;
                    var linePosition = pos.Position - line.Start.Position;

                    var text = doc.FindTextAt(lineNumber, linePosition);
                    var attr = text?.ParentNode as MyXmlAttribute;

                    if (attr != null)
                    {
                        if (nCmdID == (int)VSConstants.VSStd97CmdID.GotoDefn)
                        {
                            if (attr.ReferencedKeyPartData != null && attr.ReferencedKeyPartData.TryGetValueDef(attr.Value, out var targetAttr))
                            {
                                var targetText = targetAttr.ChildNodes.OfType <MyXmlText>().FirstOrDefault();

                                if (targetText != null)
                                {
                                    var targetLine     = this.DocumentDataLoader.CurrentSnapshot.GetLineFromLineNumber(targetText.TextLocation.Line - 1);
                                    var targetPosition = targetLine.Start.Position + targetText.TextLocation.Column - 1;

                                    m_textView.Caret.MoveTo(new SnapshotPoint(this.DocumentDataLoader.CurrentSnapshot, targetPosition));
                                    m_textView.Caret.EnsureVisible();
                                }
                            }
                        }
                        else if (nCmdID == (int)VSConstants.VSStd97CmdID.FindReferences)
                        {
                            MyXmlAttribute defAttr;
                            if (attr.ReferencedKeyPartData == null || !attr.ReferencedKeyPartData.TryGetValueDef(attr.Value, out defAttr))
                            {
                                defAttr = attr;
                            }

                            var defLocation = defAttr.ChildNodes.OfType <MyXmlText>().FirstOrDefault()?.TextLocation ?? defAttr.TextLocation;

                            var refs = defAttr.References;
                            if (refs != null)
                            {
                                IVsOutputWindow outWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;

                                // Use e.g. Tools -> Create GUID to make a stable, but unique GUID for your pane.
                                // Also, in a real project, this should probably be a static constant, and not a local variable
                                Guid   customGuid  = new Guid("D9090DD3-1BA3-4702-9697-C534D95810A9");
                                string customTitle = "Xml Key References";
                                outWindow.CreatePane(ref customGuid, customTitle, 1, 1);

                                IVsOutputWindowPane customPane;
                                outWindow.GetPane(ref customGuid, out customPane);

                                ITextDocument document;
                                var           filePath = m_provider.TextDocumentFactoryService.TryGetTextDocument(m_textView.TextDataModel.DocumentBuffer, out document) ? document.FilePath : "Current document";

                                customPane.OutputString("Searching references to key " + attr.Value + " in " + filePath + " at " + DateTime.Now + Environment.NewLine);
                                customPane.Activate(); // Brings this pane into view

                                customPane.OutputString($"{filePath}({defLocation.Line},{defLocation.Column}): Definition: {snapshot.GetLineFromLineNumber(defLocation.Line - 1).GetText()}{Environment.NewLine}");
                                foreach (var refAttr in defAttr.References ?? new MyXmlAttribute[0])
                                {
                                    var itemLocation = refAttr.ChildNodes.OfType <MyXmlText>().FirstOrDefault()?.TextLocation ?? refAttr.TextLocation;
                                    customPane.OutputString($"{filePath}({itemLocation.Line},{itemLocation.Column}): Reference: {snapshot.GetLineFromLineNumber(itemLocation.Line - 1).GetText()}{Environment.NewLine}");
                                }

                                customPane.OutputString($"Finished.{Environment.NewLine}");

                                customPane.OutputString(Environment.NewLine);
                                customPane.OutputString(Environment.NewLine);

                                const string vsWindowKindOutput = "{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}";
                                DTE          dte = Package.GetGlobalService(typeof(SDTE)) as DTE;
                                Window       win = dte.Windows.Item(vsWindowKindOutput);
                                win.Visible = true;
                                win.Activate();
                            }
                        }
                    }
                }
            }

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

            //check for a commit character
            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
                typedChar == '"')
            {
                //check for a selection
                if (m_session != null && !m_session.IsDismissed)
                {
                    //if the selection is fully selected, commit the current session
                    if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        m_session.Commit();
                        //also, don't add the character to the buffer

                        // this.DocumentDataLoader.ScheduleReloading(XmlDocumentLoader.EditTimeout);
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        //if there is no selection, dismiss the session
                        m_session.Dismiss();
                    }
                }
            }

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

            if ((!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar)) ||
                (pguidCmdGroup == VSConstants.VSStd2K && (nCmdID == (uint)VSConstants.VSStd2KCmdID.AUTOCOMPLETE ||
                                                          nCmdID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD ||
                                                          nCmdID == (uint)VSConstants.VSStd2KCmdID.SHOWMEMBERLIST
                                                          )))
            {
                if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion
                {
                    this.TriggerCompletion();
                    if (m_session != null && !((nCmdID == (uint)VSConstants.VSStd2KCmdID.AUTOCOMPLETE ||
                                                nCmdID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD ||
                                                nCmdID == (uint)VSConstants.VSStd2KCmdID.SHOWMEMBERLIST
                                                ))) // TODO: wtf?
                    {
                        m_session.Filter();
                    }
                }
                else    //the completion session is already active, so just filter
                {
                    m_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 (m_session != null && !m_session.IsDismissed)
                {
                    m_session.Filter();
                }
                handled = true;
            }

            //if (
            //    (pguidCmdGroup == VSConstants.VSStd2K && (
            //        nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR||
            //        nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
            //        nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
            //        nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN
            //    )) || (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97 && (
            //        nCmdID == (uint)VSConstants.VSStd97CmdID.Cut ||
            //        nCmdID == (uint)VSConstants.VSStd97CmdID.Paste ||
            //        nCmdID == (uint)VSConstants.VSStd97CmdID.Undo ||
            //        nCmdID == (uint)VSConstants.VSStd97CmdID.Redo
            //    ))
            //    )
            //    this.DocumentDataLoader.ScheduleReloading(XmlDocumentLoader.EditTimeout);

            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
        internal void TriggerCompletionSession(bool completeWord) {
            Dismiss();

            _activeSession = CompletionBroker.TriggerCompletion(_textView);

            if (_activeSession != null) {
                FuzzyCompletionSet set;
                if (completeWord &&
                    _activeSession.CompletionSets.Count == 1 &&
                    (set = _activeSession.CompletionSets[0] as FuzzyCompletionSet) != null &&
                    set.SelectSingleBest()) {
                    _activeSession.Commit();
                    _activeSession = null;
                } else {
                    _activeSession.Filter();
                    _activeSession.Dismissed += OnCompletionSessionDismissedOrCommitted;
                    _activeSession.Committed += OnCompletionSessionDismissedOrCommitted;
                }
            }
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (VsShellUtilities.IsInAutomationFunction(_provider.ServiceProvider))
            {
                return(_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }

            uint commandID = nCmdID;
            char typedChar = char.MinValue;

            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }

            if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
            {
                if (session != null && !session.IsDismissed)
                {
                    if (session.SelectedCompletionSet.SelectionStatus.IsSelected)
                    {
                        session.Commit();
                        MoveCaret();
                        return(VSConstants.S_OK);
                    }
                    else
                    {
                        session.Dismiss();
                    }
                }
            }

            int retVal = _nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

            bool handled = false;

            if ((!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar)) || typedChar.Equals('<'))
            {
                if (session == null || session.IsDismissed)
                {
                    TriggerCompletion();
                    session.Filter();
                }
                else
                {
                    session.Filter();
                }
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                if (session != null && !session.IsDismissed)
                {
                    session.Filter();
                }
                handled = true;
            }

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

            return(retVal);
        }