namespace Spectre.Console.Cli; internal sealed class TextBuffer : IDisposable { // There is some kind of bug private readonly StringReader _reader; public bool ReachedEnd => _reader.Peek() == -1; public string Original { get; } public int Position { get; private set; } public TextBuffer(string text) { _reader = new StringReader(text); Original = text; Position = 0; } public TextBuffer(TextBuffer? buffer, string text) { _reader = new StringReader(text); Original = buffer != null ? buffer.Original + " " + text : text; Position = buffer?.Position + 1 ?? 0; } public void Dispose() { _reader.Dispose(); } public char Peek() { return (char)_reader.Peek(); } public bool TryPeek(out char character) { var value = _reader.Peek(); if (value == -1) { character = '\0'; return false; } character = (char)value; return true; } public void Consume() { EnsureNotAtEnd(); Read(); } public void Consume(char character) { EnsureNotAtEnd(); if (Read() != character) { throw new InvalidOperationException($"Expected '{character}' token."); } } public bool IsNext(char character) { if (TryPeek(out var result)) { return result == character; } return false; } public char Read() { EnsureNotAtEnd(); var result = (char)_reader.Read(); Position++; return result; } private void EnsureNotAtEnd() { if (ReachedEnd) { throw new InvalidOperationException("Can't read past the end of the buffer."); } } }