Table of Contents

Class App

Namespace
MiniTui
Assembly
MiniTui.dll

Fluent builder for creating TUI applications. Builder methods mutate the app and return it.

[SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "The Stopping source has no timer or links; it's replaced when cancelled and needs no disposal.")]
public class App
Inheritance
App
Inherited Members

Remarks

All callbacks run on the thread that called Run() (the UI thread). Other threads talk to the app through Post(Action), RequestRedraw() and Quit().

Properties

Keys

Global key bindings, tried after the focus chain when screens are used (§9.4). Built in: ? shows help and ctrl+c quits.

public KeyMap Keys { get; }

Property Value

KeyMap

LastFrame

Numbers about the last frame drawn; default before the first one.

public FrameStats LastFrame { get; }

Property Value

FrameStats

Log

Lines written to the console while the app runs (see CaptureConsoleOutput(bool)).

public LogBuffer Log { get; }

Property Value

LogBuffer

MenuBar

The menu bar, or null.

public MenuBar? MenuBar { get; }

Property Value

MenuBar

Overlays

Modal overlays and dialogs, drawn over the screens (or over the Render(Action<Buffer, Rect>) output).

public OverlayStack Overlays { get; }

Property Value

OverlayStack

PointerPosition

Where the pointer was last reported (by any mouse event), or null before the first report.

public Vec2? PointerPosition { get; }

Property Value

Vec2?

Screens

The app's screens (§9.3). An app either pushes screens or sets a Render(Action<Buffer, Rect>) callback. With screens, the app draws the top screen, a status bar (see WithChrome(bool, bool)), overlays and toasts.

public ScreenStack Screens { get; }

Property Value

ScreenStack

ShowDebug

True while the debug overlay is drawn: component outlines and a panel of frame numbers (1.x spec §9.3). Set it from code, or with the key from WithDebugKey(string?).

public bool ShowDebug { get; set; }

Property Value

bool

Size

The terminal size in cells, or (0, 0) when the app isn't running.

public (int Width, int Height) Size { get; }

Property Value

(int Width, int Height)

Stopping

Cancelled when Quit() is called or the loop exits. Pass it to background work.

public CancellationToken Stopping { get; }

Property Value

CancellationToken

TerminalInfo

What the terminal has said about itself so far (1.x spec §12.3). Updated on the UI thread as replies arrive.

public TerminalInfo TerminalInfo { get; }

Property Value

TerminalInfo

Toasts

Toasts the app draws in the top-right corner, over everything else.

public ToastQueue Toasts { get; }

Property Value

ToastQueue

Methods

CaptureConsoleOutput(bool)

While running, redirect Out and Error into Log so stray writes can't corrupt the screen. On by default. Captured error lines are written to stderr on exit.

public App CaptureConsoleOutput(bool capture = true)

Parameters

capture bool

Returns

App

Create()

Create a new App builder.

public static App Create()

Returns

App

Invalidate()

Force a full screen redraw on the next frame.

public void Invalidate()

OnError(Func<Exception, ErrorAction>)

Decide what happens when a callback, posted action or RunTask(Func<CancellationToken, Task>) throws. Without a handler, the terminal is restored and the exception is rethrown from Run().

public App OnError(Func<Exception, ErrorAction> handler)

Parameters

handler Func<Exception, ErrorAction>

Returns

App

OnEvent(Action<Event>)

Observe every event (keys, pastes, mouse events, resizes, resumes and ticks) before it's handled.

public App OnEvent(Action<Event> handler)

Parameters

handler Action<Event>

Returns

App

OnKey(Func<ConsoleKeyInfo, bool>)

Handle a key before anything else sees it (§9.4 step 1). Return true if the key was handled, so routing stops.

public App OnKey(Func<ConsoleKeyInfo, bool> handler)

Parameters

handler Func<ConsoleKeyInfo, bool>

Returns

App

OnMouse(Func<MouseEvent, bool>)

Handle a mouse event before the components see it. Return true if it was handled, so routing stops. In an app with a Render(Action<Buffer, Rect>) callback, this is the only place mouse events go.

public App OnMouse(Func<MouseEvent, bool> handler)

Parameters

handler Func<MouseEvent, bool>

Returns

App

OnPaste(Func<string, bool>)

Handle a paste before the focus chain sees it. Return true if it was handled, so routing stops. Pastes arrive from TerminalInputSource; with ConsoleInputSource, pasted text arrives as keys.

public App OnPaste(Func<string, bool> handler)

Parameters

handler Func<string, bool>

Returns

App

OnSetup(Action)

Set up code to run once on the UI thread before the first frame.

