Example #1
0
        // Tab across to the next stop, or perform tab completion.
        private void Tab()
        {
            if (TabComplete == null)
            {
                // Add the TAB character and repaint the line.
                AddChar('\t');
            }
            else
            {
                if (_state != ReadlineState.Completing)
                {
                    CollectLastWord('\0');
                    _state = ReadlineState.Completing;
                }

                // Perform tab completion and insert the results.
                var e = new TabCompleteEventArgs(_lastWord.ToString(), ++_tabCount);
                TabComplete(this, e);
                if (e.Insert != null)
                {
                    _savePosn = _posn;
                    // Insert the value that we found.
                    var saveOverwrite = _overwrite;
                    _overwrite = false;
                    _savePosn  = e.Insert.Length;

                    _state = ReadlineState.Completing;
                    foreach (var ch in e.Insert)
                    {
                        AddChar(ch);
                    }
                    _overwrite = saveOverwrite;
                }
                else if (e.Alternatives != null && e.Alternatives.Length > 0)
                {
                    // Print the alternatives for the user.
                    _savePosn = _posn;
                    EndLine();
                    PrintAlternatives?.Invoke(this, new PrintAlternativesEventArgs(e.Alternatives));
                    WritePrompt?.Invoke(this, EventArgs.Empty);

                    _posn  = _savePosn;
                    _state = ReadlineState.Completing;
                    Redraw();
                }
                else
                {
                    if (e.Error)
                    {
                        ResetComplete(ReadlineState.MoreInput);
                    }

                    // No alternatives, or alternatives not supplied yet.
                    Console.Beep();
                }
            }
        }
Example #2
0
        private void ResetComplete(ReadlineState newState)
        {
            if (_state == ReadlineState.Completing)
            {
                _tabCount = -1;
                _savePosn = -1;
            }

            _state = newState;
        }
