// Example demonstrating the Prompt API for getting typed input from users // NOTE: See https://github.com/tui-cs/clet that turns every Terminal.Gui View into a CLI command // NOTE: — typed inputs, a real file picker, a Markdown viewer — with consistent JSON output, // NOTE: predictable exit codes, and full keyboard/mouse support. Works for humans and AI agents alike. using Terminal.Gui.App; using Terminal.Gui.Configuration; using Terminal.Gui.Drawing; using Terminal.Gui.Drivers; using Terminal.Gui.Editor; using Terminal.Gui.Resources; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; using Color = Terminal.Gui.Drawing.Color; // ReSharper disable AccessToDisposedClosure var smokeTest = args.Length > 0 && args [0] == "--smoke-test"; if (smokeTest) { ConfigurationManager.Enable (ConfigLocations.All); using IApplication smokeApp = Application.Create ().Init (); Console.WriteLine ("Smoke test passed."); return; } ConfigurationManager.Enable (ConfigLocations.All); using IApplication app = Application.Create ().Init (DriverRegistry.Names.DOTNET); // Create a main window to host the prompts using Window mainWindow = new (); mainWindow.Title = "Prompt API Examples (Esc to quit)"; mainWindow.Text = "This example demonstrates various uses of the Prompt API.\nPress the buttons to try different prompt types.\nPress Esc to quit."; mainWindow.TextAlignment = Alignment.Center; // Initial Value TextField — entered text is applied to prompt views via IValue.TrySetValueFromString TextField initialValueField = new () { Title = "Initial _Value (TrySetValueFromString)", X = 0, Y = 0, Width = Dim.Fill (), BorderStyle = LineStyle.Dotted }; mainWindow.Add (initialValueField); var buttonY = 2; // Example 1: TextField with string result using auto-Text extraction Button textFieldButton = new () { Title = "TextField (Auto-Text)", X = Pos.Center (), Y = buttonY++ }; textFieldButton.Accepting += (_, _) => { var result = mainWindow.Prompt (beginInitHandler: prompt => { prompt.Title = textFieldButton.Title; prompt.GetWrappedView ().Width = 40; prompt.GetWrappedView ().Text = "Default name"; if (!string.IsNullOrEmpty (initialValueField.Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField.Text); } }); MessageBox.Query (app, textFieldButton.Title, result is not null ? $"You entered: {result}" : "Canceled", Strings.btnOk); }; mainWindow.Add (textFieldButton); // Example 1: TextField with string result using auto-Text extraction Button editorButton = new () { Title = "Editor (Auto-Text)", X = Pos.Center (), Y = buttonY++ }; editorButton.Accepting += (_, _) => { var result = mainWindow.Prompt (beginInitHandler: prompt => { prompt.Title = editorButton.Title; prompt.GetWrappedView ().Text = "Some text\nis nice."; prompt.GetWrappedView ().Width = Dim.Fill (0, 40); prompt.GetWrappedView ().Height = Dim.Fill (0, 8); if (!string.IsNullOrEmpty (initialValueField.Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField.Text); } }); MessageBox.Query (app, editorButton.Title, result is not null ? $"You entered: {result}" : "Canceled", Strings.btnOk); }; mainWindow.Add (editorButton); // Example 2: DatePicker with DateTime result Button datePickerButton = new () { Title = "DatePicker (Typed Result)", X = Pos.Center (), Y = buttonY++ }; datePickerButton.Accepting += (_, _) => { DateTime? result = mainWindow.Prompt (resultExtractor: dp => dp.Value, beginInitHandler: prompt => { prompt.Title = "Select a Date"; prompt.GetWrappedView ().Value = DateTime.Now; if (!string.IsNullOrEmpty (initialValueField.Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField.Text); } }); if (result is { } selectedDate) { MessageBox.Query (app, datePickerButton.Title, $"You selected: {selectedDate:yyyy-MM-dd}", Strings.btnOk); } else { MessageBox.Query (app, datePickerButton.Title, "Canceled", Strings.btnOk); } }; mainWindow.Add (datePickerButton); // Example 3: ColorPicker with Color result Button colorPickerButton = new () { Title = "ColorPicker (Typed Result)", X = Pos.Center (), Y = buttonY++ }; colorPickerButton.Accepting += (_, _) => { Color? result = mainWindow.Prompt (input: null, beginInitHandler: prompt => { prompt.Title = "Pick a Color"; if (!string.IsNullOrEmpty (initialValueField.Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField.Text); } }); if (result is { } selectedColor) { MessageBox.Query (app, colorPickerButton.Title, $"You selected: {selectedColor}", Strings.btnOk); } else { MessageBox.Query (app, colorPickerButton.Title, "Canceled", Strings.btnOk); } }; mainWindow.Add (colorPickerButton); // Example 4: ColorPicker with auto-Text extraction Button colorTextButton = new () { Title = "ColorPicker (Auto-Text)", X = Pos.Center (), Y = buttonY++ }; colorTextButton.Accepting += (_, _) => { var result = mainWindow.Prompt (beginInitHandler: prompt => { prompt.Title = "Pick a Color (as text)"; prompt.GetWrappedView ().SelectedColor = Color.Red; if (!string.IsNullOrEmpty (initialValueField.Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField.Text); } }); MessageBox.Query (app, colorTextButton.Title, result is not null ? $"Color as text: {result}" : "Canceled", Strings.btnOk); }; mainWindow.Add (colorTextButton); // Example 5: Pre-created view Button preCreatedButton = new () { Title = "Pre-Created TextField", X = Pos.Center (), Y = buttonY++ }; preCreatedButton.Accepting += (_, _) => { // Pre-create and configure the view TextField textField = new () { Width = 50, Text = "Pre-configured text" }; var result = mainWindow.Prompt (textField, field => field.Text, beginInitHandler: prompt => { prompt.Title = preCreatedButton.Title; prompt.BorderStyle = LineStyle.Rounded; }); if (result is not null) { MessageBox.Query (app, preCreatedButton.Title, $"You entered: {result}", Strings.btnOk); } }; mainWindow.Add (preCreatedButton); // Example 6: Custom form with complex result extraction Button customFormButton = new () { Title = "Custom Form", X = Pos.Center (), Y = buttonY++ }; customFormButton.Accepting += (_, _) => { View formView = CreateCustomForm (); FormData? result = mainWindow.Prompt (formView, ExtractFormData, beginInitHandler: prompt => { prompt.Title = "User Information Form"; }); if (result is not null) { MessageBox.Query (app, customFormButton.Title, $"Name: {result.Name}\nAge: {result.Age}\nAgreed: {result.Agreed}", Strings.btnOk); } else { MessageBox.Query (app, "Form canceled", Strings.btnOk); } }; mainWindow.Add (customFormButton); // Example 7: FlagSelector with enum result Button flagSelectorButton = new () { Title = "FlagSelector (Enum Result)", X = Pos.Center (), Y = buttonY++ }; flagSelectorButton.Accepting += (_, _) => { SelectorStyles? result = mainWindow.Prompt, SelectorStyles> (resultExtractor: fs => fs.Value!.Value, beginInitHandler: prompt => { prompt.Title = "Choose Selector Styles"; if (!string.IsNullOrEmpty (initialValueField .Text)) { ((IValue)prompt.GetWrappedView ()) .TrySetValueFromString (initialValueField .Text); } }); if (result is { } styles) { MessageBox.Query (app, flagSelectorButton.Title, $"Selected styles: {styles}", Strings.btnOk); } else { MessageBox.Query (app, flagSelectorButton.Title, "Canceled", Strings.btnOk); } }; mainWindow.Add (flagSelectorButton); // Add a quit button Button quitButton = new () { Title = "Quit", X = Pos.Center (), Y = Pos.AnchorEnd () }; quitButton.Accepting += (_, _) => app.RequestStop (); mainWindow.Add (quitButton); app.Run (mainWindow); return; // Helper method to create a custom form View CreateCustomForm () { View form = new () { Width = 50, Height = 10 }; TextField nameField = new () { Id = "nameField", X = 10, Y = 1, Width = 30 }; TextField ageField = new () { Id = "ageField", X = 10, Y = 3, Width = 10 }; CheckBox agreeCheckbox = new () { Id = "agreeCheckbox", Title = "I agree to terms", X = 10, Y = 5 }; form.Add (new Label { Text = "Name:", X = 2, Y = 1 }); form.Add (nameField); form.Add (new Label { Text = "Age:", X = 2, Y = 3 }); form.Add (ageField); form.Add (agreeCheckbox); return form; } // Helper method to extract data from the custom form FormData ExtractFormData (View form) { TextField? nameField = form.SubViews.FirstOrDefault (v => v.Id == "nameField") as TextField; TextField? ageField = form.SubViews.FirstOrDefault (v => v.Id == "ageField") as TextField; CheckBox? agreeCheckbox = form.SubViews.FirstOrDefault (v => v.Id == "agreeCheckbox") as CheckBox; return new FormData { Name = nameField?.Text ?? string.Empty, Age = int.TryParse (ageField?.Text, out var age) ? age : 0, Agreed = agreeCheckbox?.Value == CheckState.Checked }; } // Result type for custom form internal record FormData { public int Age { get; init; } public bool Agreed { get; init; } public string Name { get; init; } = string.Empty; }