/// <summary>
        /// Reads a line of text from the console.  Any interactions you've configured before calling this method will be in effect.
        /// </summary>
        /// <param name="initialBuffer">Optionally seed the prompt with an initial value that the end user can modify</param>
        /// <returns>a line of text from the console</returns>
        public ConsoleString ReadLine(ConsoleString initialBuffer = null)
        {
            RichCommandLineContext context = new RichCommandLineContext(this.HistoryManager);

            context.Console          = this.Console;
            context.ConsoleStartTop  = this.Console.CursorTop;
            context.ConsoleStartLeft = this.Console.CursorLeft;

            if (initialBuffer != null)
            {
                context.ReplaceConsole(initialBuffer);
            }

            while (true)
            {
                context.Reset();
                context.KeyPressed       = this.Console.ReadKey(true);
                context.CharacterToWrite = new ConsoleCharacter(context.KeyPressed.KeyChar);
                context.BufferPosition   = this.Console.CursorLeft - context.ConsoleStartLeft + (this.Console.CursorTop - context.ConsoleStartTop) * this.Console.BufferWidth;

                IKeyHandler handler = null;

                if (KeyHandlers.TryGetValue(context.KeyPressed.Key, out handler) == false && context.CharacterToWrite.Value != '\u0000')
                {
                    context.WriteCharacterForPressedKey();
                    DoSyntaxHighlighting(context);
                }
                else if (handler != null)
                {
                    handler.Handle(context);

                    if (context.Intercept == false && context.CharacterToWrite.Value != '\u0000')
                    {
                        this.Console.Write(context.CharacterToWrite);
                    }

                    DoSyntaxHighlighting(context);

                    if (context.IsFinished)
                    {
                        this.Console.WriteLine();
                        break;
                    }
                }
            }

            return(new ConsoleString(context.Buffer));
        }
        /// <summary>
        /// Reads a line of text from the console.  Any interactions you've configured before calling this method will be in effect.
        /// </summary>
        /// <param name="initialBuffer">Optionally seed the prompt with an initial value that the end user can modify</param>
        /// <returns>a line of text from the console</returns>
        public ConsoleString ReadLine(ConsoleString initialBuffer = null)
        {
            RichCommandLineContext context;

            lock (SyncLock)
            {
                context                  = new RichCommandLineContext(this.HistoryManager);
                context.Console          = this.Console;
                context.ConsoleStartTop  = this.Console.CursorTop;
                context.ConsoleStartLeft = this.Console.CursorLeft;
            }

            if (initialBuffer != null)
            {
                lock (SyncLock)
                {
                    context.ReplaceConsole(initialBuffer);
                }
            }

            while (true)
            {
                context.Reset();
                context.KeyPressed = this.Console.ReadKey(true);
                lock (SyncLock)
                {
                    context.CharacterToWrite = new ConsoleCharacter(context.KeyPressed.KeyChar);
                    context.BufferPosition   = this.Console.CursorLeft - context.ConsoleStartLeft + (this.Console.CursorTop - context.ConsoleStartTop) * this.Console.BufferWidth;

                    if (context.BufferPosition < 0 || context.BufferPosition > context.Buffer.Count)
                    {
                        var message = string.Format("The cursor is not located within the bounds of the buffer. Cursor: {0},{1}    Start position: {2},{3}    Buffer position: {4}    Buffer length: {5}", this.Console.CursorTop, this.Console.CursorLeft, context.ConsoleStartTop, context.ConsoleStartLeft, context.BufferPosition, context.Buffer.Count);
                        try
                        {
                            throw new IndexOutOfRangeException(message);
                        }
                        catch (Exception ex)
                        {
                            "\n\nConsole was resized, type input again\n".ToYellow().Write();
                            ">".ToCyan().Write();
                            return(ReadLine(initialBuffer));
                        }
                    }

                    IKeyHandler handler = null;

                    if (KeyHandlers.TryGetValue(context.KeyPressed.Key, out handler) == false && IsWriteable(context.KeyPressed))
                    {
                        context.WriteCharacterForPressedKey();
                        DoSyntaxHighlighting(context);
                    }
                    else if (handler != null)
                    {
                        handler.Handle(context);

                        if (context.Intercept == false && IsWriteable(context.KeyPressed))
                        {
                            context.WriteCharacterForPressedKey();
                        }

                        DoSyntaxHighlighting(context);

                        if (context.IsFinished)
                        {
                            this.Console.WriteLine();
                            break;
                        }
                    }

                    if (AfterReadKey != null)
                    {
                        AfterReadKey(context);
                    }
                }
            }

            return(new ConsoleString(context.Buffer));
        }
        /// <summary>
        /// Reads a line of text from the console.  Any interactions you've configured before calling this method will be in effect.
        /// </summary>
        /// <param name="initialBuffer">Optionally seed the prompt with an initial value that the end user can modify</param>
        /// <returns>a line of text from the console</returns>
        public ConsoleString ReadLine(ConsoleString initialBuffer = null)
        {
            RichCommandLineContext context;
            lock (SyncLock)
            {
                context = new RichCommandLineContext(this.HistoryManager);
                context.Console = this.Console;
                context.ConsoleStartTop = this.Console.CursorTop;
                context.ConsoleStartLeft = this.Console.CursorLeft;
            }

            if(initialBuffer != null)
            {
                lock (SyncLock)
                {
                    context.ReplaceConsole(initialBuffer);
                }
            }

            while (true)
            {
                context.Reset();
                context.KeyPressed = this.Console.ReadKey(true);
                lock (SyncLock)
                {
                    context.CharacterToWrite = new ConsoleCharacter(context.KeyPressed.KeyChar);
                    context.BufferPosition = this.Console.CursorLeft - context.ConsoleStartLeft + (this.Console.CursorTop - context.ConsoleStartTop) * this.Console.BufferWidth;

                    if(context.BufferPosition < 0 || context.BufferPosition > context.Buffer.Count)
                    {
                        var message = string.Format("The cursor is not located within the bounds of the buffer. Cursor: {0},{1}    Start position: {2},{3}    Buffer position: {4}    Buffer length: {5}", this.Console.CursorTop, this.Console.CursorLeft, context.ConsoleStartTop, context.ConsoleStartLeft, context.BufferPosition, context.Buffer.Count);
                        try
                        {
                            throw new IndexOutOfRangeException(message);
                        }
                        catch(Exception ex)
                        {
                            PowerLogger.LogLine(ex.ToString());
                            throw;
                        }
                    }

                    IKeyHandler handler = null;

                    if (KeyHandlers.TryGetValue(context.KeyPressed.Key, out handler) == false && IsWriteable(context.KeyPressed))
                    {
                        context.WriteCharacterForPressedKey();
                        DoSyntaxHighlighting(context);
                    }
                    else if (handler != null)
                    {
                        handler.Handle(context);

                        if (context.Intercept == false && IsWriteable(context.KeyPressed))
                        {
                            context.WriteCharacterForPressedKey();
                        }

                        DoSyntaxHighlighting(context);

                        if (context.IsFinished)
                        {
                            this.Console.WriteLine();
                            break;
                        }
                    }

                    if (AfterReadKey != null)
                    {
                        AfterReadKey(context);
                    }
                }
            }

            return new ConsoleString(context.Buffer);
        }