示例#1
0
 public void DisableAll()
 {
     _vimBuffer1.Process(GlobalSettings.DisableAllCommand);
     Assert.Equal(ModeKind.Disabled, _vimBuffer1.ModeKind);
     Assert.Equal(ModeKind.Disabled, _vimBuffer2.ModeKind);
     Assert.True(Vim.IsDisabled);
 }
示例#2
0
        /// <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));
        }
示例#3
0
        /// <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);
            }
        }
示例#4
0
        /// <summary>
        /// The PreviewKeyDown event is raised before Visual Assist handles a key stroke and they respect the
        /// Handled property of the KeyEventArgs structure.  This is our chance to intercept any keys that
        /// they will process in a way that conflicts with VsVim
        /// </summary>
        public override void PreviewKeyDown(KeyEventArgs args)
        {
            VimTrace.TraceInfo("VisualAssistKeyProcessor::PreviewKeyDown {0} {1}", args.Key, args.KeyboardDevice.Modifiers);

            if (IsTextViewFocused &&
                _vimBuffer.ModeKind == ModeKind.Normal &&
                args.Key == Key.OemPeriod &&
                args.KeyboardDevice.Modifiers == ModifierKeys.None)
            {
                // Visual Assist in general won't process any keys when we are in normal mode because we have
                // the caret hidden.  However it appears they check for the caret hidden on a timer or some
                // form of delay.  This is provable by editting some text in insert mode then quickly hitting
                // Escape followed by '.'.  If this happens fast enough they will process the '.' directly
                // instead of letting the key stroke go through.   This will cause a '.' to appear in the code
                // instead of a repeat action.
                //
                // Experimentation shows that they only do this processing for a subset of keys including
                // '.'.  Letter keys and the like don't have this behavior so we let them go through
                // normal processing.  In the future though we may find more keys that need this exception
                _vimBuffer.Process(KeyInputUtil.CharToKeyInput('.'));
                args.Handled = true;
            }

            VimTrace.TraceInfo("VisualAssistKeyProcessor::KeyDown Handled = {0}", args.Handled);
            base.PreviewKeyDown(args);
        }
示例#5
0
        /// <summary>
        /// This method handles the KeyInput as it applies to command line editor.  Make sure to
        /// mark the key as handled if we use it here.  If we don't then it will propagate out to
        /// the editor and be processed again
        /// </summary>
        internal void HandleKeyEvent(KeyEventArgs e)
        {
            switch (e.Key)
            {
            case Key.Escape:
                _vimBuffer.Process(KeyInputUtil.EscapeKey);
                ChangeEditKind(EditKind.None);
                e.Handled = true;
                break;

            case Key.Return:
                ExecuteCommand(_margin.CommandLineTextBox.Text);
                e.Handled = true;
                break;

            case Key.Up:
                _vimBuffer.Process(KeyInputUtil.VimKeyToKeyInput(VimKey.Up));
                e.Handled = true;
                break;

            case Key.Down:
                _vimBuffer.Process(KeyInputUtil.VimKeyToKeyInput(VimKey.Down));
                e.Handled = true;
                break;
            }
        }
 public void Repeat_Insert()
 {
     Create("the cat");
     _buffer.SwitchMode(ModeKind.Insert, ModeArgument.NewInsertWithCount(2));
     _buffer.Process("hi");
     Assert.AreEqual(2, _textView.GetCaretPoint().Position);
     _buffer.Process(VimKey.Escape);
     Assert.AreEqual("hihithe cat", _textView.GetLine(0).GetText());
     Assert.AreEqual(3, _textView.GetCaretPoint().Position);
 }
示例#7
0
 public static void Process(this IVimBuffer buf, string input, bool enter = false)
 {
     foreach (var c in input)
     {
         var i = KeyInputUtil.CharToKeyInput(c);
         buf.Process(i);
     }
     if (enter)
     {
         buf.Process(KeyInputUtil.EnterKey);
     }
 }
示例#8
0
        /// <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);
        }
 public void Timeout_Single()
 {
     _vimBuffer.Vim.KeyMap.MapWithNoRemap("cat", "chase the cat", KeyRemapMode.Insert);
     _vimBuffer.SwitchMode(ModeKind.Insert, ModeArgument.None);
     _vimBuffer.Process('c');
     Assert.Equal("", _vimBuffer.TextBuffer.GetLine(0).GetText());
     WaitForTimer();
     Assert.Equal("c", _vimBuffer.TextBuffer.GetLine(0).GetText());
 }
