/// <summary>
        /// Reads input from user using hints. Commands history is supported.
        /// </summary>
        /// <param name="inputRegex"></param>
        /// <returns></returns>
        public string ReadLine(string inputRegex = ".*")
        {
            ConsoleKeyInfo input;

            _currentDirectory = Directory.GetCurrentDirectory();

            var userInput    = string.Empty;
            var fullInput    = string.Empty;
            var wasUserInput = false;
            var length       = string.IsNullOrEmpty(_options.InitialText)
                ? _currentDirectory.Length + ConsoleUtils.Prompt.Length
                : _options.InitialText.Length;
            var cursorPosition = new ConsoleCursorPosition(length, Console.CursorTop, Console.WindowWidth);

            ClearConsoleLinesAndWriteInitialText(cursorPosition.StartTop, cursorPosition.Top);
            Suggestion suggestion = InitialSuggestionAndHelp(cursorPosition.StartTop);

            while ((input = Console.ReadKey()).Key != ConsoleKey.Enter)
            {
                var writeSuggestionToConsole = false;
                int positionToDelete;
                if (_previousPressedKey == ConsoleKey.Tab && input.Key != ConsoleKey.Tab)
                {
                    _suggestionsForUserInput = null;
                    suggestion = null;
                }

                switch (input.Key)
                {
                case ConsoleKey.Delete:
                    positionToDelete = cursorPosition.InputLength;
                    if (positionToDelete >= 0 && positionToDelete < userInput.Length)
                    {
                        if (_currentDirectory.Length > cursorPosition.Left - cursorPosition.InputLength)
                        {
                            cursorPosition--;
                        }

                        userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty;
                    }

                    wasUserInput = !string.IsNullOrWhiteSpace(userInput);
                    UpdateSuggestionsForUserInput(userInput);
                    suggestion = GetFirstSuggestion();
                    break;

                case ConsoleKey.Backspace:
                    positionToDelete = cursorPosition.InputLength - 1;
                    if (positionToDelete >= 0 && positionToDelete < userInput.Length)
                    {
                        userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty;
                        cursorPosition--;
                    }

                    if (cursorPosition.InputLength < 0)
                    {
                        cursorPosition = cursorPosition.SetLength(0);
                    }

                    wasUserInput = !string.IsNullOrWhiteSpace(userInput);
                    UpdateSuggestionsForUserInput(userInput);
                    suggestion = GetFirstSuggestion();
                    break;

                case ConsoleKey.Tab:
                    if (_previousPressedKey == ConsoleKey.Tab)
                    {
                        suggestion = GetNextSuggestion();
                        if (suggestion != null)
                        {
                            writeSuggestionToConsole = true;
                            userInput = suggestion.Value + ' ';
                        }
                    }
                    else
                    {
                        if (suggestion != null)
                        {
                            writeSuggestionToConsole = true;
                            userInput = suggestion.Value + ' ';
                            ////UpdateSuggestionsForUserInput(userInput);
                            suggestion = GetFirstSuggestion();
                            var tmp = fullInput.LastIndexOf(" ");

                            if (fullInput.EndsWith("="))
                            {
                                cursorPosition = cursorPosition.SetLength(fullInput.Length);
                            }
                            else if (tmp == -1)
                            {
                                cursorPosition = cursorPosition.SetLength(userInput.Length);
                            }
                            else
                            {
                                cursorPosition = cursorPosition.SetLength(tmp + userInput.Length);
                            }
                        }
                    }

                    break;

                case ConsoleKey.Spacebar:
                    userInput    = userInput.Insert(cursorPosition.InputLength, " ");
                    wasUserInput = true;
                    cursorPosition++;

                    if (userInput.StartsWith(InternalTerminalCommands.Cd))
                    {
                        UpdateDirectorySuggestionsForUserInput(userInput);
                        suggestion = GetFirstSuggestion();
                    }
                    else
                    {
                        _suggestionsForUserInput = null;
                        suggestion = null;
                    }

                    break;

                case ConsoleKey.UpArrow:
                    if (!wasUserInput)
                    {
                        userInput      = GetPreviousCommandFromHistory();
                        cursorPosition = cursorPosition.SetLength(userInput.Length);
                    }
                    else
                    {
                        suggestion = GetPreviousSuggestion();
                    }

                    break;

                case ConsoleKey.DownArrow:
                    if (!wasUserInput)
                    {
                        userInput      = GetNextCommandFromHistory();
                        cursorPosition = cursorPosition.SetLength(userInput.Length);
                    }
                    else
                    {
                        suggestion = GetNextSuggestion();
                    }

                    break;

                case ConsoleKey.LeftArrow:
                    if (cursorPosition.InputLength > 0)
                    {
                        cursorPosition--;
                    }

                    break;

                case ConsoleKey.RightArrow:
                    if (cursorPosition.InputLength < userInput.Length)
                    {
                        cursorPosition++;
                    }

                    break;

                case ConsoleKey.Home:
                    cursorPosition = cursorPosition.SetLength(0);
                    break;

                case ConsoleKey.End:
                    cursorPosition = cursorPosition.SetLength(userInput.Length);
                    break;

                case ConsoleKey.F1:
                case ConsoleKey.F2:
                case ConsoleKey.F3:
                case ConsoleKey.F4:
                case ConsoleKey.F5:
                case ConsoleKey.F6:
                case ConsoleKey.F7:
                case ConsoleKey.F8:
                case ConsoleKey.F9:
                case ConsoleKey.F10:
                case ConsoleKey.F11:
                case ConsoleKey.F12:
                    break;

                default:
                    if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex))
                    {
                        cursorPosition++;
                        userInput = userInput.Insert(cursorPosition.InputLength - 1,
                                                     input.KeyChar.ToString());
                    }

                    wasUserInput = true;

                    if (userInput.StartsWith(InternalTerminalCommands.Cd) || _options.OnlyDirectoriesSuggestions)
                    {
                        UpdateDirectorySuggestionsForUserInput(userInput);
                    }
                    else
                    {
                        UpdateSuggestionsForUserInput(userInput);
                    }

                    suggestion = GetFirstSuggestion();
                    break;
                }

                ClearConsoleLinesAndWriteInitialText(cursorPosition.StartTop, cursorPosition.Top);

                var li = fullInput.TrimEnd().LastIndexOf(" ");
                if (li == -1 && !fullInput.StartsWith(InternalTerminalCommands.Cd, StringComparison.OrdinalIgnoreCase) && !_options.OnlyDirectoriesSuggestions)
                {
                    if (input.Key == ConsoleKey.Tab && _previousPressedKey == ConsoleKey.Tab && suggestion != null)
                    {
                        fullInput      = userInput;
                        cursorPosition = cursorPosition.SetLength(fullInput.Length);
                        ConsoleUtils.Write(fullInput, ConsoleColor.Green);
                    }
                    else
                    {
                        ConsoleUtils.Write(userInput, ConsoleColor.Green);
                        fullInput = userInput;
                    }
                }
                else
                {
                    if (!writeSuggestionToConsole)
                    {
                        ConsoleUtils.Write(userInput, ConsoleColor.Green);
                        fullInput = userInput;
                    }
                    else
                    {
                        userInput = WriteSugestionAsUserInput(userInput, suggestion, li, ref fullInput, ref cursorPosition);
                    }
                }

                if (userInput.Any())
                {
                    if (suggestion != null && suggestion.Value != userInput && writeSuggestionToConsole == false)
                    {
                        WriteSuggestion(suggestion);
                        WriteOnBottomLine(suggestion.Help);
                        _lastSuggestion = suggestion;
                    }
                    else
                    {
                        var splitedUserInput = userInput.Split(' ');
                        var toCheck          = splitedUserInput.Last().Split('=').First();
                        if (_lastSuggestion != null && toCheck.Equals(_lastSuggestion.Value))
                        {
                            WriteOnBottomLine(_lastSuggestion.Help);
                        }
                        else
                        {
                            WriteOnBottomLine(string.Empty);
                        }
                    }
                }
                else
                {
                    WriteOnBottomLine(string.Empty);
                }

                Console.CursorLeft  = cursorPosition.Left;
                Console.CursorTop   = cursorPosition.Top;
                _previousPressedKey = input.Key;
            }

            Console.WriteLine(string.Empty);
            AddCommandToHistory(fullInput);
            return(fullInput);
        }
        private string WriteSugestionAsUserInput(string userInput, Suggestion suggestion, int li, ref string fullInput, ref ConsoleCursorPosition cursorPosition)
        {
            var suggestionValue = userInput;

            suggestionValue = suggestionValue.TrimEnd();
            if (li == -1)
            {
                li = fullInput.Length - 1;
            }

            bool startsWithCd = fullInput.StartsWith(InternalTerminalCommands.Cd, StringComparison.OrdinalIgnoreCase);

            if (!suggestionValue.StartsWith("-") && !startsWithCd && !_options.OnlyDirectoriesSuggestions)
            {
                suggestionValue = $" {suggestionValue} ";
            }
            else
            {
                if (fullInput.Contains(@"\") && startsWithCd)
                {
                    var splitedInputs = fullInput.Split(' ').Last().Split('\\');

                    foreach (var spllitedInput in splitedInputs)
                    {
                        li = li + spllitedInput.Length + 1;
                    }
                }
                else if (fullInput.Contains("/") && startsWithCd)
                {
                    var splitedInputs = fullInput.Split(' ').Last().Split('/');

                    foreach (var spllitedInput in splitedInputs)
                    {
                        li = li + spllitedInput.Length + 1;
                    }
                }
                else
                {
                    if (suggestion.SuggestionType != HintType.DirectoryOrFile)
                    {
                        suggestionValue = $" {suggestionValue}";
                    }
                    else if (startsWithCd)
                    {
                        li++;
                    }
                    else
                    {
                        if (fullInput.Contains("/") || fullInput.Contains(@"\"))
                        {
                            li++;
                        }
                    }
                }
            }

            if (suggestion.SuggestionType == HintType.Value)
            {
                suggestionValue = $" -{suggestion.Key}={suggestionValue.Trim()}";
            }

            fullInput       = $"{fullInput.Substring(0, li)}{suggestionValue}";
            suggestionValue = fullInput;
            ConsoleUtils.Write(fullInput, ConsoleColor.Green);
            cursorPosition = cursorPosition.SetLength(fullInput.Length);
            return(suggestionValue);
        }
        /// <summary>
        /// Reads input from user using hints. Commands history is supported
        /// </summary>
        /// <param name="inputRegex"></param>
        /// <param name="hintColor"></param>
        /// <returns></returns>
        public string ReadHintedLine(string inputRegex = ".*", ConsoleColor hintColor = ConsoleColor.DarkGray)
        {
            ConsoleKeyInfo input;

            Suggestion suggestion     = null;
            var        userInput      = string.Empty;
            var        fullInput      = string.Empty;
            var        readLine       = string.Empty;
            var        wasUserInput   = false;
            var        target         = string.Empty;
            var        cursorPosition = new ConsoleCursorPosition(ConsoleUtils.Prompt.Length, Console.CursorTop, Console.WindowWidth);

            ClearConsoleLines(cursorPosition.StartTop, cursorPosition.Top);
            while ((input = Console.ReadKey()).Key != ConsoleKey.Enter)
            {
                var writeSugestionToConsole = false;
                int positionToDelete;
                switch (input.Key)
                {
                case ConsoleKey.Delete:
                    positionToDelete = cursorPosition.InputLength;
                    if (positionToDelete >= 0 && positionToDelete < userInput.Length)
                    {
                        cursorPosition--;
                        userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty;
                    }

                    wasUserInput = !string.IsNullOrWhiteSpace(userInput);
                    UpdateSuggestionsForUserInput(userInput);
                    suggestion = GetFirstSuggestion();
                    break;

                case ConsoleKey.Backspace:
                    positionToDelete = cursorPosition.InputLength - 1;
                    if (positionToDelete >= 0 && positionToDelete < userInput.Length)
                    {
                        userInput = userInput.Any() ? userInput.Remove(positionToDelete, 1) : string.Empty;
                        cursorPosition--;
                    }

                    if (cursorPosition.InputLength < 0)
                    {
                        cursorPosition = cursorPosition.SetLength(0);
                    }

                    wasUserInput = !string.IsNullOrWhiteSpace(userInput);
                    UpdateSuggestionsForUserInput(userInput);
                    suggestion = GetFirstSuggestion();
                    break;

                case ConsoleKey.Tab:
                    if (suggestion != null)
                    {
                        writeSugestionToConsole = true;
                        userInput = suggestion.Value + ' ';
                        UpdateSuggestionsForUserInput(userInput);
                        suggestion = GetFirstSuggestion();
                        var tmp = fullInput.LastIndexOf(" ");
                        if (tmp == -1)
                        {
                            cursorPosition = cursorPosition.SetLength(userInput.Length);
                        }
                        else
                        {
                            cursorPosition = cursorPosition.SetLength(tmp + userInput.Length);
                        }
                    }

                    break;

                case ConsoleKey.Spacebar:
                    userInput    = userInput + " ";
                    wasUserInput = true;
                    cursorPosition++;
                    ////if (suggestion != null)
                    ////{
                    ////    userInput = suggestion.Value + ' ';
                    ////}
                    ////else if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex))
                    ////{
                    ////    cursorPosition++;
                    ////    userInput = userInput.Insert(cursorPosition.InputLength - 1, input.KeyChar.ToString());
                    ////    UpdateSuggestionsForUserInput(userInput);
                    ////    suggestion = GetFirstSuggestion();
                    ////    cursorPosition = cursorPosition.SetLength(userInput.Length);
                    ////}
                    break;

                case ConsoleKey.UpArrow:
                    if (!wasUserInput)
                    {
                        userInput      = GetPreviousCommandFromHistory();
                        cursorPosition = cursorPosition.SetLength(userInput.Length);
                    }
                    else
                    {
                        suggestion = GetPreviousSuggestion();
                    }

                    break;

                case ConsoleKey.DownArrow:
                    if (!wasUserInput)
                    {
                        userInput      = GetNextCommandFromHistory();
                        cursorPosition = cursorPosition.SetLength(userInput.Length);
                    }
                    else
                    {
                        suggestion = GetNextSuggestion();
                    }

                    break;

                case ConsoleKey.LeftArrow:
                    if (cursorPosition.InputLength > 0)
                    {
                        cursorPosition--;
                    }

                    break;

                case ConsoleKey.RightArrow:
                    if (cursorPosition.InputLength < userInput.Length)
                    {
                        cursorPosition++;
                    }

                    break;

                case ConsoleKey.Home:
                    cursorPosition = cursorPosition.SetLength(0);
                    break;

                case ConsoleKey.End:
                    cursorPosition = cursorPosition.SetLength(userInput.Length);
                    break;

                case ConsoleKey.F1:
                case ConsoleKey.F2:
                case ConsoleKey.F3:
                case ConsoleKey.F4:
                case ConsoleKey.F5:
                case ConsoleKey.F6:
                case ConsoleKey.F7:
                case ConsoleKey.F8:
                case ConsoleKey.F9:
                case ConsoleKey.F10:
                case ConsoleKey.F11:
                case ConsoleKey.F12:
                    break;

                default:
                    if (Regex.IsMatch(input.KeyChar.ToString(), inputRegex))
                    {
                        cursorPosition++;
                        userInput = userInput.Insert(cursorPosition.InputLength - 1,
                                                     input.KeyChar.ToString());
                    }

                    wasUserInput = true;
                    UpdateSuggestionsForUserInput(userInput);
                    suggestion = GetFirstSuggestion();
                    break;
                }

                readLine = suggestion != null ? suggestion.Value : userInput.TrimEnd(' ');

                ClearConsoleLines(cursorPosition.StartTop, cursorPosition.Top);
                var li = fullInput.TrimEnd().LastIndexOf(" ");
                if (li == -1)
                {
                    ConsoleUtils.Write(userInput, ConsoleColor.Green);
                    fullInput = userInput;
                }
                else
                {
                    if (!writeSugestionToConsole)
                    {
                        ConsoleUtils.Write(userInput, ConsoleColor.Green);
                        fullInput = userInput;
                    }
                    else
                    {
                        userInput = userInput.TrimEnd();
                        if (!userInput.StartsWith("-"))
                        {
                            userInput = $"{userInput} ";
                        }

                        fullInput = $"{fullInput.Substring(0, li)} {userInput}";
                        userInput = fullInput;
                        ConsoleUtils.Write(fullInput, ConsoleColor.Green);
                        cursorPosition = cursorPosition.SetLength(fullInput.Length);
                    }
                }

                if (userInput.Any())
                {
                    if (suggestion != null && suggestion.Value != userInput && writeSugestionToConsole == false)
                    {
                        WriteSuggestion(suggestion, hintColor);
                        WriteOnBottomLine(suggestion.Help);
                    }
                }

                Console.CursorLeft = cursorPosition.Left;
                Console.CursorTop  = cursorPosition.Top;
            }

            //ClearConsoleLines();
            Console.WriteLine(string.Empty);
            AddCommandToHistory(readLine);
            return(fullInput);
        }