PromptControl

June 7, 2026 · View on GitHub

Single-line text input with readline-style editing, history, selection, clipboard, and tab completion.

Overview

PromptControl provides a labeled text input field with rich editing capabilities including cursor navigation, word-level operations, text selection, clipboard support, command history, and tab completion. Supports password masking, horizontal scrolling, and mouse click-to-cursor.

Properties

PropertyTypeDefaultDescription
Promptstring?"> "Label text displayed before the input area (supports markup)
Inputstring""Current input text
MaskCharacterchar?nullDisplay character for password fields
InputWidthint?nullInput field width (auto-computed from available space if null)
UnfocusOnEnterbooltrueWhether focus leaves the control on Enter
HistoryEnabledboolfalseEnable Up/Down arrow command recall
TabCompleterFunc<string, int, IEnumerable<string>?>?nullTab completion delegate
InputBackgroundColorColor?ThemeBackground when unfocused
InputFocusedBackgroundColorColor?ThemeBackground when focused
InputForegroundColorColor?ThemeForeground when unfocused
InputFocusedForegroundColorColor?ThemeForeground when focused
IsEnabledbooltrueWhether the control accepts input
HasSelectionbool(read-only)Whether text is currently selected
SelectedTextstring?(read-only)The selected text, or null

Events

EventArgumentsDescription
EnteredstringEnter key pressed — provides the input text
InputChangedstringInput text changed (typing, paste, delete)

Creating PromptControl

var prompt = Controls.Prompt("Search: ")
    .WithHistory()
    .WithMaskCharacter('*')  // password field
    .OnEntered((sender, text) => Console.WriteLine($"You entered: {text}"))
    .Build();

Using Constructor

var prompt = new PromptControl
{
    Prompt = "Enter name: ",
    UnfocusOnEnter = false,
    HistoryEnabled = true
};
prompt.Entered += (sender, text) => ProcessInput(text);

Keyboard Support

KeyAction
Left ArrowMove cursor left
Right ArrowMove cursor right
Home / Ctrl+AMove to start (Ctrl+A selects all)
End / Ctrl+EMove to end
Ctrl+LeftMove word left
Ctrl+RightMove word right

Editing

KeyAction
BackspaceDelete character left (or delete selection)
DeleteDelete character right (or delete selection)
Ctrl+KKill from cursor to end of line
Ctrl+UKill from start to cursor
Ctrl+WKill word backward

Selection & Clipboard

KeyAction
Shift+Left/RightExtend selection
Shift+Home/EndExtend selection to start/end
Ctrl+ASelect all
Ctrl+CCopy selection to clipboard
Ctrl+VPaste from clipboard
Ctrl+XCut selection to clipboard

Copy/paste works locally and over SSH. The control implements IPasteTarget (paste is single-line: newlines are flattened to spaces). See Clipboard, Copy & Paste for the OSC 52 remote-clipboard behavior and configuration.

History & Completion

KeyAction
Up ArrowPrevious history entry (when HistoryEnabled)
Down ArrowNext history entry
TabTrigger tab completion (when TabCompleter is set)
EnterSubmit input (fires Entered, adds to history)
EscapeClear focus

Mouse Support

ActionResult
ClickFocus control and position cursor at clicked character

Tab Completion

Set a TabCompleter delegate that returns completion candidates:

var prompt = Controls.Prompt("$ ")
    .WithTabCompleter((input, cursorPos) =>
    {
        var commands = new[] { "help", "exit", "clear", "history" };
        return commands.Where(c => c.StartsWith(input));
    })
    .WithHistory()
    .Build();

When Tab is pressed:

  • Single match: auto-completes the input
  • Multiple matches: inserts the longest common prefix
  • No matches: Tab passes through to focus traversal (no trap)

Examples

Password Input

var password = Controls.Prompt("Password: ")
    .WithMaskCharacter('●')
    .OnEntered((_, pwd) => Authenticate(pwd))
    .Build();

Command Line with History

var cli = Controls.Prompt("$ ")
    .WithHistory()
    .UnfocusOnEnter(false)
    .OnEntered((sender, cmd) =>
    {
        ExecuteCommand(cmd);
        ((PromptControl)sender!).SetInput("");
    })
    .Build();

URL Bar

var addressBar = Controls.Prompt($"{icon} ")
    .UnfocusOnEnter(false)
    .WithAlignment(HorizontalAlignment.Stretch)
    .OnEntered(async (sender, url) =>
    {
        await htmlControl.LoadUrlAsync(url);
    })
    .Build();

Best Practices

  • Use UnfocusOnEnter(false) for controls where the user types multiple inputs (command lines, search bars)
  • Use WithHistory() for command-line interfaces
  • Use WithMaskCharacter('●') for password fields
  • Tab completion returns false (passes through) when no matches — the user is never trapped
  • Ctrl+A selects all text; typing with a selection replaces it

See Also

Back to Controls | Back to Main Documentation