示例#10
0
 public void Timeout_Single()
 {
     _vimBuffer.Vim.GlobalKeyMap.AddKeyMapping("cat", "chase the cat", allowRemap: false, KeyRemapMode.Insert);
     _vimBuffer.SwitchMode(ModeKind.Insert, ModeArgument.None);
     _vimBuffer.Process('c');
     Assert.Equal("", _vimBuffer.TextBuffer.GetLine(0).GetText());
     WaitForTimer();
     Assert.Equal("c", _vimBuffer.TextBuffer.GetLine(0).GetText());
 }
示例#11
0
        internal static void Process(this IVimBuffer vimBuffer, string input, bool enter = false)
        {
            foreach (var c in input)
            {
                var keyInput = KeyInputUtil.CharToKeyInput(c);
                vimBuffer.Process(keyInput);
            }

            if (enter)
            {
                vimBuffer.Process(KeyInputUtil.EnterKey);
            }
        }
示例#12
0
        /// <summary>
        /// Process the full notation as a series of KeyInput values
        /// </summary>
        public static void ProcessNotation(this IVimBuffer vimBuffer, string notation, bool enter = false)
        {
            var keyInputSet = KeyNotationUtil.StringToKeyInputSet(notation);

            foreach (var keyInput in keyInputSet.KeyInputs)
            {
                vimBuffer.Process(keyInput);
            }

            if (enter)
            {
                vimBuffer.Process(KeyInputUtil.EnterKey);
            }
        }
示例#13
0
 public override void PreviewKeyUp(KeyEventArgs args)
 {
     if (args.Key == Key.Escape)
     {
         // The Escape key was pressed and we are still inside of Insert mode.  This means that R#
         // handled the key stroke to dismiss intellisense.  Leave insert mode now to complete the operation
         if (_vimBuffer.ModeKind == ModeKind.Insert)
         {
             VimTrace.TraceInfo("ReSharperKeyUtil::PreviewKeyUp handled escape swallowed by ReSharper");
             _vimBuffer.Process(KeyInputUtil.EscapeKey);
         }
     }
     base.PreviewKeyUp(args);
 }
        public void MappedLeft()
        {
            // Reported in issue #1103.
            var command = "%s//g";

            _vimBuffer.Process($":map Q :{command}<Left><Left>", enter: true);
            Assert.Equal(ModeKind.Normal, _vimBuffer.ModeKind);
            _vimBuffer.Process("Q");
            Assert.Equal(ModeKind.Command, _vimBuffer.ModeKind);
            var expectedCaretPosition = command.Length - 2;
            var expectedCommand       = new EditableCommand(command, expectedCaretPosition);

            Assert.Equal(expectedCommand, _vimBuffer.CommandMode.EditableCommand);
            Assert.Equal(":" + command, _control.CommandLineTextBox.Text);
            Assert.Equal(expectedCaretPosition + 1, _control.CommandLineTextBox.SelectionStart);
        }
示例#15
0
 /// <summary>
 /// The escape key was pressed.  If we are currently in insert mode we need to leave it because it
 /// means that Visual Assist swallowed the key stroke
 /// </summary>
 private void HandleEscape()
 {
     if (_vimBuffer.ModeKind == ModeKind.Insert)
     {
         _vimBuffer.Process(KeyInputUtil.EscapeKey);
     }
 }
示例#16
0
        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);
        }
示例#17
0
        /// <summary>
        /// This method handles the KeyInput as it applies to command line editor.  Make sure to
        /// mark the key as handled if we use it here.  If we don't then it will propagate out to
        /// the editor and be processed again
        /// </summary>
        internal void HandleKeyEvent(KeyEventArgs e)
        {
            switch (e.Key)
            {
            case Key.Escape:
                _vimBuffer.Process(KeyInputUtil.EscapeKey);
                ChangeEditKind(EditKind.None);
                e.Handled = true;
                break;

            case Key.Return:
//                    ExecuteCommand(_margin.CommandLineTextBox.Text);
                ExecuteCommand(_commandText);
                e.Handled = true;
                break;

            case Key.Up:
                _vimBuffer.Process(KeyInputUtil.VimKeyToKeyInput(VimKey.Up));
                e.Handled = true;
                break;

            case Key.Down:
                _vimBuffer.Process(KeyInputUtil.VimKeyToKeyInput(VimKey.Down));
                e.Handled = true;
                break;

            case Key.R:
                if (e.KeyboardDevice.Modifiers == ModifierKeys.Control)
                {
                    // During edits we are responsible for handling the command line.  Need to
                    // put a " into the box at the edit position

                    //                        var textBox = _margin.CommandLineTextBox;
//                        var text =  textBox.Text;
//                        var builder = new StringBuilder();
//                        var offset =  textBox.SelectionStart;
//                        builder.Append(text, 0, offset);
//                        builder.Append('"');
//                        builder.Append(text, offset, text.Length - offset);
//                        UpdateCommandLine(builder.ToString());
//                        textBox.Select(offset, 0);

                    // Now move the buffer into paste wait
                    _vimBuffer.Process(KeyInputUtil.ApplyKeyModifiersToChar('r', VimKeyModifiers.Control));
                }
                break;

            case Key.U:
                if (e.KeyboardDevice.Modifiers == ModifierKeys.Control)
                {
//                        var textBox = _margin.CommandLineTextBox;
//                        var text = textBox.Text.Substring(textBox.SelectionStart);
//                        textBox.Text = text;
//
//                        UpdateVimBufferStateWithCommandText(text);
                }
                break;
            }
        }
