/// <summary> /// Try and process the KeyInput from the Exec method /// </summary> private bool TryExec(ref Guid commandGroup, ref OleCommandData oleCommandData, KeyInput keyInput) { if (!_buffer.CanProcess(keyInput)) { // If the IVimBuffer can't process it then it doesn't matter return(false); } // Next we need to determine if we can process this directly or not. The only mode // we actively intercept KeyInput for is InsertMode because we need to route it // through IOleCommandTarget to get Intellisense and many other features. var mode = _buffer.ModeKind == ModeKind.Insert ? _buffer.InsertMode : null; if (mode == null) { return(_buffer.Process(keyInput)); } // 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(KeyRemapMode.Insert, keyInput, out mapped) || CanProcessDirectly(mode, mapped)) { return(_buffer.Process(keyInput)); } // At this point we've determined that we need to intercept this return(TryExecIntercepted(ref commandGroup, ref oleCommandData, keyInput, mapped)); }
/// <summary> /// Last chance at custom handling of user input. At this point we have the /// advantage that WPF has properly converted the user input into a char which /// can be effeciently mapped to a KeyInput value. /// </summary> public override void TextInput(TextCompositionEventArgs args) { bool handled = false; if (!String.IsNullOrEmpty(args.Text) && 1 == args.Text.Length && !IgnoreTextInput) { // Only want to intercept text coming from the keyboard. Let other // components edit without having to come through us var keyboard = args.Device as KeyboardDevice; if (keyboard != null) { var ki = KeyUtil.CharAndModifiersToKeyInput(args.Text[0], keyboard.Modifiers); handled = _buffer.CanProcess(ki) && _buffer.Process(ki); } } if (handled) { args.Handled = true; } else { base.TextInput(args); } }
public void QueryStatus_IgnoreEscapeIfCantProcess() { _buffer.SwitchMode(ModeKind.Disabled, ModeArgument.None); Assert.False(_buffer.CanProcess(KeyInputUtil.EscapeKey)); _nextTarget.SetupQueryStatus().Verifiable(); RunQueryStatus(KeyInputUtil.EscapeKey); _factory.Verify(); }
public void CanProcess_Simple() { var keyInput = KeyInputUtil.CharToKeyInput('c'); var normal = CreateAndAddNormalMode(MockBehavior.Loose); normal.Setup(x => x.CanProcess(keyInput)).Returns(true).Verifiable(); _vimBuffer.SwitchMode(ModeKind.Normal, ModeArgument.None); Assert.IsTrue(_vimBuffer.CanProcess(keyInput)); normal.Verify(); }
/// <summary> /// Try and process the KeyInput from the Exec method /// </summary> private bool TryProcessWithBuffer(ref Guid commandGroup, ref OleCommandData oleCommandData, KeyInput keyInput) { if (!_buffer.CanProcess(keyInput)) { // If the IVimBuffer can't process it then it doesn't matter return(false); } // Next we need to determine if we can process this directly or not. The only mode // we actively intercept KeyInput for is InsertMode because we need to route it // through IOleCommandTarget to get Intellisense and many other features. var insertMode = _buffer.ModeKind == ModeKind.Insert ? _buffer.InsertMode : null; if (insertMode == null) { return(_buffer.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) || !ShouldProcessWithCommandTargetOverInsertMode(insertMode, mapped)) { return(_buffer.Process(keyInput).IsAnyHandled); } // We are now intentionally by passing insert mode here. If there is an active // IWordCompletionSession here we need to manually dismiss it. Else it will remain // as we start typing a new word if (insertMode.ActiveWordCompletionSession.IsSome()) { insertMode.ActiveWordCompletionSession.Value.Dismiss(); } // We've successfully mapped the KeyInput (even if t's a no-op) and determined that // we don't want to process it directly if possible. Now we try and process the // potentially mapped value if (TryProcessWithExec(commandGroup, oleCommandData, insertMode, keyInput, mapped)) { return(true); } // If we couldn't map the KeyInput value into a Visual Studio command then go straight to the // ITextBuffer. Insert mode is already designed to handle these KeyInput values we'd just prefer // to pass them through Visual Studio.. Remember to use the original KeyInput value here as // going through IVimBuffer will process mappings return(_buffer.Process(keyInput).IsAnyHandled); }
internal bool TryProcess(VimKey vimKey, int clickCount = 1) { var keyInput = KeyInputUtil.ApplyKeyModifiersToKey(vimKey, _keyboardDevice.KeyModifiers); keyInput = KeyInputUtil.ApplyClickCount(keyInput, clickCount); // If the user has explicitly set the mouse to be <nop> then we don't want to report this as // handled. Otherwise it will swallow the mouse event and as a consequence disable other // features that begin with a mouse click. // // There is really no other way for the user to opt out of mouse behavior besides mapping the // key to <nop> otherwise that would be done here. var keyInputSet = _vimBuffer.GetKeyInputMapping(keyInput).KeyInputSet; if (keyInputSet.Length > 0 && keyInputSet.KeyInputs[0].Key == VimKey.Nop) { return(false); } if (_vimBuffer.CanProcess(keyInput)) { return(_vimBuffer.Process(keyInput).IsAnyHandled); } return(false); }
internal bool TryProcess(VimKey vimKey) { var keyInput = KeyInputUtil.VimKeyToKeyInput(vimKey); if (_vimBuffer.CanProcess(keyInput)) { return(_vimBuffer.Process(keyInput).IsAnyHandled); } return(false); }
private CommandStatus QueryStatus(EditCommand editCommand) { if (editCommand.HasKeyInput && _vimBuffer.CanProcess(editCommand.KeyInput)) { var commandStatus = QueryStatusCore(editCommand.KeyInput); if (commandStatus.HasValue) { return(commandStatus.Value); } } return(CommandStatus.PassOn); }
private bool TryProcess(KeyEventArgs e, KeyInput keyInput) { if (KeyEventIsDeadChar(e)) { // When a dead key combination is pressed we will get the key down events in // sequence after the combination is complete. The dead keys will come first // and be followed the final key which produces the char. That final key // is marked as DeadCharProcessed. // // All of these should be ignored. They will produce a TextInput value which // we can process in the TextInput event return(false); } if ((_vimBuffer.ModeKind.IsAnyInsert() || _vimBuffer.ModeKind.IsAnySelect()) && !_vimBuffer.CanProcessAsCommand(keyInput) && keyInput.Char > 0x1f && _vimBuffer.BufferedKeyInputs.IsEmpty && !_vimBuffer.Vim.MacroRecorder.IsRecording) { return(false); } if (_completionBroker.IsCompletionActive(_textView) && !IsEscapeKey(e)) { return(false); } if (_signatureHelpBroker.IsSignatureHelpActive(_textView) && !IsEscapeKey(e)) { return(false); } if (_inlineRenameListenerFactory.InRename) { return(false); } if (_vimBuffer.ModeKind.IsAnyInsert() && e.Characters == "\t") { // Allow tab key to work for snippet completion // // TODO: We should only really do this when the characters // to the left of the caret form a valid snippet return(false); } return(_vimBuffer.CanProcess(keyInput) && _vimBuffer.Process(keyInput).IsAnyHandled); }
/// <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); }
/// <summary> /// Try and process the given KeyInput with the IVimBuffer. This is overridable by /// derived classes in order for them to prevent any KeyInput from reaching the /// IVimBuffer /// </summary> protected virtual bool TryProcess(KeyInput keyInput) { return(_vimBuffer.CanProcess(keyInput) && _vimBuffer.Process(keyInput).IsAnyHandled); }
/// <summary> /// Helper for the CanProcess function which maps the VimKey to a KeyInput value /// </summary> public static bool CanProcess(this IVimBuffer buffer, VimKey key) { var keyInput = KeyInputUtil.VimKeyToKeyInput(key); return(buffer.CanProcess(keyInput)); }
/// <summary> /// Helper for the CanProcess function which maps the char to a KeyInput value /// </summary> public static bool CanProcess(this IVimBuffer buffer, char c) { var keyInput = KeyInputUtil.CharToKeyInput(c); return(buffer.CanProcess(keyInput)); }
/// <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); }