Ejemplo n.º 1
0
        /// <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;
                }
            }

            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;
        }
Ejemplo n.º 2
0
        /// <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))
                {
                    handled = TryProcess(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;
        }
Ejemplo n.º 3
0
        private ReadOnlyCollection <ITagSpan <MarkGlyphTag> > GetTags(SnapshotSpan span)
        {
            if (_glyphPairs.Count == 0)
            {
                return(s_emptyTagList);
            }

            var snapshot = span.Snapshot;
            var list     = new List <ITagSpan <MarkGlyphTag> >();

            VimTrace.TraceDebug($"MarkGlyphTagger::GetTags: starting...");
            foreach (var pair in _glyphPairs)
            {
                var chars      = pair.Item1;
                var lineNumber = pair.Item2;

                if (lineNumber < snapshot.LineCount)
                {
                    var line      = snapshot.GetLineFromLineNumber(lineNumber);
                    var startSpan = new SnapshotSpan(line.Start, 0);
                    if (span.Contains(startSpan))
                    {
                        VimTrace.TraceDebug($"MarkGlyphTagger::GetTags: tag {lineNumber} {chars}");
                        var tag     = new MarkGlyphTag(chars);
                        var tagSpan = new TagSpan <MarkGlyphTag>(startSpan, tag);
                        list.Add(tagSpan);
                    }
                }
            }
            return(list.ToReadOnlyCollectionShallow());
        }
Ejemplo n.º 4
0
        private void CachePairs()
        {
            _glyphPairs.Clear();

            if (_activeMarks == 0)
            {
                return;
            }

            var pairs =
                _lineNumberMap
                .Where(pair => pair.Value != -1)
                .GroupBy(pair => pair.Value)
                .Select(grouping =>
                        Tuple.Create(
                            String.Concat(
                                grouping
                                .Select(pair => pair.Key.Char)
                                .OrderBy(key => key)),
                            grouping.Key
                            )
                        );

            _glyphPairs.AddRange(pairs);
            VimTrace.TraceDebug($"MarkGlyphTagger: Glyph Pairs");
            foreach (var pair in _glyphPairs)
            {
                VimTrace.TraceDebug($"MarkGlyphTagger: {pair.Item2} -> {pair.Item1}");
            }
        }
Ejemplo n.º 5
0
        /// <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;
        }
Ejemplo n.º 6
0
        private CommandStatus QueryStatus(EditCommand editCommand)
        {
            VimTrace.TraceDebug("VsCommandTarget::QueryStatus {0}", editCommand);

            var action = CommandStatus.PassOn;

            foreach (var commandTarget in _commandTargets)
            {
                action = commandTarget.QueryStatus(editCommand);
                if (action != CommandStatus.PassOn)
                {
                    break;
                }
            }

            VimTrace.TraceDebug("VsCommandTarget::QueryStatus {0}", action);
            return(action);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// The async completion presenter will fade out the completion menu when the control key is clicked. That
 /// is unfortunate for VsVim as control is held down for the duration of a completion session. This ... method
 /// is used to reset the opacity to 1.0
 /// </summary>
 private void ResetTipOpacity(object sender, EventArgs e)
 {
     try
     {
         var methodInfo = _vsTextView.GetType().BaseType.GetMethod(
             "SetTipOpacity",
             BindingFlags.NonPublic | BindingFlags.Instance,
             Type.DefaultBinder,
             types: new[] { typeof(double) },
             modifiers: null);
         if (methodInfo is object)
         {
             methodInfo.Invoke(_vsTextView, new object[] { (double)1.0 });
         }
     }
     catch (Exception ex)
     {
         VimTrace.TraceDebug($"Unable to set tip opacity {ex}");
     }
 }
Ejemplo n.º 8
0
 private void OnTextBufferChanged(object sender, TextContentChangedEventArgs e)
 {
     VimTrace.TraceDebug($"MarkGlyphTagger::TextBufferChanged {e.AfterVersion}");
     UpdateAllMarks();
 }