Exemplo n.º 1
0
        /// <summary>
        /// Try and custom process the given InsertCommand when it's appropriate to override
        /// with Visual Studio specific behavior
        /// </summary>
        public bool TryCustomProcess(InsertCommand command)
        {
            var oleCommandData = OleCommandData.Empty;

            try
            {
                if (!TryGetOleCommandData(command, out oleCommandData))
                {
                    // Not a command that we custom process
                    return(false);
                }

                if (_vim.InBulkOperation && !command.IsInsertNewLine)
                {
                    // If we are in the middle of a bulk operation we don't want to forward any
                    // input to IOleCommandTarget because it will trigger actions like displaying
                    // Intellisense.  Definitely don't want intellisense popping up during say a
                    // repeat of a 'cw' operation or macro.
                    //
                    // The one exception to this rule though is the Enter key.  Every single language
                    // formats Enter in a special way that we absolutely want to preserve in a change
                    // or macro operation.  Go ahead and let it go through here and we'll dismiss
                    // any intellisense which pops up as a result
                    return(false);
                }

                var versionNumber = _textBuffer.CurrentSnapshot.Version.VersionNumber;
                int hr            = _nextTarget.Exec(oleCommandData);

                // Whether or not an Exec succeeded is a bit of a heuristic.  IOleCommandTarget implementations like
                // C++ will return E_ABORT if Intellisense failed but the character was actually inserted into
                // the ITextBuffer.  VsVim really only cares about the character insert.  However we must also
                // consider cases where the character successfully resulted in no action as a success
                return(ErrorHandler.Succeeded(hr) || versionNumber < _textBuffer.CurrentSnapshot.Version.VersionNumber);
            }
            finally
            {
                if (oleCommandData != null)
                {
                    oleCommandData.Dispose();
                }

                if (_vim.InBulkOperation && _broker.IsCompletionActive)
                {
                    _broker.DismissDisplayWindows();
                }
            }
        }
Exemplo n.º 2
0
 public void DismissDisplayWindows1()
 {
     _quickInfoBroker.Setup(x => x.IsQuickInfoActive(_textView.Object)).Returns(true).Verifiable();
     _quickInfoBroker.Setup(x => x.GetSessions(_textView.Object)).Returns(new List <IQuickInfoSession>().AsReadOnly()).Verifiable();
     _broker.DismissDisplayWindows();
     _quickInfoBroker.Verify();
 }
Exemplo n.º 3
0
        /// <summary>
        /// Try and custom process the given InsertCommand when it's appropriate to override
        /// with Visual Studio specific behavior
        /// </summary>
        public bool TryCustomProcess(InsertCommand command)
        {
            // Don't want to let VS process insert commands during clean macro recording.  Doing so
            // will pop up UI, auto complete braces, etc ...  which interfere with recording.
            if (_vim.MacroRecorder.IsRecording && _vimApplicationSettings.CleanMacros)
            {
                return(false);
            }

            VimTrace.TraceInfo($"TryCustomProcess {command} and completion {_broker.IsCompletionActive}");

            var oleCommandData = OleCommandData.Empty;

            try
            {
                if (_vim.InBulkOperation && !command.IsInsertNewLine)
                {
                    // If we are in the middle of a bulk operation we don't want to forward any
                    // input to IOleCommandTarget because it will trigger actions like displaying
                    // Intellisense.  Definitely don't want intellisense popping up during say a
                    // repeat of a 'cw' operation or macro.
                    //
                    // The one exception to this rule though is the Enter key.  Every single language
                    // formats Enter in a special way that we absolutely want to preserve in a change
                    // or macro operation.  Go ahead and let it go through here and we'll dismiss
                    // any intellisense which pops up as a result
                    return(false);
                }

                if (!_vimApplicationSettings.UseEditorTabAndBackspace && (command.IsBack || command.IsInsertTab))
                {
                    // When the user has opted into 'softtabstop' then Vim has a better understanding of
                    // <BS> than Visual Studio.  Allow that processing to win
                    return(false);
                }

                if (!TryGetOleCommandData(command, out oleCommandData))
                {
                    // Not a command that we custom process
                    return(false);
                }

                var versionNumber = _textBuffer.CurrentSnapshot.Version.VersionNumber;
                var hr            = _nextCommandTarget.Exec(oleCommandData);

                // Whether or not an Exec succeeded is a bit of a heuristic.  IOleCommandTarget implementations like
                // C++ will return E_ABORT if Intellisense failed but the character was actually inserted into
                // the ITextBuffer.  VsVim really only cares about the character insert.  However we must also
                // consider cases where the character successfully resulted in no action as a success
                return(ErrorHandler.Succeeded(hr) || versionNumber < _textBuffer.CurrentSnapshot.Version.VersionNumber);
            }
            finally
            {
                if (oleCommandData != null)
                {
                    oleCommandData.Dispose();
                }

                if (_vim.InBulkOperation && _broker.IsCompletionActive)
                {
                    _broker.DismissDisplayWindows();
                }
            }
        }
Exemplo n.º 4
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);
            }

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