/// <summary>
        /// Replace the current token in the input buffer with all possible
        /// completions for it.
        /// </summary>
        public void ReplaceCurrentTokenWithAllCompletions()
        {
            if (TokenCompleter == null)
            {
                return;
            }

            var completions = TokenCompletionSet.Create(Buffer.Contents, Buffer.CursorIndex, TokenCompleter);

            if (completions.Empty)
            {
                return;
            }

            var replacementText = string.Concat(completions.Completions.Select(completion => completion + " "));
            var tokenStartIndex = completions.OriginalToken.InnerStartingOffset;
            var tokenLength     = completions.OriginalToken.InnerLength;

            MoveConsoleAndBufferCursors(SeekOrigin.Begin, tokenStartIndex);
            Buffer.Remove(tokenLength);
            Buffer.Insert(replacementText);

            SyncBufferToConsole(tokenStartIndex, replacementText.Length);
            MoveConsoleAndBufferCursors(SeekOrigin.Begin, tokenStartIndex + replacementText.Length);
        }
        private void ReplaceCurrentTokenWithCompletion(bool reverseOrder, bool lastOperationWasCompletion)
        {
            if (TokenCompleter == null)
            {
                return;
            }

            // If we can't pull a completion from the cache, then generate new ones.
            if (!lastOperationWasCompletion || (_lastCompletions == null))
            {
                _lastCompletions      = TokenCompletionSet.Create(Buffer.Contents, Buffer.CursorIndex, TokenCompleter);
                _completionEnumerator = CircularEnumerator.Create(_lastCompletions.Completions);
            }

            // Bail if no completions are available.
            if (_lastCompletions.Empty)
            {
                return;
            }

            // Find the existing token length.
            var existingTokenLength = _completionEnumerator.Started
                ? _completionEnumerator.GetCurrentItem().Length
                : _lastCompletions.OriginalToken.InnerLength;

            // Find the existing token start.
            var existingTokenStart =
                _lastCompletions.OriginalToken.InnerStartingOffset;

            // Select the new completion.
            if (reverseOrder)
            {
                _completionEnumerator.MovePrevious();
            }
            else
            {
                _completionEnumerator.MoveNext();
            }

            // Select the completion.
            var completion = _completionEnumerator.GetCurrentItem();

            // Replace the current token in the buffer with the completion.
            MoveConsoleAndBufferCursors(SeekOrigin.Begin, existingTokenStart);
            Buffer.Remove(existingTokenLength);
            Buffer.Insert(completion);

            // Rewrite the input text.
            SyncBufferToConsole(
                existingTokenStart,
                Buffer.Length - existingTokenStart,
                (existingTokenLength > completion.Length) ? existingTokenLength - completion.Length : 0);

            MoveConsoleAndBufferCursors(SeekOrigin.Current, completion.Length);
        }
        /// <summary>
        /// Displays all completions without modifying the input buffer.
        /// </summary>
        public void DisplayAllCompletions()
        {
            if (TokenCompleter == null)
            {
                return;
            }

            var completions = TokenCompletionSet.Create(Buffer.Contents, Buffer.CursorIndex, TokenCompleter);

            if (completions.Empty)
            {
                return;
            }

            MoveConsoleCursorToNextLine();
            DisplayInColumns(completions.Completions);
            DisplayInputLine();
        }