/// <summary>
        /// Try and process the KeyInput from the Exec method.  This method decides whether or not
        /// a key should be processed directly by IVimBuffer or if should be going through
        /// IOleCommandTarget.  Generally the key is processed by IVimBuffer but for many intellisense
        /// scenarios we want the key to be routed to Visual Studio directly.  Issues to consider
        /// here are ...
        ///
        ///  - How should the KeyInput participate in Macro playback?
        ///  - Does both VsVim and Visual Studio need to process the key (Escape mainly)
        ///
        /// </summary>
        private bool TryProcessWithBuffer(KeyInput keyInput)
        {
            // If the IVimBuffer can't process it then it doesn't matter
            if (!_vimBuffer.CanProcess(keyInput))
            {
                return(false);
            }

            // In the middle of a word completion session let insert mode handle the input.  It's
            // displaying the intellisense itself and this method is meant to let custom intellisense
            // operate normally
            if (_vimBuffer.ModeKind == ModeKind.Insert && _vimBuffer.InsertMode.ActiveWordCompletionSession.IsSome())
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            // If we are in a peek definition window and normal mode we need to let the Escape key
            // pass on to the next command target.  This is necessary to close the peek definition
            // window
            if (_vimBuffer.ModeKind == ModeKind.Normal &&
                _textView.IsPeekView() &&
                keyInput == KeyInputUtil.EscapeKey)
            {
                return(false);
            }

            // The only time we actively intercept keys and route them through IOleCommandTarget
            // is when one of the IDisplayWindowBroker windows is active
            //
            // In those cases if the KeyInput is a command which should be handled by the
            // display window we route it through IOleCommandTarget to get the proper
            // experience for those features
            if (!_broker.IsAnyDisplayActive())
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            // Next we need to consider here are Key mappings.  The CanProcess and Process APIs
            // will automatically map the KeyInput under the hood at the IVimBuffer level but
            // not at the individual IMode.  Have to manually map here and test against the
            // mapped KeyInput
            if (!TryGetSingleMapping(keyInput, out KeyInput mapped))
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            bool handled;

            if (IsDisplayWindowKey(mapped))
            {
                // If the key which actually needs to be processed is a display window key, say
                // down, up, etc..., then forward it on to the next IOleCommandTarget.  It is responsible
                // for mapping that key to action against the display window
                handled = ErrorHandler.Succeeded(_nextOleCommandTarget.Exec(mapped));
            }
            else
            {
                // Intentionally using keyInput here and not mapped.  Process will do mapping on the
                // provided input hence we should be using the original keyInput here not mapped
                handled = _vimBuffer.Process(keyInput).IsAnyHandled;
            }

            // The Escape key should always dismiss the active completion session.  However Vim
            // itself is mostly ignorant of display windows and typically won't dismiss them
            // as part of processing Escape (one exception is insert mode).  Dismiss it here if
            // it's still active
            if (mapped.Key == VimKey.Escape && _broker.IsAnyDisplayActive())
            {
                _broker.DismissDisplayWindows();
            }

            return(handled);
        }
Example #2
0
        /// <summary>
        /// Try and process the KeyInput from the Exec method.  This method decides whether or not
        /// a key should be processed directly by IVimBuffer or if should be going through
        /// IOleCommandTarget.  Generally the key is processed by IVimBuffer but for many intellisense
        /// scenarios we want the key to be routed to Visual Studio directly.  Issues to consider
        /// here are ...
        ///
        ///  - How should the KeyInput participate in Macro playback?
        ///  - Does both VsVim and Visual Studio need to process the key (Escape mainly)
        ///
        /// </summary>
        private bool TryProcessWithBuffer(KeyInput keyInput)
        {
            // If the IVimBuffer can't process it then it doesn't matter
            if (!_vimBuffer.CanProcess(keyInput))
            {
                return(false);
            }

            // In the middle of a word completion session let insert mode handle the input.  It's
            // displaying the intellisense itself and this method is meant to let custom intellisense
            // operate normally
            if (_vimBuffer.ModeKind == ModeKind.Insert && _vimBuffer.InsertMode.ActiveWordCompletionSession.IsSome())
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            // The only time we actively intercept keys and route them through IOleCommandTarget
            // is when one of the IDisplayWindowBroker windows is active
            //
            // In those cases if the KeyInput is a command which should be handled by the
            // display window we route it through IOleCommandTarget to get the proper
            // experience for those features
            if (!_broker.IsAnyDisplayActive())
            {
                // The one exception to this rule is R#.  We can't accurately determine if
                // R# has intellisense active or not so we have to pretend like it always
                // does.  We limit this to insert mode only though.
                if (!_resharperUtil.IsInstalled || _vimBuffer.ModeKind != ModeKind.Insert)
                {
                    return(_vimBuffer.Process(keyInput).IsAnyHandled);
                }
            }

            // Next we need to consider here are Key mappings.  The CanProcess and Process APIs
            // will automatically map the KeyInput under the hood at the IVimBuffer level but
            // not at the individual IMode.  Have to manually map here and test against the
            // mapped KeyInput
            KeyInput mapped;

            if (!TryGetSingleMapping(keyInput, out mapped))
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            // If the key actually being processed is a display window key and the display window
            // is active then we allow IOleCommandTarget to control the key
            if (IsDisplayWindowKey(mapped))
            {
                return(false);
            }

            var handled = _vimBuffer.Process(keyInput).IsAnyHandled;

            // The Escape key should always dismiss the active completion session.  However Vim
            // itself is mostly ignorant of display windows and typically won't dismiss them
            // as part of processing Escape (one exception is insert mode).  Dismiss it here if
            // it's still active
            if (mapped.Key == VimKey.Escape && _broker.IsAnyDisplayActive())
            {
                _broker.DismissDisplayWindows();
            }

            return(handled);
        }