public void DoTabCompletion() { var inputState = new InputState(); Console.Write('>'); while (true) { var input = Console.ReadKey(true); switch (input.Key) { case ConsoleKey.Tab: if (input.Modifiers.HasFlag(ConsoleModifiers.Shift)) { inputState.TabIndex = (inputState.TabIndex ?? 0) - 1; } else { if (inputState.TabIndex.HasValue) { ++inputState.TabIndex; } else { inputState.TabIndex = 0; } } var action = GetAction(inputState); if (action != null) { ClearCurrentConsoleLine(); Console.Write(action.FullText); inputState.TabCompletedBuffer = action.FullText; } break; case ConsoleKey.Enter: // We need a newline regardless of what the next action is Console.WriteLine(); var selectedAction = GetAction(inputState); if (selectedAction != null) { selectedAction.Execute(); return; } else { ConsoleHelpers.WriteRedLine("No action with that name recognized, try again or ask for `help`"); } inputState = new InputState(); break; case ConsoleKey.Escape: inputState = new InputState(); ClearCurrentConsoleLine(); break; case ConsoleKey.Backspace: Console.Write("\b \b"); inputState.Backspace(); break; default: inputState.Append(input.KeyChar); Console.Write(input.KeyChar); break; } } }