run method
Starts the inline prompt loop and returns a Future containing the final result.
Implementation
Future<T?> run() async {
final termSize = await terminal.size;
final width = termSize.x;
// Autosize the height dynamically if not explicitly specified.
final computedHeight = height ?? widget.getIntrinsicHeight(width);
// Create a temporary buffer and inline renderer.
final buffer = Buffer.blank(width, computedHeight);
final renderer = Renderer(
width,
computedHeight,
mode: RenderingMode.inline,
);
// Mount the widget tree element persistently so states and focus configuration
// are retained between keyboard event loop iterations.
final rootElement = widget.createElement()..mount(null);
void draw() {
// Rebuild the element tree to consume any new state modifications.
final el = rootElement;
if (el is StatefulElement) {
el.rebuild();
} else if (el is StatelessElement) {
el.rebuild();
} else {
try {
(el as dynamic).rebuild();
} catch (_) {}
}
buffer.clear();
// Render the rebuilt element tree on our double buffer canvas.
rootElement.render(buffer, Rect(0, 0, width, computedHeight));
final sb = StringBuffer();
renderer.render(buffer, sb);
if (sb.isNotEmpty) {
terminal.backend.write(sb.toString());
}
}
// Connect the static repainter callback so that inner setState() invocations
// (e.g. from typing inside a TextField) trigger screen updates.
State.onNeedRepaint = draw;
// Initial frame draw
draw();
try {
await for (final event in terminal.events) {
if (event is term.KeyEvent) {
// Cleanly catch Ctrl+C to restore cursor and exit
if (event.key.length == 1 && event.key.codeUnits[0] == 3) {
terminal.showCursor();
exit(0);
}
var isDone = false;
// 1. Let custom interceptor handle the key event first
if (onKeyEvent != null) {
isDone = onKeyEvent!(event);
}
// 2. If not custom-intercepted, route the event down to the focused widgets
if (!isDone) {
_routeKeyEvent(rootElement, event);
}
// 3. Check if we should auto-complete on Enter
if (completeOnEnter &&
(event.key == 'enter' ||
event.key == '\n' ||
event.key == '\r')) {
isDone = true;
}
// Force a redraw to reflect any selections or edits.
draw();
if (isDone) {
break;
}
}
}
} finally {
// Reset the repaint handler to avoid leaks.
State.onNeedRepaint = null;
}
if (onComplete != null) {
return onComplete!();
}
return null;
}