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
LastFrame
Numbers about the last frame drawn; default before the first one.
public FrameStats LastFrame { get; }
Property Value
Log
Lines written to the console while the app runs (see CaptureConsoleOutput(bool)).
public LogBuffer Log { get; }
Property Value
MenuBar
The menu bar, or null.
public MenuBar? MenuBar { get; }
Property Value
Overlays
Modal overlays and dialogs, drawn over the screens (or over the Render(Action<Buffer, Rect>) output).
public OverlayStack Overlays { get; }
Property Value
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
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
Size
The terminal size in cells, or (0, 0) when the app isn't running.
public (int Width, int Height) Size { get; }
Property Value
Stopping
Cancelled when Quit() is called or the loop exits. Pass it to background work.
public CancellationToken Stopping { get; }
Property Value
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
Toasts
Toasts the app draws in the top-right corner, over everything else.
public ToastQueue Toasts { get; }
Property Value
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
capturebool
Returns
Create()
Create a new App builder.
public static App Create()
Returns
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
handlerFunc<Exception, ErrorAction>
Returns
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
Returns
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
handlerFunc<ConsoleKeyInfo, bool>
Returns
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
handlerFunc<MouseEvent, bool>
Returns
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
Returns
OnSetup(Action)
Set up code to run once on the UI thread before the first frame.
public App OnSetup(Action setup)
Parameters
setupAction
Returns
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
Returns
OnUpdate(Action)
Configure update logic that runs on every loop iteration, before rendering.
public App OnUpdate(Action update)
Parameters
updateAction
Returns
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
actionAction
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
quitbool
Returns
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
Returns
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
cancellationTokenCancellationToken
Returns
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
workFunc<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
actionAction
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
backendITerminalBackend
Returns
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
Returns
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
enabledbool
Returns
WithColorMode(ColorMode)
Override the detected color mode of the default console backend.
public App WithColorMode(ColorMode mode)
Parameters
modeColorMode
Returns
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
Returns
Exceptions
- FormatException
keyisn'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
intervalTimeSpan
Returns
Exceptions
- ArgumentOutOfRangeException
intervalis 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
enabledbool
Returns
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
inputIInputSource
Returns
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
enabledbool
Returns
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
menuBarMenuBar
Returns
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
enabledbool
Returns
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
enabledbool
Returns
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
enabledbool
Returns
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
themeTheme
Returns
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
Returns
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
rateTimeSpan?
Returns
WithTimeProvider(TimeProvider)
The clock for ticks, LoadedAt and log timestamps. Tests can pass a fake one.
public App WithTimeProvider(TimeProvider provider)
Parameters
providerTimeProvider