Example #3
0
        // Read the next line of input using line editing.  Returns "null"
        // if an EOF indication is encountered in the input.
        public string ReadLine()
        {
            var treatControlCAsInterrupt = Console.TreatControlCAsInput;

            Console.TreatControlCAsInput = !CtrlCInterrupts;

            try
            {
                // Output the prompt.
                WritePrompt?.Invoke(this, EventArgs.Empty);

                // Enter the main character input loop.
                _posn        = 0;
                _length      = 0;
                _column      = 0;
                _lastColumn  = 0;
                _overwrite   = false;
                _historyPosn = -1;
                var ctrlv = false;
                _state = ReadlineState.MoreInput;
                do
                {
                    var key = ConsoleExtensions.ReadKey(true);
                    var ch  = key.KeyChar;
                    if (ctrlv)
                    {
                        ctrlv = false;
                        if ((ch >= 0x0001 && ch <= 0x001F) || ch == 0x007F)
                        {
                            // Insert a control character into the buffer.
                            AddChar(ch);
                            continue;
                        }
                    }
                    if (ch != '\0')
                    {
                        switch (ch)
                        {
                        case '\u0001':
                        {
                            // CTRL-A: move to the home position.
                            MoveHome();
                        }
                        break;

                        case '\u0002':
                        {
                            // CTRL-B: go back one character.
                            MoveLeft();
                        }
                        break;

                        case '\u0003':
                        {
                            // CTRL-C encountered in "raw" mode.
                            if (CtrlCInterrupts)
                            {
                                EndLine();
                                Interrupt?.Invoke(null, EventArgs.Empty);
                                return(null);
                            }
                            CancelLine();
                            _lastWord.Length = 0;
                        }
                        break;

                        case '\u0004':
                        {
                            // CTRL-D: EOF or delete the current character.
                            if (CtrlDIsEOF)
                            {
                                _lastWord.Length = 0;
                                // Signal an EOF if the buffer is empty.
                                if (_length == 0)
                                {
                                    EndLine();
                                    return(null);
                                }
                            }
                            else
                            {
                                Delete();
                                ResetComplete(ReadlineState.MoreInput);
                            }
                        }
                        break;

                        case '\u0005':
                        {
                            // CTRL-E: move to the end position.
                            MoveEnd();
                        }
                        break;

                        case '\u0006':
                        {
                            // CTRL-F: go forward one character.
                            MoveRight();
                        }
                        break;

                        case '\u0007':
                        {
                            // CTRL-G: ring the terminal bell.
                            Console.Beep();
                        }
                        break;

                        case '\u0008':
                        case '\u007F':
                        {
                            if (key.Key == ConsoleKey.Delete)
                            {
                                // Delete the character under the cursor.
                                Delete();
                            }
                            else
                            {
                                // Delete the character before the cursor.
                                Backspace();
                            }
                            ResetComplete(ReadlineState.MoreInput);
                        }
                        break;

                        case '\u0009':
                        {
                            // Process a tab.
                            Tab();
                        }
                        break;

                        case '\u000A':
                        case '\u000D':
                        {
                            // Line termination.
                            EndLine();
                            ResetComplete(ReadlineState.Done);
                            _lastWord.Length = 0;
                        }
                        break;

                        case '\u000B':
                        {
                            // CTRL-K: erase until the end of the line.
                            EraseToEnd();
                        }
                        break;

                        case '\u000C':
                        {
                            // CTRL-L: clear screen and redraw.
                            Console.Clear();
                            WritePrompt?.Invoke(this, EventArgs.Empty);
                            Redraw();
                        }
                        break;

                        case '\u000E':
                        {
                            // CTRL-N: move down in the history.
                            MoveDown();
                        }
                        break;

                        case '\u0010':
                        {
                            // CTRL-P: move up in the history.
                            MoveUp();
                        }
                        break;

                        case '\u0015':
                        {
                            // CTRL-U: erase to the start of the line.
                            EraseToStart();
                            ResetComplete(ReadlineState.None);
                        }
                        break;

                        case '\u0016':
                        {
                            // CTRL-V: prefix a control character.
                            ctrlv = true;
                        }
                        break;

                        case '\u0017':
                        {
                            // CTRL-W: erase the previous word.
                            EraseWord();
                            ResetComplete(ReadlineState.MoreInput);
                        }
                        break;

                        case '\u0019':
                        {
                            // CTRL-Y: yank the last erased string.
                            if (_yankedString != null)
                            {
                                foreach (var ch2 in _yankedString)
                                {
                                    AddChar(ch2);
                                }
                            }
                        }
                        break;

                        case '\u001A':
                        {
                            // CTRL-Z: Windows end of file indication.
                            if (CtrlZIsEOF && _length == 0)
                            {
                                EndLine();
                                return(null);
                            }
                        }
                        break;

                        case '\u001B':
                        {
                            // Escape is "clear line".
                            Clear();
                            ResetComplete(ReadlineState.MoreInput);
                        }
                        break;

                        default:
                        {
                            if (ch >= ' ')
                            {
                                // Ordinary character.
                                AddChar(ch);
                                ResetComplete(ReadlineState.MoreInput);
                            }
                        }
                        break;
                        }
                    }
                    else if (key.Modifiers == 0)
                    {
                        switch (key.Key)
                        {
                        case ConsoleKey.Backspace:
                        {
                            // Delete the character before the cursor.
                            Backspace();
                            ResetComplete(ReadlineState.MoreInput);
                        }
                        break;

                        case ConsoleKey.Delete:
                        {
                            // Delete the character under the cursor.
                            Delete();
                            ResetComplete(ReadlineState.MoreInput);
                        }
                        break;

                        case ConsoleKey.Enter:
                        {
                            // Line termination.
                            EndLine();
                            ResetComplete(ReadlineState.Done);
                        }
                        break;

                        case ConsoleKey.Escape:
                        {
                            // Clear the current line.
                            Clear();
                            ResetComplete(ReadlineState.None);
                        }
                        break;

                        case ConsoleKey.Tab:
                        {
                            // Process a tab.
                            Tab();
                        }
                        break;

                        case ConsoleKey.LeftArrow:
                        {
                            // Move left one character.
                            MoveLeft();
                        }
                        break;

                        case ConsoleKey.RightArrow:
                        {
                            // Move right one character.
                            MoveRight();
                        }
                        break;

                        case ConsoleKey.UpArrow:
                        {
                            // Move up one line in the history.
                            MoveUp();
                        }
                        break;

                        case ConsoleKey.DownArrow:
                        {
                            // Move down one line in the history.
                            MoveDown();
                        }
                        break;

                        case ConsoleKey.Home:
                        {
                            // Move to the beginning of the line.
                            MoveHome();
                        }
                        break;

                        case ConsoleKey.End:
                        {
                            // Move to the end of the line.
                            MoveEnd();
                        }
                        break;

                        case ConsoleKey.Insert:
                        {
                            // Toggle insert/overwrite mode.
                            _overwrite = !_overwrite;
                        }
                        break;
                        }
                    }
                    else if ((key.Modifiers & ConsoleModifiers.Alt) != 0)
                    {
                        switch (key.Key)
                        {
                        case ConsoleKey.F:
                        {
                            // ALT-F: move forward a word.
                            MoveForwardWord();
                        }
                        break;

                        case ConsoleKey.B:
                        {
                            // ALT-B: move backward a word.
                            MoveBackwardWord();
                        }
                        break;

                        case ConsoleKey.D:
                        {
                            // ALT-D: erase until the end of the word.
                            EraseToEndWord();
                        }
                        break;

                        case ConsoleKey.Backspace:
                        case ConsoleKey.Delete:
                        {
                            // ALT-DEL: erase until the start of the word.
                            EraseToStartWord();
                        }
                        break;
                        }
                    }
                } while (_state != ReadlineState.Done);
                return(new string(_buffer, 0, _length));
            }
            finally
            {
                Console.TreatControlCAsInput = treatControlCAsInterrupt;
            }
        }
