Ejemplo n.º 1
0
 private bool IsDoneWithCompletions(CompletionResult currentCompletion, PSKeyInfo nextKey)
 {
     return(nextKey == Keys.Space ||
            nextKey == Keys.Enter ||
            KeysEndingCompletion.TryGetValue(currentCompletion.ResultType, out var doneKeys) &&
            doneKeys.Contains(nextKey));
 }
Ejemplo n.º 2
0
        private void ReadOneOrMoreKeys()
        {
            _readkeyStopwatch.Restart();
            while (_console.KeyAvailable)
            {
                // _charMap is only guaranteed to accumulate input while KeyAvailable
                // returns false. Make sure to check KeyAvailable after every ProcessKey call,
                // and clear it in a loop in case the input was something like ^[[1 which can
                // be 3, 2, or part of 1 key depending on timing.
                _charMap.ProcessKey(_console.ReadKey());
                while (_charMap.KeyAvailable)
                {
                    var key = PSKeyInfo.FromConsoleKeyInfo(_charMap.ReadKey());
                    _lastNKeys.Enqueue(key);
                    _queuedKeys.Enqueue(key);
                }
                if (_readkeyStopwatch.ElapsedMilliseconds > 2)
                {
                    // Don't spend too long in this loop if there are lots of queued keys
                    break;
                }
            }

            if (_queuedKeys.Count == 0)
            {
                while (!_charMap.KeyAvailable)
                {
                    // Don't want to block when there is an escape sequence being read.
                    if (_charMap.InEscapeSequence)
                    {
                        if (_console.KeyAvailable)
                        {
                            _charMap.ProcessKey(_console.ReadKey());
                        }
                        else
                        {
                            // We don't want to sleep for the whole escape timeout
                            // or the user will have a laggy console, but there's
                            // nothing to block on at this point either, so do a
                            // small sleep to yield the CPU while we're waiting
                            // to decide what the input was. This will only run
                            // if there are no keys waiting to be read.
                            Thread.Sleep(5);
                        }
                    }
                    else
                    {
                        _charMap.ProcessKey(_console.ReadKey());
                    }
                }
                while (_charMap.KeyAvailable)
                {
                    var key = PSKeyInfo.FromConsoleKeyInfo(_charMap.ReadKey());
                    _lastNKeys.Enqueue(key);
                    _queuedKeys.Enqueue(key);
                }
            }
        }
Ejemplo n.º 3
0
        private static void Chord(ConsoleKeyInfo?key = null, object arg = null)
        {
            if (!key.HasValue)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (_singleton._chordDispatchTable.TryGetValue(PSKeyInfo.FromConsoleKeyInfo(key.Value), out var secondKeyDispatchTable))
            {
                var secondKey = ReadKey();
                _singleton.ProcessOneKey(secondKey, secondKeyDispatchTable, ignoreIfNoAction: true, arg: arg);
            }
        }