public App OnSetup(Action setup)

Parameters

setup Action

Returns

App

OnSetup(Action<App>)

Set up code to run once on the UI thread before the first frame. It receives the app, for example to start loads with Load(App, Func<CancellationToken, Task<T>>, CancellationToken).

public App OnSetup(Action<App> setup)

Parameters

setup Action<App>

Returns

App

OnUpdate(Action)

Configure update logic that runs on every loop iteration, before rendering.

public App OnUpdate(Action update)

Parameters

update Action

Returns

App

Post(Action)

Run action on the UI thread. Thread-safe. If it throws, OnError(Func<Exception, ErrorAction>) decides what happens.

public void Post(Action action)

Parameters

action Action

Quit()

Stop the loop after the current item. Thread-safe.

public void Quit()

QuitWhenEmpty(bool)

Quit when the last screen is popped. On by default.

public App QuitWhenEmpty(bool quit = true)

Parameters

quit bool

Returns

App

Render(Action<Buffer, Rect>)

Configure the render callback, called with the buffer and screen rect whenever a frame is drawn.

public App Render(Action<Buffer, Rect> render)

Parameters

render Action<Buffer, Rect>

Returns

App

Exceptions

InvalidOperationException

Screens have been pushed; an app uses either screens or a render callback.

RequestRedraw()

Draw a frame soon, even if nothing else happened. Thread-safe.

public void RequestRedraw()

Run()

Run the application on this thread. Blocks until Quit() is called.

public void Run()

RunAsync(CancellationToken)

Run the application on a new UI thread. Cancelling cancellationToken quits it.

[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "The exception is handed to the returned task.")]
public Task RunAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

Task

A task that completes when the app exits, or faults with the exception Run() would throw.

RunTask(Func<CancellationToken, Task>)

Start async work on the UI thread, so its continuations resume there. The token is Stopping. Exceptions go to OnError(Func<Exception, ErrorAction>); cancellation after Quit() is ignored.

public Task RunTask(Func<CancellationToken, Task> work)

Parameters

work Func<CancellationToken, Task>

Returns

Task

A task that completes when the work finishes. It never faults.

Suspend(Action)

Give the terminal back while action runs, for example to run $EDITOR or another program in it (1.x spec §5.4). The app stops reading input, turns mouse reporting and bracketed paste off, restores the terminal mode, leaves the alternate screen and stops capturing Out and Error. When the action returns, or throws, the app takes the terminal again, sends OnEvent(Action<Event>) a ResumeEvent and redraws fully. Input typed during the action goes to the action or the program it runs, not to the app. While it runs, Ctrl+C doesn't end the app.

public void Suspend(Action action)

Parameters

action Action

Remarks

Called from inside an action, it runs action directly.

Exceptions

InvalidOperationException

The app isn't running, or this isn't its UI thread.

SuspendProcess()

Stop the process and return to the shell, as Ctrl+Z does in most terminal programs, with the terminal given back as Suspend(Action) does (1.x spec §5.5). Returns once the shell continues the process (fg) and the app has taken the terminal again. See also WithSuspendKey(bool).

public bool SuspendProcess()

Returns

bool

False, doing nothing, where there's no job control: on Windows, or when the app doesn't draw to the console.

Exceptions

InvalidOperationException

The app isn't running, or this isn't its UI thread.

WithBackend(ITerminalBackend)

Draw through a specific backend, such as TestBackend, instead of the console.

public App WithBackend(ITerminalBackend backend)

Parameters

backend ITerminalBackend

Returns

App

WithChrome(bool, bool)

With screens, reserve the bottom row for a status bar showing key hints on the left and, if breadcrumb is set, the screen titles on the right. On by default.

public App WithChrome(bool statusBar = true, bool breadcrumb = true)

Parameters

statusBar bool
breadcrumb bool

Returns

App

WithClipboardRead(bool)

Read the system clipboard through the terminal (an OSC 52 query) when Ctrl+V or Shift+Insert pastes on Linux and macOS (1.x spec §20.3). Off by default: many terminals refuse, some ask the user each time, and one that doesn't answer costs a 500 ms wait, after which the app stops asking. Windows reads its clipboard anyway.

public App WithClipboardRead(bool enabled = true)

Parameters

enabled bool

Returns

App

WithColorMode(ColorMode)

Override the detected color mode of the default console backend.

public App WithColorMode(ColorMode mode)

Parameters

mode ColorMode

Returns

App

WithDebugKey(string?)

Make key toggle the debug overlay (1.x spec §9). Off by default. The key is checked right after OnKey(Func<ConsoleKeyInfo, bool>), before Ctrl+C, overlays and the focus chain, so it works while a dialog is open or a text field has focus. Null turns the key off again.

