/// <summary> /// This handler is necessary to intercept keyboard input which maps to Vim /// commands but doesn't map to text input. Any combination which can be /// translated into actual text input will be done so much more accurately by /// WPF and will end up in the TextInput event. /// /// An example of why this handler is needed is for key combinations like /// Shift+Escape. This combination won't translate to an actual character in most /// (possibly all) keyboard layouts. This means it won't ever make it to the /// TextInput event. But it can translate to a Vim command or mapped keyboard /// combination that we do want to handle. Hence we override here specifically /// to capture those circumstances /// </summary> public override void KeyDown(KeyEventArgs e) { VimTrace.TraceInfo("VimKeyProcessor::KeyDown {0} {1}", e.Characters, e.CharactersIgnoringModifiers); bool handled = false; // Attempt to map the key information into a KeyInput value which can be processed // by Vim. If this works and the key is processed then the input is considered // to be handled bool canConvert = _keyUtil.TryConvertSpecialToKeyInput(e.Event, out KeyInput keyInput); if (canConvert) { handled = TryProcess(e, keyInput); } VimTrace.TraceInfo("VimKeyProcessor::KeyDown Handled = {0}", handled); var status = Mac.StatusBar.GetStatus(_vimBuffer); var text = status.Text; if (_vimBuffer.ModeKind == ModeKind.Command) { // Add a fake 'caret' text = text.Insert(status.CaretPosition, "|"); } IdeApp.Workbench.StatusBar.ShowMessage(text); e.Handled = handled; }
/// <summary> /// This handler is necessary to intercept keyboard input which maps to Vim /// commands but doesn't map to text input. Any combination which can be /// translated into actual text input will be done so much more accurately by /// WPF and will end up in the TextInput event. /// /// An example of why this handler is needed is for key combinations like /// Shift+Escape. This combination won't translate to an actual character in most /// (possibly all) keyboard layouts. This means it won't ever make it to the /// TextInput event. But it can translate to a Vim command or mapped keyboard /// combination that we do want to handle. Hence we override here specifically /// to capture those circumstances /// </summary> public override void KeyDown(KeyEventArgs e) { VimTrace.TraceInfo("VimKeyProcessor::KeyDown {0} {1}", e.Characters, e.CharactersIgnoringModifiers); bool handled = false; if (ShouldBeProcessedByVim(e)) { var oldMode = VimBuffer.Mode.ModeKind; VimTrace.TraceDebug(oldMode.ToString()); // Attempt to map the key information into a KeyInput value which can be processed // by Vim. If this works and the key is processed then the input is considered // to be handled if (_keyUtil.TryConvertSpecialToKeyInput(e.Event, out KeyInput keyInput)) { var bufferedKeyInputsWasEmpty = VimBuffer.BufferedKeyInputs.IsEmpty; handled = TryProcess(keyInput); if (handled && BufferedKeysWasEmptyAndIsEmpty() && oldMode == ModeKind.Insert && CharTriggersCompletion(keyInput.Char) && !_completionBroker.IsCompletionActive(VimBuffer.TextView)) { // Because VsVim handled the key press for us in insert mode, // we need to trigger the completion window to open. _completionBroker.TriggerCompletion(VimBuffer.TextView); } bool BufferedKeysWasEmptyAndIsEmpty() { // We don't want the completion window to appear if we // have something like `inoremap fd <esc>` // and we just typed the first 'f' or the 'd' return(bufferedKeyInputsWasEmpty && VimBuffer.BufferedKeyInputs.IsEmpty); } } } VimTrace.TraceInfo("VimKeyProcessor::KeyDown Handled = {0}", handled); var status = Mac.StatusBar.GetStatus(VimBuffer); var text = status.Text; if (VimBuffer.ModeKind == ModeKind.Command) { // Add a fake 'caret' text = text.Insert(status.CaretPosition, "|"); } IdeApp.Workbench.StatusBar.ShowMessage(text); e.Handled = handled; }
/// <summary> /// Convert this key processors's keyboard events into KeyInput and /// forward it to TryProcess /// </summary> public override void KeyDown(KeyEventArgs args) { if (_keyUtil.TryConvertSpecialToKeyInput(args.Key, args.KeyboardDevice.Modifiers, out KeyInput keyInput)) { args.Handled = TryProcess(keyInput); } else if (TryConvertLetterToKeyInput(args, out keyInput)) { args.Handled = TryProcess(keyInput); } else { _firstChord = null; base.KeyDown(args); } }
/// <summary> /// This handler is necessary to intercept keyboard input which maps to Vim /// commands but doesn't map to text input. Any combination which can be /// translated into actual text input will be done so much more accurately by /// WPF and will end up in the TextInput event. /// /// An example of why this handler is needed is for key combinations like /// Shift+Escape. This combination won't translate to an actual character in most /// (possibly all) keyboard layouts. This means it won't ever make it to the /// TextInput event. But it can translate to a Vim command or mapped keyboard /// combination that we do want to handle. Hence we override here specifically /// to capture those circumstances /// </summary> public override void KeyDown(KeyEventArgs args) { VimTrace.TraceInfo("VimKeyProcessor::KeyDown {0} {1}", args.Key, args.KeyboardDevice.Modifiers); bool handled; if (args.Key == Key.DeadCharProcessed) { // 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 by 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 handled = false; } else if (_keyUtil.IsAltGr(args.KeyboardDevice.Modifiers)) { // AltGr greatly confuses things becuase it's realized in WPF as Control | Alt. So // while it's possible to use Control to further modify a key which used AltGr // originally the result is indistinguishable here (and in gVim). Don't attempt // to process it handled = false; } else { // Attempt to map the key information into a KeyInput value which can be processed // by Vim. If this worksa nd the key is processed then the input is considered // to be handled KeyInput keyInput; if (_keyUtil.TryConvertSpecialToKeyInput(args.Key, args.KeyboardDevice.Modifiers, out keyInput)) { handled = TryProcess(keyInput); } else { handled = false; } } VimTrace.TraceInfo("VimKeyProcessor::KeyDown Handled = {0}", handled); args.Handled = handled; base.KeyDown(args); }
/// <summary> /// This handler is necessary to intercept keyboard input which maps to Vim /// commands but doesn't map to text input. Any combination which can be /// translated into actual text input will be done so much more accurately by /// WPF and will end up in the TextInput event. /// /// An example of why this handler is needed is for key combinations like /// Shift+Escape. This combination won't translate to an actual character in most /// (possibly all) keyboard layouts. This means it won't ever make it to the /// TextInput event. But it can translate to a Vim command or mapped keyboard /// combination that we do want to handle. Hence we override here specifically /// to capture those circumstances /// </summary> public override void KeyDown(KeyEventArgs args) { VimTrace.TraceInfo("VimKeyProcessor::KeyDown {0} {1} {2}", args.Key, args.SystemKey, args.KeyboardDevice.Modifiers); var key = args.Key == Key.System ? args.SystemKey : args.Key; bool handled; if (key == Key.DeadCharProcessed) { // 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 by 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 handled = false; } else { // Attempt to map the key information into a KeyInput value which can be processed // by Vim. If this worksa nd the key is processed then the input is considered // to be handled if (_keyUtil.TryConvertSpecialToKeyInput(key, args.KeyboardDevice.Modifiers, out KeyInput keyInput)) { handled = TryProcess(keyInput); } else { handled = false; } } VimTrace.TraceInfo("VimKeyProcessor::KeyDown Handled = {0}", handled); args.Handled = handled; base.KeyDown(args); }
/// <summary> /// This handler is necessary to intercept keyboard input which maps to Vim /// commands but doesn't map to text input. Any combination which can be /// translated into actual text input will be done so much more accurately by /// WPF and will end up in the TextInput event. /// /// An example of why this handler is needed is for key combinations like /// Shift+Escape. This combination won't translate to an actual character in most /// (possibly all) keyboard layouts. This means it won't ever make it to the /// TextInput event. But it can translate to a Vim command or mapped keyboard /// combination that we do want to handle. Hence we override here specifically /// to capture those circumstances /// </summary> public override void KeyDown(KeyEventArgs e) { VimTrace.TraceInfo("VimKeyProcessor::KeyDown {0} {1}", e.Characters, e.CharactersIgnoringModifiers); bool handled; 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 handled = false; } else if (_completionBroker.IsCompletionActive(TextView) && !IsEscapeKey(e)) { handled = false; } else if (_signatureHelpBroker.IsSignatureHelpActive(TextView)) { handled = false; } else if (_inlineRenameListenerFactory.InRename) { handled = false; } else { var oldMode = VimBuffer.Mode.ModeKind; VimTrace.TraceDebug(oldMode.ToString()); // Attempt to map the key information into a KeyInput value which can be processed // by Vim. If this works and the key is processed then the input is considered // to be handled if (_keyUtil.TryConvertSpecialToKeyInput(e.Event, out KeyInput keyInput)) { handled = TryProcess(keyInput); } else { handled = false; } if (oldMode != ModeKind.Insert) { handled = true; } } VimTrace.TraceInfo("VimKeyProcessor::KeyDown Handled = {0}", handled); var status = Mac.StatusBar.GetStatus(VimBuffer); var text = status.Text; if (VimBuffer.ModeKind == ModeKind.Command) { // Add a fake 'caret' text = text.Insert(status.CaretPosition, "|"); } IdeApp.Workbench.StatusBar.ShowMessage(text); e.Handled = handled; }