Ejemplo n.º 4
0
 private void PrependQueuedKeys(PSKeyInfo key)
 {
     if (_queuedKeys.Count > 0)
     {
         // This should almost never happen so being inefficient is fine.
         var list = new List <PSKeyInfo>(_queuedKeys);
         _queuedKeys.Clear();
         _queuedKeys.Enqueue(key);
         list.ForEach(k => _queuedKeys.Enqueue(k));
     }
     else
     {
         _queuedKeys.Enqueue(key);
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Chords in vi needs special handling because a numeric argument can be input between the 1st and 2nd key.
        /// </summary>
        private static void ViChord(ConsoleKeyInfo?key = null, object arg = null)
        {
            if (!key.HasValue)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (arg != null)
            {
                Chord(key, arg);
                return;
            }

            if (_singleton._chordDispatchTable.TryGetValue(PSKeyInfo.FromConsoleKeyInfo(key.Value), out var secondKeyDispatchTable))
            {
                var secondKey = ReadKey();
                if (secondKeyDispatchTable.TryGetValue(secondKey, out var handler))
                {
                    _singleton.ProcessOneKey(secondKey, secondKeyDispatchTable, ignoreIfNoAction: true, arg: arg);
                }
                else if (!IsNumeric(secondKey))
                {
                    _singleton.ProcessOneKey(secondKey, secondKeyDispatchTable, ignoreIfNoAction: true, arg: arg);
                }
                else
                {
                    var argBuffer = _singleton._statusBuffer;
                    argBuffer.Clear();
                    _singleton._statusLinePrompt = "digit-argument: ";
                    while (IsNumeric(secondKey))
                    {
                        argBuffer.Append(secondKey.KeyChar);
                        _singleton.Render();
                        secondKey = ReadKey();
                    }
                    int numericArg = int.Parse(argBuffer.ToString());
                    if (secondKeyDispatchTable.TryGetValue(secondKey, out handler))
                    {
                        _singleton.ProcessOneKey(secondKey, secondKeyDispatchTable, ignoreIfNoAction: true, arg: numericArg);
                    }
                    else
                    {
                        Ding();
                    }
                    argBuffer.Clear();
                    _singleton.ClearStatusMessage(render: true);
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Chords in vi needs special handling because a numeric argument can be input between the 1st and 2nd key.
        /// </summary>
        private static void ViChord(ConsoleKeyInfo?key = null, object arg = null)
        {
            if (!key.HasValue)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (arg != null)
            {
                Chord(key, arg);
                return;
            }

            if (_singleton._chordDispatchTable.TryGetValue(PSKeyInfo.FromConsoleKeyInfo(key.Value), out var secondKeyDispatchTable))
            {
                ViChordHandler(secondKeyDispatchTable, arg);
            }
        }
Ejemplo n.º 7
0
        void ProcessOneKey(PSKeyInfo key, Dictionary <PSKeyInfo, KeyHandler> dispatchTable, bool ignoreIfNoAction, object arg)
        {
            var consoleKey = key.AsConsoleKeyInfo();

            // Our dispatch tables are built as much as possible in a portable way, so for example,
            // we avoid depending on scan codes like ConsoleKey.Oem6 and instead look at the
            // PSKeyInfo.Key. We also want to ignore the shift state as that may differ on
            // different keyboard layouts.
            //
            // That said, we first look up exactly what we get from Console.ReadKey - that will fail
            // most of the time, and when it does, we normalize the key.
            if (!dispatchTable.TryGetValue(key, out var handler))
            {
                // If we see a control character where Ctrl wasn't used but shift was, treat that like
                // shift hadn't be pressed.  This cleanly allows Shift+Backspace without adding a key binding.
                if (key.Shift && !key.Control && !key.Alt)
                {
                    var c = consoleKey.KeyChar;
                    if (c != '\0' && char.IsControl(c))
                    {
                        key = PSKeyInfo.From(consoleKey.Key);
                        dispatchTable.TryGetValue(key, out handler);
                    }
                }
            }

            if (handler != null)
            {
                if (handler.ScriptBlock != null)
                {
                    CallPossibleExternalApplication(() => handler.Action(consoleKey, arg));
                }
                else
                {
                    handler.Action(consoleKey, arg);
                }
            }
            else if (!ignoreIfNoAction)
            {
                SelfInsert(consoleKey, arg);
            }
        }
Ejemplo n.º 8
0
 private void SetKeyHandlerInternal(string[] keys, Action <ConsoleKeyInfo?, object> handler, string briefDescription, string longDescription, ScriptBlock scriptBlock)
 {
     foreach (var key in keys)
     {
         var chord    = ConsoleKeyChordConverter.Convert(key);
         var firstKey = PSKeyInfo.FromConsoleKeyInfo(chord[0]);
         if (chord.Length == 1)
         {
             _dispatchTable[firstKey] = MakeKeyHandler(handler, briefDescription, longDescription, scriptBlock);
         }
         else
         {
             _dispatchTable[firstKey] = MakeKeyHandler(Chord, "ChordFirstKey");
             if (!_chordDispatchTable.TryGetValue(firstKey, out var secondDispatchTable))
             {
                 secondDispatchTable           = new Dictionary <PSKeyInfo, KeyHandler>();
                 _chordDispatchTable[firstKey] = secondDispatchTable;
             }
             secondDispatchTable[PSKeyInfo.FromConsoleKeyInfo(chord[1])] = MakeKeyHandler(handler, briefDescription, longDescription, scriptBlock);
         }
     }
 }
Ejemplo n.º 9
0
 private void RemoveKeyHandlerInternal(string[] keys)
 {
     foreach (var key in keys)
     {
         var chord    = ConsoleKeyChordConverter.Convert(key);
         var firstKey = PSKeyInfo.FromConsoleKeyInfo(chord[0]);
         if (chord.Length == 1)
         {
             _dispatchTable.Remove(firstKey);
         }
         else
         {
             if (_chordDispatchTable.TryGetValue(firstKey, out var secondDispatchTable))
             {
                 secondDispatchTable.Remove(PSKeyInfo.FromConsoleKeyInfo(chord[1]));
                 if (secondDispatchTable.Count == 0)
                 {
                     _dispatchTable.Remove(firstKey);
                 }
             }
         }
     }
 }
Ejemplo n.º 10
0
 static PSKeyInfo Key(ConsoleKey key) => PSKeyInfo.From(key);
Ejemplo n.º 11
0
 static PSKeyInfo Alt(char c) => PSKeyInfo.WithAlt(c);
Ejemplo n.º 12
0
 static PSKeyInfo Alt(ConsoleKey key) => PSKeyInfo.WithAlt(key);
Ejemplo n.º 13
0
 private static bool IsNumeric(PSKeyInfo key)
 {
     return(key.KeyChar >= '0' && key.KeyChar <= '9' && !key.Control && !key.Alt);
 }
Ejemplo n.º 14
0
 static PSKeyInfo Ctrl(ConsoleKey key) => PSKeyInfo.WithCtrl(key);
Ejemplo n.º 15
0
        /// <summary>
        /// Return key handlers bound to specified chords.
        /// </summary>
        /// <returns></returns>
        public static IEnumerable <PowerShell.KeyHandler> GetKeyHandlers(string[] Chord)
        {
            var boundFunctions = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            if (Chord == null || Chord.Length == 0)
            {
                yield break;
            }

            foreach (string Key in Chord)
            {
                ConsoleKeyInfo[] consoleKeyChord = ConsoleKeyChordConverter.Convert(Key);
                PSKeyInfo        firstKey        = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[0]);

                if (_singleton._dispatchTable.TryGetValue(firstKey, out KeyHandler entry))
                {
                    if (consoleKeyChord.Length == 1)
                    {
                        yield return(new PowerShell.KeyHandler
                        {
                            Key = firstKey.KeyStr,
                            Function = entry.BriefDescription,
                            Description = entry.LongDescription,
                            Group = GetDisplayGrouping(entry.BriefDescription),
                        });
                    }
                    else
                    {
                        PSKeyInfo secondKey = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[1]);
                        if (_singleton._chordDispatchTable.TryGetValue(firstKey, out var secondDispatchTable) &&
                            secondDispatchTable.TryGetValue(secondKey, out entry))
                        {
                            yield return(new PowerShell.KeyHandler
                            {
                                Key = firstKey.KeyStr + "," + secondKey.KeyStr,
                                Function = entry.BriefDescription,
                                Description = entry.LongDescription,
                                Group = GetDisplayGrouping(entry.BriefDescription),
                            });
                        }
                    }
                }

                // If in Vi mode, also check Vi's command mode list.
                if (_singleton._options.EditMode == EditMode.Vi)
                {
                    if (_viCmdKeyMap.TryGetValue(firstKey, out entry))
                    {
                        if (consoleKeyChord.Length == 1)
                        {
                            if (entry.BriefDescription == "Ignore")
                            {
                                continue;
                            }

                            yield return(new PowerShell.KeyHandler
                            {
                                Key = "<" + firstKey.KeyStr + ">",
                                Function = entry.BriefDescription,
                                Description = entry.LongDescription,
                                Group = GetDisplayGrouping(entry.BriefDescription),
                            });
                        }
                        else
                        {
                            PSKeyInfo secondKey = PSKeyInfo.FromConsoleKeyInfo(consoleKeyChord[1]);
                            if (_viCmdChordTable.TryGetValue(firstKey, out var secondDispatchTable) &&
                                secondDispatchTable.TryGetValue(secondKey, out entry))
                            {
                                if (entry.BriefDescription == "Ignore")
                                {
                                    continue;
                                }

                                yield return(new PowerShell.KeyHandler
                                {
                                    Key = "<" + firstKey.KeyStr + "," + secondKey.KeyStr + ">",
                                    Function = entry.BriefDescription,
                                    Description = entry.LongDescription,
                                    Group = GetDisplayGrouping(entry.BriefDescription),
                                });
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 16
0
 static PSKeyInfo Key(char c) => PSKeyInfo.From(c);
Ejemplo n.º 17
0
 static PSKeyInfo CtrlAlt(char c) => PSKeyInfo.WithCtrlAlt(c);
Ejemplo n.º 18
0
 static PSKeyInfo CtrlShift(ConsoleKey key) => PSKeyInfo.WithShiftCtrl(key);
Ejemplo n.º 19
0
 static PSKeyInfo Shift(ConsoleKey key) => PSKeyInfo.WithShift(key);