Example #4
0
        // Read the next line of input using line editing.  Returns "null"
        // if an EOF indication is encountered in the input.
        public string ReadLine()
        {
            var treatControlCAsInterrupt = Console.TreatControlCAsInput;
            Console.TreatControlCAsInput = !CtrlCInterrupts;

            try
            {
                // Output the prompt.
                WritePrompt?.Invoke(this, EventArgs.Empty);

                // Enter the main character input loop.
                _posn = 0;
                _length = 0;
                _column = 0;
                _lastColumn = 0;
                _overwrite = false;
                _historyPosn = -1;
                var ctrlv = false;
                _state = ReadlineState.MoreInput;
                do
                {
                    var key = ConsoleExtensions.ReadKey(true);
                    var ch = key.KeyChar;
                    if (ctrlv)
                    {
                        ctrlv = false;
                        if ((ch >= 0x0001 && ch <= 0x001F) || ch == 0x007F)
                        {
                            // Insert a control character into the buffer.
                            AddChar(ch);
                            continue;
                        }
                    }
                    if (ch != '\0')
                    {
                        switch (ch)
                        {
                            case '\u0001':
                            {
                                // CTRL-A: move to the home position.
                                MoveHome();
                            }
                                break;

                            case '\u0002':
                            {
                                // CTRL-B: go back one character.
                                MoveLeft();
                            }
                                break;

                            case '\u0003':
                            {
                                // CTRL-C encountered in "raw" mode.
                                if (CtrlCInterrupts)
                                {
                                    EndLine();
                                    Interrupt?.Invoke(null, EventArgs.Empty);
                                    return null;
                                }
                                CancelLine();
                                _lastWord.Length = 0;
                            }
                                break;

                            case '\u0004':
                            {
                                // CTRL-D: EOF or delete the current character.
                                if (CtrlDIsEOF)
                                {
                                    _lastWord.Length = 0;
                                    // Signal an EOF if the buffer is empty.
                                    if (_length == 0)
                                    {
                                        EndLine();
                                        return null;
                                    }
                                }
                                else
                                {
                                    Delete();
                                    ResetComplete(ReadlineState.MoreInput);
                                }
                            }
                                break;

                            case '\u0005':
                            {
                                // CTRL-E: move to the end position.
                                MoveEnd();
                            }
                                break;

                            case '\u0006':
                            {
                                // CTRL-F: go forward one character.
                                MoveRight();
                            }
                                break;

                            case '\u0007':
                            {
                                // CTRL-G: ring the terminal bell.
                                Console.Beep();
                            }
                                break;

                            case '\u0008':
                            case '\u007F':
                            {
                                if (key.Key == ConsoleKey.Delete)
                                {
                                    // Delete the character under the cursor.
                                    Delete();
                                }
                                else
                                {
                                    // Delete the character before the cursor.
                                    Backspace();
                                }
                                ResetComplete(ReadlineState.MoreInput);
                            }
                                break;

                            case '\u0009':
                            {
                                // Process a tab.
                                Tab();
                            }
                                break;

                            case '\u000A':
                            case '\u000D':
                            {
                                // Line termination.
                                EndLine();
                                ResetComplete(ReadlineState.Done);
                                _lastWord.Length = 0;
                            }
                                break;

                            case '\u000B':
                            {
                                // CTRL-K: erase until the end of the line.
                                EraseToEnd();
                            }
                                break;

                            case '\u000C':
                            {
                                // CTRL-L: clear screen and redraw.
                                Console.Clear();
                                WritePrompt?.Invoke(this, EventArgs.Empty);
                                Redraw();
                            }
                                break;

                            case '\u000E':
                            {
                                // CTRL-N: move down in the history.
                                MoveDown();
                            }
                                break;

                            case '\u0010':
                            {
                                // CTRL-P: move up in the history.
                                MoveUp();
                            }
                                break;

                            case '\u0015':
                            {
                                // CTRL-U: erase to the start of the line.
                                EraseToStart();
                                ResetComplete(ReadlineState.None);
                            }
                                break;

                            case '\u0016':
                            {
                                // CTRL-V: prefix a control character.
                                ctrlv = true;
                            }
                                break;

                            case '\u0017':
                            {
                                // CTRL-W: erase the previous word.
                                EraseWord();
                                ResetComplete(ReadlineState.MoreInput);
                            }
                                break;

                            case '\u0019':
                            {
                                // CTRL-Y: yank the last erased string.
                                if (_yankedString != null)
                                {
                                    foreach (var ch2 in _yankedString)
                                    {
                                        AddChar(ch2);
                                    }
                                }
                            }
                                break;

                            case '\u001A':
                            {
                                // CTRL-Z: Windows end of file indication.
                                if (CtrlZIsEOF && _length == 0)
                                {
                                    EndLine();
                                    return null;
                                }
                            }
                                break;

                            case '\u001B':
                            {
                                // Escape is "clear line".
                                Clear();
                                ResetComplete(ReadlineState.MoreInput);
                            }
                                break;

                            default:
                            {
                                if (ch >= ' ')
                                {
                                    // Ordinary character.
                                    AddChar(ch);
                                    ResetComplete(ReadlineState.MoreInput);
                                }
                            }
                                break;
                        }
                    }
                    else if (key.Modifiers == 0)
                    {
                        switch (key.Key)
                        {
                            case ConsoleKey.Backspace:
                            {
                                // Delete the character before the cursor.
                                Backspace();
                                ResetComplete(ReadlineState.MoreInput);
                            }
                                break;

                            case ConsoleKey.Delete:
                            {
                                // Delete the character under the cursor.
                                Delete();
                                ResetComplete(ReadlineState.MoreInput);
                            }
                                break;

                            case ConsoleKey.Enter:
                            {
                                // Line termination.
                                EndLine();
                                ResetComplete(ReadlineState.Done);
                            }
                                break;

                            case ConsoleKey.Escape:
                            {
                                // Clear the current line.
                                Clear();
                                ResetComplete(ReadlineState.None);
                            }
                                break;

                            case ConsoleKey.Tab:
                            {
                                // Process a tab.
                                Tab();
                            }
                                break;

                            case ConsoleKey.LeftArrow:
                            {
                                // Move left one character.
                                MoveLeft();
                            }
                                break;

                            case ConsoleKey.RightArrow:
                            {
                                // Move right one character.
                                MoveRight();
                            }
                                break;

                            case ConsoleKey.UpArrow:
                            {
                                // Move up one line in the history.
                                MoveUp();
                            }
                                break;

                            case ConsoleKey.DownArrow:
                            {
                                // Move down one line in the history.
                                MoveDown();
                            }
                                break;

                            case ConsoleKey.Home:
                            {
                                // Move to the beginning of the line.
                                MoveHome();
                            }
                                break;

                            case ConsoleKey.End:
                            {
                                // Move to the end of the line.
                                MoveEnd();
                            }
                                break;

                            case ConsoleKey.Insert:
                            {
                                // Toggle insert/overwrite mode.
                                _overwrite = !_overwrite;
                            }
                                break;
                        }
                    }
                    else if ((key.Modifiers & ConsoleModifiers.Alt) != 0)
                    {
                        switch (key.Key)
                        {
                            case ConsoleKey.F:
                            {
                                // ALT-F: move forward a word.
                                MoveForwardWord();
                            }
                                break;

                            case ConsoleKey.B:
                            {
                                // ALT-B: move backward a word.
                                MoveBackwardWord();
                            }
                                break;

                            case ConsoleKey.D:
                            {
                                // ALT-D: erase until the end of the word.
                                EraseToEndWord();
                            }
                                break;

                            case ConsoleKey.Backspace:
                            case ConsoleKey.Delete:
                            {
                                // ALT-DEL: erase until the start of the word.
                                EraseToStartWord();
                            }
                                break;
                        }
                    }
                } while (_state != ReadlineState.Done);
                return new string(_buffer, 0, _length);
            }
            finally
            {
                Console.TreatControlCAsInput = treatControlCAsInterrupt;
            }
        }