示例#18
0
        /// <summary>
        /// Process the VimKey values in sequence
        /// </summary>
        public static bool Process(this IVimBuffer buf, params VimKey[] keys)
        {
            var ret = false;

            foreach (var key in keys)
            {
                ret = buf.Process(KeyInputUtil.VimKeyToKeyInput(key)).IsAnyHandled;
            }
            return(ret);
        }
示例#19
0
        internal bool TryProcess(VimKey vimKey)
        {
            var keyInput = KeyInputUtil.VimKeyToKeyInput(vimKey);

            if (_vimBuffer.CanProcess(keyInput))
            {
                return(_vimBuffer.Process(keyInput).IsAnyHandled);
            }

            return(false);
        }
示例#20
0
 public void TypeForwardShouldReplace()
 {
     Create("hello world");
     _buffer.SwitchMode(ModeKind.Replace, ModeArgument.None);
     _buffer.Process("again");
     Assert.AreEqual("again world", _textView.GetLine(0).GetText());
     Assert.AreEqual(5, _textView.GetCaretPoint().Position);
 }
示例#21
0
        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);
        }
示例#22
0
 public void KeyMap_ShiftAndReturn()
 {
     Create("cat", "dog");
     _vimBuffer.Process(":map <S-RETURN> o<Esc>", enter: true);
     _simulation.Run(KeyInputUtil.ApplyModifiersToVimKey(VimKey.Enter, KeyModifiers.Shift));
     Assert.Equal(3, _textBuffer.CurrentSnapshot.LineCount);
     Assert.Equal("cat", _textBuffer.GetLine(0).GetText());
     Assert.Equal("", _textBuffer.GetLine(1).GetText());
     Assert.Equal("dog", _textBuffer.GetLine(2).GetText());
 }
        /// <summary>
        /// This method handles keeping the history buffer in sync with the commandline display text
        /// which do not happen otherwise for EditKind.None.
        /// </summary>
        private bool HandleHistoryNavigation(KeyInput keyInput)
        {
            var handled    = _vimBuffer.Process(keyInput).IsAnyHandled;
            var prefixChar = GetPrefixChar(_editKind);

            if (handled && _editKind != EditKind.None && prefixChar.HasValue)
            {
                switch (_editKind)
                {
                case EditKind.Command:
                    UpdateCommandLine(prefixChar.ToString() + _vimBuffer.CommandMode.Command);
                    break;

                case EditKind.SearchForward:
                case EditKind.SearchBackward:
                    UpdateCommandLine(prefixChar.ToString() + _vimBuffer.IncrementalSearch.CurrentSearchText);
                    break;
                }
                _margin.UpdateCaretPosition(EditPosition.End);
            }
            return(handled);
        }
示例#24
0
 public static bool Process(this IVimBuffer buf, VimKey key)
 {
     return(buf.Process(KeyInputUtil.VimKeyToKeyInput(key)));
 }
示例#25
0
 private void RunCommand(string command)
 {
     _buffer.Process(':');
     _buffer.Process(command, enter: true);
 }
示例#26
0
 public void TestChar_h_1()
 {
     _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot, 2));
     _buffer.Process('h');
     Assert.Equal(1, _textView.Caret.Position.BufferPosition.Position);
 }
示例#27
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);
        }
示例#28
0
 /// <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);
 }
示例#29
0
        public void SwitchModeOneTimeCommand_SetProperty()
        {
            var mode = CreateAndAddInsertMode(MockBehavior.Loose);

            mode.Setup(x => x.Process(It.IsAny <KeyInput>())).Returns(ProcessResult.NewHandled(ModeSwitch.SwitchModeOneTimeCommand));
            _vimBuffer.SwitchMode(ModeKind.Insert, ModeArgument.None);
            _vimBuffer.Process('c');
            Assert.IsTrue(_vimBuffer.InOneTimeCommand.IsSome(ModeKind.Insert));
        }
示例#30
0
 public static bool Process(this IVimBuffer buf, char c)
 {
     return(buf.Process(KeyInputUtil.CharToKeyInput(c)).IsAnyHandled);
 }