Termina.Generators
0.1.0-beta1
See the version list below for details.
dotnet add package Termina.Generators --version 0.1.0-beta1
NuGet\Install-Package Termina.Generators -Version 0.1.0-beta1
<PackageReference Include="Termina.Generators" Version="0.1.0-beta1" />
<PackageVersion Include="Termina.Generators" Version="0.1.0-beta1" />
<PackageReference Include="Termina.Generators" />
paket add Termina.Generators --version 0.1.0-beta1
#r "nuget: Termina.Generators, 0.1.0-beta1"
#:package Termina.Generators@0.1.0-beta1
#addin nuget:?package=Termina.Generators&version=0.1.0-beta1&prerelease
#tool nuget:?package=Termina.Generators&version=0.1.0-beta1&prerelease
Termina
Termina is a reactive terminal UI (TUI) framework for .NET built on top of Spectre.Console. It provides an MVVM architecture with source-generated reactive properties, ASP.NET Core-style routing, and seamless integration with Microsoft.Extensions.Hosting.
Features
- Reactive MVVM Architecture - ViewModels with
[Reactive]attribute for source-generated observable properties - ASP.NET Core-Style Routing - Route templates with parameters (
/tasks/{id:int}) and type constraints - Source Generators - AOT-compatible code generation for reactive properties and route parameter injection
- Dependency Injection - Full integration with
Microsoft.Extensions.DependencyInjection - Hosting Integration - Works with
Microsoft.Extensions.Hostingfor clean application lifecycle management - Spectre.Console Rendering - Beautiful terminal UIs with full Spectre.Console component support
Installation
dotnet add package Termina
Quick Start
1. Define a ViewModel
using Termina.Reactive;
public partial class CounterViewModel : ReactiveViewModel
{
[Reactive] private int _count;
[Reactive] private string _message = "Press Up/Down to change count";
public override void OnActivated()
{
Input.OfType<KeyPressed>()
.Subscribe(HandleKey)
.DisposeWith(Subscriptions);
}
private void HandleKey(KeyPressed key)
{
switch (key.KeyInfo.Key)
{
case ConsoleKey.UpArrow:
Count++;
Message = $"Count: {Count}";
break;
case ConsoleKey.DownArrow:
Count--;
Message = $"Count: {Count}";
break;
case ConsoleKey.Q:
Shutdown();
break;
}
}
}
The [Reactive] attribute generates:
- A
BehaviorSubject<T>backing field - A public property
Countwith get/set - An
IObservable<T>propertyCountChangedfor subscriptions
2. Define a Page
using Spectre.Console;
using Spectre.Console.Rendering;
using Termina.Pages;
public class CounterPage : ReactivePage<CounterViewModel>
{
protected override IRenderable Render(CounterViewModel vm)
{
return new Panel(
new Rows(
new FigletText(vm.Count.ToString()).Color(Color.Cyan1),
new Text(vm.Message)
))
.Header("Counter Demo")
.Border(BoxBorder.Rounded);
}
}
3. Configure and Run
using Microsoft.Extensions.Hosting;
using Termina.Hosting;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddTermina("/counter", termina =>
{
termina.RegisterRoute<CounterPage, CounterViewModel>("/counter");
termina.RegisterRoute<TodoListPage, TodoListViewModel>("/todos");
termina.RegisterRoute<TodoDetailPage, TodoDetailViewModel>("/todos/{id:int}");
});
await builder.Build().RunAsync();
Routing
Termina uses ASP.NET Core-style route templates with parameter support.
Route Templates
// Simple routes
termina.RegisterRoute<HomePage, HomeViewModel>("/");
termina.RegisterRoute<TasksPage, TasksViewModel>("/tasks");
// Routes with parameters
termina.RegisterRoute<TaskDetailPage, TaskDetailViewModel>("/tasks/{id:int}");
termina.RegisterRoute<UserPage, UserViewModel>("/users/{name}");
termina.RegisterRoute<DocumentPage, DocumentViewModel>("/docs/{id:guid}");
Supported Type Constraints
| Constraint | C# Type | Example |
|---|---|---|
:int |
int |
/tasks/{id:int} |
:guid |
Guid |
/docs/{id:guid} |
:bool |
bool |
/items/{active:bool} |
| (none) | string |
/users/{name} |
Route Parameter Injection
Use [FromRoute] to automatically inject route parameters into your ViewModel:
public partial class TaskDetailViewModel : ReactiveViewModel
{
[FromRoute] private int _id; // Injected from route before OnActivated
public override void OnActivated()
{
// Id property is already populated
LoadTask(Id);
}
}
Navigation
// Navigate by path
Navigate("/tasks/42");
// Navigate with route values (type-safe)
NavigateWithParams("/tasks/{id}", new { id = 42 });
// Go back
// (handled by framework when CanGoBack is true)
Reactive Properties
The [Reactive] attribute on private fields generates observable properties:
public partial class MyViewModel : ReactiveViewModel
{
[Reactive] private string _name = "default";
[Reactive] private int _count;
[Reactive] private IReadOnlyList<Item> _items = Array.Empty<Item>();
}
Generated code provides:
Name,Count,Items- public properties with get/setNameChanged,CountChanged,ItemsChanged-IObservable<T>for subscriptions
Pages automatically re-render when any reactive property changes.
Page Lifecycle
public partial class MyViewModel : ReactiveViewModel
{
public override void OnActivated()
{
// Called when navigating TO this page
// Set up subscriptions here
}
public override void OnDeactivating()
{
// Called when navigating AWAY from this page
// Clean up if needed (Subscriptions auto-dispose)
}
}
Navigation Behavior
Control how pages behave when navigated to:
// Reset state each time (default)
termina.RegisterRoute<MyPage, MyViewModel>("/page", NavigationBehavior.ResetOnNavigation);
// Preserve state across navigations
termina.RegisterRoute<MyPage, MyViewModel>("/page", NavigationBehavior.PreserveState);
Testing
Termina includes VirtualInputSource for automated testing:
var scriptedInput = new VirtualInputSource();
builder.Services.AddTerminaVirtualInput(scriptedInput);
// Queue up scripted input
scriptedInput.EnqueueKey(ConsoleKey.UpArrow);
scriptedInput.EnqueueKey(ConsoleKey.Enter);
scriptedInput.EnqueueKey(ConsoleKey.Q);
scriptedInput.Complete();
await host.RunAsync();
Requirements
- .NET 10.0 or later
- AOT-compatible (Native AOT publishing supported)
License
Apache 2.0 - See LICENSE for details.
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Termina.Generators:
| Package | Downloads |
|---|---|
|
Termina
Reactive terminal UI (TUI) framework for .NET with custom ANSI rendering, MVVM architecture, source-generated reactive properties, and ASP.NET Core-style routing. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.11.0 | 0 | 6/7/2026 |
| 0.10.2 | 2,332 | 5/30/2026 |
| 0.10.1 | 1,352 | 5/24/2026 |
| 0.10.0 | 397 | 5/23/2026 |
| 0.9.0 | 2,401 | 5/18/2026 |
| 0.8.0 | 7,014 | 3/17/2026 |
| 0.7.2 | 1,965 | 3/1/2026 |
| 0.7.1 | 416 | 2/27/2026 |
| 0.7.0 | 120 | 2/26/2026 |
| 0.6.1 | 112 | 2/25/2026 |
| 0.6.0 | 322 | 2/24/2026 |
| 0.5.1 | 488 | 12/19/2025 |
| 0.5.0 | 319 | 12/18/2025 |
| 0.4.0 | 361 | 12/18/2025 |
| 0.3.0 | 297 | 12/17/2025 |
| 0.2.1 | 759 | 12/16/2025 |
| 0.2.0 | 302 | 12/16/2025 |
| 0.1.0 | 327 | 12/16/2025 |
| 0.1.0-beta1 | 140 | 12/12/2025 |
Initial release of Termina - a reactive terminal UI (TUI) framework for .NET.
**Features**:
- Reactive MVVM architecture with source-generated properties
- ASP.NET Core-style routing with parameterized routes and type constraints
- Two-tier event architecture (pages and navigation)
- Virtualizable input support for large datasets
- Built on Spectre.Console for rich terminal rendering
- Full AOT/trimming compatibility