Files
ttui/test/TinyTUI.ComponentChecks/Program.cs
T
chuan 41c0d91d77 feat: add autocomplete foundation
- add reusable autocomplete provider contracts

- integrate slash command completions with editor select list
2026-06-04 02:23:06 +08:00

83 lines
3.8 KiB
C#

using TinyTUI.Components;
using TinyTUI.Autocomplete;
using TinyTUI.Input;
using TinyTUI.Rendering;
using TinyTUI.Text;
var measurer = new TerminalTextMeasurer();
var input = new Input(measurer) { Prompt = "> " };
AssertFalse(input.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "unfocused input marker");
input.Focused = true;
AssertTrue(input.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "focused input marker");
var editor = new Editor(measurer) { Placeholder = "type here" };
AssertFalse(editor.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "unfocused editor marker");
editor.Focused = true;
AssertTrue(editor.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "focused editor marker");
var list = new SelectList(measurer);
list.SetItems(["alpha", "beta"]);
AssertFalse(list.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "unfocused select marker");
list.Focused = true;
AssertTrue(list.Render(20)[0].Contains(CursorMarker.Marker, StringComparison.Ordinal), "focused select marker");
AssertEqual(3, new Spacer(3).Render(10).Count, "spacer line count");
AssertEqual(0, new Spacer(-1).Render(10).Count, "spacer clamps negative lines");
var truncated = new TruncatedText("abcdef\nignored", measurer)
{
PaddingX = 1,
PaddingY = 1,
};
var truncatedLines = truncated.Render(6);
AssertEqual(3, truncatedLines.Count, "truncated text vertical padding");
AssertEqual(6, measurer.GetWidth(truncatedLines[1]), "truncated text padded width");
AssertTrue(truncatedLines[1].Contains("abc", StringComparison.Ordinal), "truncated text first line only");
var loader = new CancellableLoader(keybindings: KeybindingRegistry.CreateDefault());
var canceled = false;
loader.OnCanceled = () => canceled = true;
loader.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Escape));
AssertTrue(loader.IsCanceled, "cancellable loader token");
AssertTrue(canceled, "cancellable loader callback");
var autocompleteEditor = new Editor(measurer)
{
AutocompleteProvider = new SlashCommandAutocompleteProvider(
[
new SlashCommand("help", "show help"),
new SlashCommand("history", "show history"),
]),
};
autocompleteEditor.HandleInput(new TuiInputEvent(TuiInputEventKind.Text, "/h"));
AssertTrue(autocompleteEditor.IsAutocompleteActive, "slash command autocomplete active");
AssertTrue(autocompleteEditor.RenderAutocomplete(40).Any(line => line.Contains("help", StringComparison.Ordinal)), "slash command autocomplete render");
autocompleteEditor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Down));
autocompleteEditor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Tab));
AssertEqual("/history ", autocompleteEditor.Value, "slash command autocomplete confirm");
AssertFalse(autocompleteEditor.IsAutocompleteActive, "slash command autocomplete closes after confirm");
autocompleteEditor.Value = "/h";
autocompleteEditor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Tab));
AssertTrue(autocompleteEditor.IsAutocompleteActive, "forced autocomplete active");
autocompleteEditor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Escape));
AssertFalse(autocompleteEditor.IsAutocompleteActive, "autocomplete cancel");
AssertEqual("/h", autocompleteEditor.Value, "autocomplete cancel keeps text");
Console.WriteLine("TinyTUI component checks passed");
static void AssertEqual<T>(T expected, T actual, string name)
{
if (!EqualityComparer<T>.Default.Equals(expected, actual))
throw new InvalidOperationException($"{name}: expected '{expected}', actual '{actual}'");
}
static void AssertTrue(bool condition, string name)
{
if (!condition)
throw new InvalidOperationException($"{name}: assertion failed");
}
static void AssertFalse(bool condition, string name) => AssertTrue(!condition, name);