public App WithDebugKey(string? key = "f12")

Parameters

key string

A key in the KeyMap syntax, such as "f12" or "ctrl+shift+d".

Returns

App

Exceptions

FormatException

key isn't a valid key.

WithDoubleClickTime(TimeSpan)

The longest time between the presses of a double- or triple-click (1.x spec §17.3). 500 ms by default.

public App WithDoubleClickTime(TimeSpan interval)

Parameters

interval TimeSpan

Returns

App

Exceptions

ArgumentOutOfRangeException

interval is outside 100 ms to 2 s.

WithHover(bool)

Ask the terminal to report every pointer move too (all-motion tracking, 1.x spec §17.5), so components can show what's under the pointer through Hover, and menus follow it. Turns WithMouse(bool) on as well. Off by default: each move is an event, and often a frame.

public App WithHover(bool enabled = true)

Parameters

enabled bool

Returns

App

WithInput(IInputSource)

Read keys from a specific source, such as ScriptedInputSource, instead of the console. The app doesn't dispose it.

public App WithInput(IInputSource input)

Parameters

input IInputSource

Returns

App

WithKeyboardProtocol(bool)

Turn on the best keyboard protocol the terminal supports (1.x spec §12.5): the kitty keyboard protocol, else xterm's modifyOtherKeys, each only after the terminal said it supports it, or Windows Terminal's win32-input-mode on Windows. Keys the classic encoding can't express, such as Ctrl+Enter, Shift+Enter, Ctrl+Tab and Ctrl+I, then arrive as themselves; every other key arrives as before. On by default; the MINITUI_KEYBOARD=legacy environment variable also turns it off. The protocol in use is Keyboard.

public App WithKeyboardProtocol(bool enabled = true)

Parameters

enabled bool

Returns

App

WithMenuBar(MenuBar?)

Show menuBar on the top row, above the screens (1.x spec §15.5): F10 opens its first menu, Alt and a title's mnemonic opens that one. Null removes it.

public App WithMenuBar(MenuBar? menuBar)

Parameters

menuBar MenuBar

Returns

App

WithMouse(bool)

Ask the terminal to report mouse presses, releases and the wheel while the app runs (1.x spec §4.6). Off by default: while the app captures the mouse, selecting text in the terminal needs Shift+drag (Option+drag in iTerm2). Needs TerminalInputSource, the default input.

public App WithMouse(bool enabled = true)

Parameters

enabled bool

Returns

App

WithSuspendKey(bool)

Make an unhandled Ctrl+Z call SuspendProcess(), so it returns to the shell as in most terminal programs (1.x spec §5.5). Off by default. A component or key binding for ctrl+z still gets it first, and an open overlay swallows it. Has no effect on Windows, which has no job control.

public App WithSuspendKey(bool enabled = true)

Parameters

enabled bool

Returns

App

WithTerminalQueries(bool)

Ask the terminal about itself at startup and after a resume: its colors, its keyboard protocols and its name (1.x spec §12.3). On by default; the MINITUI_QUERIES=0 environment variable also turns it off. Replies arrive in TerminalInfo and as a TerminalInfoEvent.

public App WithTerminalQueries(bool enabled = true)

Parameters

enabled bool

Returns

App

WithTheme(Theme)

The theme widgets draw with while the app runs (Current). Without one, the app uses Default. When the terminal has no colors (NO_COLOR), Default is replaced by Monochrome so the selection stays visible; custom themes are used as is. Can be called while running, from any thread; the next frame uses the new theme.

public App WithTheme(Theme theme)

Parameters

theme Theme

Returns

App

WithTheme(Theme, Theme)

Use dark on a dark background and light on a light one, as IsDark says (1.x spec §12.4). dark is used until the background is known, and when it never is; the first frame waits up to 150 ms for the terminal's reply. Calling WithTheme(Theme) afterwards replaces the pair.

public App WithTheme(Theme dark, Theme light)

Parameters

dark Theme
light Theme

Returns

App

WithTickRate(TimeSpan?)

How often a TickEvent is delivered, which also redraws. The default is 250 ms. Null means no ticks: the app only redraws after input, posted actions and redraw requests.

public App WithTickRate(TimeSpan? rate)

Parameters

rate TimeSpan?

Returns

App

WithTimeProvider(TimeProvider)

The clock for ticks, LoadedAt and log timestamps. Tests can pass a fake one.

public App WithTimeProvider(TimeProvider provider)

Parameters

provider TimeProvider

Returns

App