Example #5
0
        // Tab across to the next stop, or perform tab completion.
        private void Tab()
        {
            if (TabComplete == null)
            {
                // Add the TAB character and repaint the line.
                AddChar('\t');
            }
            else
            {
                if (_state != ReadlineState.Completing)
                {
                    CollectLastWord('\0');
                    _state = ReadlineState.Completing;
                }

                // Perform tab completion and insert the results.
                var e = new TabCompleteEventArgs(_lastWord.ToString(), ++_tabCount);
                TabComplete(this, e);
                if (e.Insert != null)
                {
                    _savePosn = _posn;
                    // Insert the value that we found.
                    var saveOverwrite = _overwrite;
                    _overwrite = false;
                    _savePosn = e.Insert.Length;

                    _state = ReadlineState.Completing;
                    foreach (var ch in e.Insert)
                    {
                        AddChar(ch);
                    }
                    _overwrite = saveOverwrite;
                }
                else if (e.Alternatives != null && e.Alternatives.Length > 0)
                {
                    // Print the alternatives for the user.
                    _savePosn = _posn;
                    EndLine();
                    PrintAlternatives?.Invoke(this, new PrintAlternativesEventArgs(e.Alternatives));
                    WritePrompt?.Invoke(this, EventArgs.Empty);

                    _posn = _savePosn;
                    _state = ReadlineState.Completing;
                    Redraw();
                }
                else
                {
                    if (e.Error)
                    {
                        ResetComplete(ReadlineState.MoreInput);
                    }

                    // No alternatives, or alternatives not supplied yet.
                    Console.Beep();
                }
            }
        }
Example #6
0
        private void ResetComplete(ReadlineState newState)
        {
            if (_state == ReadlineState.Completing)
            {
                _tabCount = -1;
                _savePosn = -1;
            }

            _state = newState;
        }