public void HandleCharacter(char character)
        {
            if (char.IsDigit(character) || char.IsLetter(character) || char.IsSymbol(character) || char.IsPunctuation(character) || char.IsWhiteSpace(character))
            {
                var appended = CurrentEditor.InsertCharacter(character);

                if (mode != Mode.Search)
                {
                    terminal.Write(character);

                    if (!appended)
                    {
                        terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position));
                    }
                }
                else
                {
                    SearchPrompt.Recreate(terminal, -1);

                    history.Reset();
                    var result = history.ReverseSearch(search.Value);
                    terminal.WriteNoMove(result, SearchPrompt.Skip);
                }
            }

            tabTabMode = false;
        }
        public void HandleControlSequence(ControlSequence seq)
        {
            switch (seq.Type)
            {
            case ControlSequenceType.Home:
            {
                var diff = CurrentEditor.MoveHome();
                terminal.CursorBackward(diff);
            }
            break;

            case ControlSequenceType.End:
            {
                var diff = CurrentEditor.MoveEnd();
                terminal.CursorForward(diff);
            }
            break;

            case ControlSequenceType.LeftArrow:
                if (CurrentEditor.MoveCharacterBackward())
                {
                    terminal.CursorBackward();
                }
                break;

            case ControlSequenceType.RightArrow:
                if (CurrentEditor.MoveCharacterForward())
                {
                    terminal.CursorForward();
                }
                break;

            case ControlSequenceType.UpArrow:
            {
                if (mode == Mode.UserInput)
                {
                    break;
                }

                if (!history.HasMoved)
                {
                    history.SetCurrentCommand(CurrentEditor.Value);
                }

                var prev = history.PreviousCommand();
                if (prev != null)
                {
                    var len = CurrentEditor.Position;
                    CurrentEditor.SetValue(prev);
                    terminal.CursorBackward(len);
                    terminal.ClearToTheEndOfLine();
                    terminal.Write(CurrentEditor.Value);
                }
            }
            break;

            case ControlSequenceType.DownArrow:
            {
                if (mode == Mode.UserInput)
                {
                    break;
                }

                var cmd = history.NextCommand();
                if (cmd != null)
                {
                    var len = CurrentEditor.Position;
                    CurrentEditor.SetValue(cmd);
                    terminal.CursorBackward(len);
                    terminal.ClearToTheEndOfLine();
                    terminal.Write(CurrentEditor.Value);
                }
            }
            break;

            case ControlSequenceType.Backspace:
                if (CurrentEditor.RemovePreviousCharacter())
                {
                    terminal.CursorBackward();

                    if (mode == Mode.Command || mode == Mode.UserInput)
                    {
                        terminal.ClearToTheEndOfLine();
                        terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position));
                    }
                    else if (mode == Mode.Search)
                    {
                        SearchPrompt.Recreate(terminal);

                        history.Reset();
                        var result = history.ReverseSearch(search.Value);
                        terminal.WriteNoMove(result, SearchPrompt.Skip);
                    }
                }
                break;

            case ControlSequenceType.Delete:
                if (CurrentEditor.RemoveNextCharacter())
                {
                    if (mode == Mode.Command || mode == Mode.UserInput)
                    {
                        terminal.ClearToTheEndOfLine();
                        terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position));
                    }
                    else if (mode == Mode.Search)
                    {
                        SearchPrompt.Recreate(terminal);

                        history.Reset();
                        var result = history.ReverseSearch(search.Value);
                        terminal.WriteNoMove(result, SearchPrompt.Skip);
                    }
                }
                break;

            case ControlSequenceType.CtrlLeftArrow:
            {
                var diff = CurrentEditor.MoveWordBackward();
                terminal.CursorBackward(diff);
            }
            break;

            case ControlSequenceType.CtrlRightArrow:
            {
                var diff = CurrentEditor.MoveWordForward();
                terminal.CursorForward(diff);
            }
            break;

            case ControlSequenceType.Ctrl:
                switch ((char)seq.Argument)
                {
                case 'c':
                    if (mode == Mode.Command)
                    {
                        terminal.CursorForward(CurrentEditor.MoveEnd());
                        terminal.Write("^C");
                        terminal.NewLine();
                    }
                    else
                    {
                        mode = Mode.Command;
                        terminal.ClearLine();
                    }

                    search.Clear();
                    command.Clear();

                    NormalPrompt.Write(terminal);
                    history.Reset();

                    break;

                case 'r':
                    if (mode == Mode.UserInput)
                    {
                        break;
                    }
                    else if (mode == Mode.Command)
                    {
                        mode = Mode.Search;
                        terminal.CursorBackward(command.MoveHome());
                        terminal.ClearLine();
                        search.SetValue(string.Empty);
                        command.Clear();

                        CurrentPrompt.Write(terminal);
                    }
                    else if (mode == Mode.Search)
                    {
                        if (search.Value != string.Empty)
                        {
                            var result = history.ReverseSearch(search.Value);
                            terminal.CursorForward(SearchPrompt.Skip);
                            terminal.ClearToTheEndOfLine();
                            terminal.WriteNoMove(result);
                            terminal.CursorBackward(SearchPrompt.Skip);
                        }
                    }

                    break;

                case 'w':
                {
                    var diff = CurrentEditor.RemoveWord();
                    if (diff > 0)
                    {
                        terminal.CursorBackward(diff);
                        if (mode == Mode.Command || mode == Mode.UserInput)
                        {
                            terminal.ClearToTheEndOfLine();
                            terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position));
                        }
                        else if (mode == Mode.Search)
                        {
                            SearchPrompt.Recreate(terminal);
                            history.Reset();
                            var result = history.ReverseSearch(search.Value);
                            terminal.WriteNoMove(result);
                        }
                    }
                }
                break;

                case 'k':
                    CurrentEditor.RemoveToTheEnd();

                    if (mode == Mode.Command || mode == Mode.UserInput)
                    {
                        terminal.ClearToTheEndOfLine();
                    }
                    else if (mode == Mode.Search)
                    {
                        SearchPrompt.Recreate(terminal);
                        history.Reset();
                        var result = history.ReverseSearch(search.Value);
                        terminal.WriteNoMove(result);
                    }
                    break;

                default:
                    break;
                }
                break;

            case ControlSequenceType.Esc:
                if (mode == Mode.Search)
                {
                    search.Clear();
                    command.SetValue(history.CurrentCommand ?? string.Empty);
                    mode = Mode.Command;

                    terminal.ClearLine();
                    NormalPrompt.Write(terminal);
                    terminal.Write(command.Value);
                }
                break;

            case ControlSequenceType.Tab:
                if (mode == Mode.UserInput)
                {
                    break;
                }
                else if (mode == Mode.Search)
                {
                    mode = Mode.Command;
                    CurrentEditor.SetValue(history.CurrentCommand);
                    terminal.ClearLine();
                    CurrentPrompt.Write(terminal);
                    terminal.Write(CurrentEditor.Value);
                }
                else if (mode == Mode.Command)
                {
                    var sugs = handler.SuggestionNeeded(CurrentEditor.Value);
                    var preparedBaseString = PreprocessSuggestionsInput(CurrentEditor.Value);
                    var commonPrefix       = Helper.CommonPrefix(sugs, preparedBaseString);
                    var prefix             = String.IsNullOrEmpty(commonPrefix) ? CurrentEditor.Value : commonPrefix;

                    if (sugs.Length == 0)
                    {
                        break;
                    }

                    if (!tabTabMode || sugs.Length == 1)
                    {
                        tabTabMode = true;

                        terminal.CursorBackward(CurrentEditor.Position);
                        terminal.ClearToTheEndOfLine();
                        CurrentEditor.SetValue(prefix);
                    }
                    else if (tabTabMode)
                    {
                        terminal.NewLine();

                        var splitPoint = prefix.LastIndexOf(" ", StringComparison.Ordinal);
                        foreach (var sug in sugs)
                        {
                            terminal.WriteRaw(string.Format(" {0}\r\n", sug.Substring(splitPoint + 1)));
                        }
                        CurrentEditor.SetValue(prefix);
                        NormalPrompt.Write(terminal);
                    }

                    if (sugs.Length == 1 && sugs[0][sugs[0].Length - 1] != DirectorySeparatorChar)
                    {
                        CurrentEditor.InsertCharacter(' ');
                    }
                    terminal.Write(CurrentEditor.Value);
                    return;
                }

                break;

            case ControlSequenceType.Enter:
                var wasInSearchMode = false;
                if (mode == Mode.Search)
                {
                    mode = Mode.Command;
                    command.SetValue(history.CurrentCommand ?? string.Empty);
                    search.Clear();

                    terminal.ClearLine();
                    wasInSearchMode = true;
                }
                else
                {
                    terminal.CursorForward(CurrentEditor.MoveEnd());
                    terminal.NewLine();
                }

                if (CurrentEditor.Value != string.Empty)
                {
                    if (wasInSearchMode)
                    {
                        NormalPrompt.Write(terminal);
                        terminal.Write(command.Value);
                        terminal.NewLine();
                    }

                    var cmd = CurrentEditor.Value;
                    while (true)
                    {
                        var interaction = handler.HandleCommand(cmd, null);
                        if (interaction != null && interaction.QuitEnvironment)
                        {
                            terminal.Stop();
                            return;
                        }

                        CurrentEditor.Clear();
                        if (interaction != null && interaction.CommandToExecute != null)
                        {
                            cmd = interaction.CommandToExecute;
                            terminal.Write(cmd);
                            terminal.NewLine();
                            (interaction as CommandInteraction).Clear();
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                NormalPrompt.Write(terminal);
                if (CurrentEditor.Length > 0)
                {
                    terminal.Write(CurrentEditor.Value);
                }
                history.Reset();

                break;

            default:
                break;
            }

            tabTabMode = false;
        }