Cameek.GreenScreen 0.1.10

dotnet add package Cameek.GreenScreen --version 0.1.10
                    
NuGet\Install-Package Cameek.GreenScreen -Version 0.1.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cameek.GreenScreen" Version="0.1.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cameek.GreenScreen" Version="0.1.10" />
                    
Directory.Packages.props
<PackageReference Include="Cameek.GreenScreen" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cameek.GreenScreen --version 0.1.10
                    
#r "nuget: Cameek.GreenScreen, 0.1.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cameek.GreenScreen@0.1.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cameek.GreenScreen&version=0.1.10
                    
Install as a Cake Addin
#tool nuget:?package=Cameek.GreenScreen&version=0.1.10
                    
Install as a Cake Tool

Cameek.GreenScreen

Cameek.GreenScreen is a .NET 8 terminal UI framework for full-screen Rich or Classic console applications. It provides controls, keyboard and mouse input, virtualized DataGrid tables, TreeView search, image support, ANSI color fallback, native Windows Console input, Linux PTY hosting, and scoped physical-terminal handoff for foreground interactive commands.

This is a pre-1.0 framework release. Install the core package directly, and add the optional Images package when the application uses PngImage.

dotnet add package Cameek.GreenScreen
dotnet add package Cameek.GreenScreen.Images

Scenarios

  • Full-screen terminal UIs with controls such as panels, labels, buttons, dialogs, menus, text boxes, date/time inputs, typed combo/list selection, radio groups, toggle switches, separators, virtualized data grids, tree views, text areas, scroll views, progress bars, status bars, and log views.
  • Local terminal rendering over ANSI escape sequences.
  • SSH and container terminal sessions where capability detection can be overridden.
  • Interactive PTY-hosted child processes with argument arrays, working directories, environment overrides, resize, output reads, input writes, exit codes, and lifecycle control.
  • Best-effort floating overlays over PTY output without injecting bytes inside UTF-8 or terminal control sequences.
  • Right-aligned menu bars and mirrored left-expanding submenu trees for compact top-right controls.
  • Foreground interactive commands that temporarily own the physical terminal, then return to the same in-memory UI.
  • Background work that reports safely back to the UI loop without making controls thread-safe.
  • Fixed-size status panels written once to normal shell output and retained in scrollback.
  • Responsive terminal-cell layouts with stacks, docks, grids, alignment, margins, padding, and an explicit absolute-positioning escape hatch.
  • Resizable two-pane layouts with keyboard, mouse, collapse, minimum-size, Rich/Classic, and portable-glyph behavior.
  • Declarative application shortcuts with dynamic availability, deterministic contextual fallthrough, and modal isolation.
  • A curated terminal-symbol catalog with deliberate Unicode, SafeUnicode, and ASCII fallbacks for common UI actions and states.
  • An application-level minimum usable viewport guard that preserves UI state while embedded terminals are too small.

Managed Layout And Control Density

Managed layout resolves sizing requests into the same Bounds rectangles used by rendering, hit testing, and focus navigation. Existing controls remain manually positioned by default under ContainerControl, Panel, RichPanel, and the application root. Opt a shell into the root's managed overlay slot, then compose it with layout panels:

var shell = new DockPanel
{
    Positioning = LayoutPositioning.Managed,
    Width = LayoutLength.Fill(),
    Height = LayoutLength.Fill()
};

var actions = new StackPanel
{
    Orientation = Orientation.Horizontal,
    Spacing = 1
};
actions.Add(new RichButton("▶ Run")
{
    Density = ControlDensity.Compact
});

shell.Add(actions, Dock.Bottom);
app.Root.Add(shell);

Every control exposes the common ControlDensity API. Standard preserves existing behavior; Compact reduces default chrome for buttons, single-line inputs, text areas, progress bars, tabs, and tree rows while keeping Rich/Classic rendering independent. Explicit borders and layout properties win, and density does not propagate through arbitrary containers. Managed buttons center vertically by default, Auto panels include border/title geometry, and Canvas always preserves exact child Bounds. See docs/controls.md for the density matrix and docs/layout.md for sizing and container behavior.

DataGrid<T>/RichDataGrid<T> add sticky sortable headers, Auto/Cells/Percent/Fill columns, stable key-based row selection, shared horizontal and vertical scrollbars, and virtual compact row actions. The grid remains one managed leaf control and renders only visible rows; see docs/controls.md.

ComboBox<T>/RichComboBox<T> and ListBox<T>/RichListBox<T> keep typed application models while selecting display text through ItemTextSelector; string convenience types remain available. RadioButtonGroup separates non-visual exclusivity from layout, ToggleSwitch provides stable-width On/Off state, and Separator composes lightweight horizontal or vertical rules. See common controls.

TreeView/RichTreeView support generic cancellable lazy expansion, independently styled expanders/icons/labels, hierarchy guides, node colors, fuzzy search projection, and an opt-in shared vertical scrollbar. SearchBox adds an integrated terminal-aware clear action. FileSystemRoot and FileSystemScope provide multi-root, path-segment-aware existing-path validation with fail-closed link policies. FileBrowser/RichFileBrowser build safe, read-only, lazy filesystem navigation on those foundations and optionally perform bounded, cycle-safe recursive search indexing; FilePickerDialog and FilePicker add modal and integrated field selection while freshly validating both browsed and typed paths. See TreeView controls, FileBrowser, FilePickerDialog, FilePicker, filesystem scope, and API conventions.

TextArea/RichTextArea provide read-only navigation, configurable literal-tab or spaces input, and terminal-cell-aware grapheme cursor, wrapping, scrolling, and source-line rendering. The non-visual FileDocument model adds conservative encoding/newline-preserving text I/O and external-change detection, while per-instance syntax registries provide tolerant YAML, JSON, TOML, XML, INI, and plain-text source spans. FileEditor/RichFileEditor compose those APIs into a one-file editor; MultiFileEditor/RichMultiFileEditor add persistent closeable tabs, duplicate activation, dirty-close protection, Save All, and keyboard document switching. See Editor foundations.

SplitPane/RichSplitPane compose two controls without adding an outer frame. Horizontal means left/right and Vertical means top/bottom. The initial split can use Cells, Percent, Auto, or weighted Fill; keyboard or mouse resizing converts it to an explicit cell position. Pane collapse keeps each control and its view state alive. See SplitPane layout.

Application actions can use KeyGesture, UiCommand, and TerminalApplication.KeyBindings instead of an invisible global-input control. Bindings use exact modifiers, dynamic CanExecute, registration-order fallthrough, and default modal isolation. Control.WantsGlobalInput remains the separate mechanism for control-owned popup and navigation behavior. See application command routing.

Use the curated TerminalSymbols.Preferred catalog when an action or state benefits from a compact glyph. Button.Symbol resolves the selected symbol through the active Unicode/SafeUnicode/ASCII and emoji policy while leaving symbol-free buttons unchanged. See terminal symbols.

Set app.MinimumTerminalSize = new Size(40, 20) to declare the smallest usable viewport. The default Message behavior displays a resize prompt and pauses normal UI layout/input; ClipTopLeft instead lays out at EffectiveLayoutSize = max(physical, minimum) and keeps the physically visible top-left portion interactive. Size always remains the real host-terminal size. See application lifecycle.

Checkboxes And Tabs

CheckBox and RichCheckBox own a two-state boolean value and raise CheckedChanged only when it changes. Space, Enter, or a complete left-click toggles the value.

var validation = new RichCheckBox("Enable validation")
{
    IsChecked = true,
    AccentColor = TerminalColor.Cyan
};

TabControl and RichTabControl own ordinary TabPage containers. Only the selected page is visible and interactive, and its bounds automatically fill the content region. Standard density uses adjacent three-row headers joined to one common content frame; Compact density defaults to a one-row header without a content frame. Explicit HeaderHeight and Border values win.

Set ShowCloseButtons = true and TabPage.CanClose = true to enable semantic close buttons. A complete Down/Up gesture raises cancellable TabClosing, then TabClosed only after successful removal. Narrow header strips keep the selected tab visible and expose portable previous/next overflow cells. Ctrl+Tab and Ctrl+Shift+Tab cycle enabled pages even when focus is in page content.

 ╭──────────╮╭───────────╮
 │ Selected ││ Execution │
╭╯          ╰┴───────────┴──────────╮
var tabs = new RichTabControl { Bounds = new Rect(0, 0, 50, 14) };
var general = new TabPage("General");
general.Add(validation);
var output = new TabPage("Output");
output.Add(new RichLogView());
tabs.AddPage(general);
tabs.AddPage(output);

Rich tab content, content-frame cells, header bodies, and header-frame cells are transparent by default. Set FillBackground = true to restore the filled content surface, FillHeaderBackground = true to fill the Rich button-like header body, or FillHeaderFrameBackground = true to paint beneath header-frame glyphs. These options are independent; generic TabControl content remains filled by default.

One-Shot Shell Blocks

TerminalBlockRenderer.Render renders an existing fixed-size control tree once into sequential shell output. It does not start TerminalApplication, enter the alternate screen, read input, move the cursor, or retain frame history.

var size = new Size(34, 3);
var panel = new Panel { Bounds = new Rect(0, 0, size.Width, size.Height) };
panel.Add(new Label { Bounds = new Rect(0, 0, 32, 1), Text = "Preparation complete" });

new TerminalBlockRenderer().Render(panel, size);

For a deliberately refreshed shell block, RewritePreviousBlock explicitly moves up by the block height, returns to column 1, and writes the same complete serialization. It is intended only for transient states of the immediately preceding logical block. Once unrelated output has been written, that block is scrollback history; append a new wizard step with Render instead. The replacement must have the same dimensions and must not have wrapped. This opt-in operation still does not enter interactive terminal mode.

View-only controls, including AsciiImage and optional PngImage controls, render through their normal ScreenBuffer path. Interactive controls render their current state but receive no input during a one-shot render.

Labels and form-style controls are transparent by default, allowing the parent panel to own their background. Set FillBackground = true when a checkbox, text or masked input, text area, or closed dropdown should fill its interior. FillFrameBackground independently controls framed cells; dropdown popup lists remain opaque.

Terminal Lifecycle

Use SuspendTerminal() when a child must own real stdin, stdout, and stderr. The outermost scope releases GreenScreen's input and alternate screen; disposal reacquires the current terminal size and fully repaints the existing control tree. Ordinary full-screen rendering remains differential while geometry is stable, but size changes and event-level geometry notifications advance an internal epoch and invalidate the physical-frame baseline. A frame is trusted only when size and epoch remain stable through its single write/flush and final commit guard.

using var app = new TerminalApplication();

shellButton.Click += (_, _) =>
{
    using (app.SuspendTerminal())
    {
        using var process = Process.Start(startInfo)
            ?? throw new InvalidOperationException("Failed to start the shell.");
        process.WaitForExit();
    }
};

Keep controls on the UI thread. Use Post to return a background result to the run loop; posted actions run after input dispatch and before Tick in FIFO order.

_ = Task.Run(async () =>
{
    await DoWorkAsync();
    app.Post(_ => status.Text = "Completed");
});

See docs/application-lifecycle.md for launch-after-close, background, foreground handoff, and PTY-managed execution patterns.

Colors

The public drawing model uses TerminalColor instead of ConsoleColor. It supports terminal default colors, ANSI16 colors, indexed 256-color values, and 24-bit RGB truecolor.

buffer.SetHalfBlock(
    x,
    y,
    TerminalColor.Rgb(255, 80, 20),
    TerminalColor.Indexed(45));

AnsiTerminalOptions.ColorMode can be set to Auto, TrueColor, Indexed256, or Ansi16. Auto mode uses conservative environment hints such as COLORTERM=truecolor and TERM=*256color; explicit configuration always wins.

Input Backends

TerminalApplication.InputBackendMode selects how keyboard and mouse input reaches the common TerminalInputEvent model:

  • Auto uses native Windows Console records when a usable Windows console input handle is available; otherwise it uses the ANSI input path.
  • Ansi forces the existing escape-sequence and SGR input path.
  • WindowsConsole requires a usable native Windows Console input handle and throws a clear initialization error when one is unavailable.

Native Windows input enables mouse and resize records while GreenScreen runs, disables Quick Edit for reliable mouse interaction, and restores the exact previous console input mode during cleanup. Controls do not depend on the backend: they receive the same TerminalInputEvent keyboard and mouse abstraction whether the source was ANSI/SGR or Windows Console records.

PTY Hosting

Use PtyProcess for generic child processes. Arguments are passed as an array and are not concatenated through a shell unless you explicitly start a shell yourself.

using var process = PtyProcess.Start(new PtyProcessStartInfo
{
    FileName = "sudo",
    Arguments = { "apt", "install", "kubectl" },
    WorkingDirectory = Environment.CurrentDirectory,
    InitialSize = new Size(120, 32)
});

process.Write("y\n"u8.ToArray());
var exitCode = await process.WaitForExitAsync();

ShellOverlayApplication remains as a convenience shell overlay demo API, but it now sits on top of the generic PTY process layer.

PTY support in this alpha is implemented and tested for Linux. Windows ConPTY and macOS backends are not implemented yet. The task-based ReadAsync and WriteAsync helpers are convenience wrappers over blocking PTY operations; cancellation prevents starting queued work but does not guarantee interruption after the native operation has begun.

Interactive full-screen and host modes require successful raw/no-echo terminal setup. If the original terminal state cannot be captured or raw mode cannot be activated, GreenScreen fails fast instead of continuing in canonical or echoing mode.

Overlays

Overlays are best-effort. GreenScreen tracks PTY output boundaries so it does not inject overlay bytes inside UTF-8 code points, CSI, OSC, DCS, or related string sequences. Overlay changes are versioned, prepared, deferred until a safe child-stream boundary, and committed only after their bytes are written; older commits do not erase newer redraw requests. A replacement draw first clears the previously committed overlay geometry, then draws the new overlay, and then commits the new clear bytes and hit regions. Mouse hit testing follows immutable hit regions from the last committed visible overlay snapshot. It also restores common SGR text attributes after drawing overlays.

This does not make an overlay a protected graphical layer. Full-screen child applications can clear or redraw the same screen area. Suspend overlay rendering for programs such as editors, pagers, nested SSH sessions, and full-screen installers.

InteractiveProcessHost.SuspendOverlay() exposes a scoped public rendering suspension mechanism. It pauses and clears overlay rendering while the scope is alive; draw requests may coalesce while suspended, and the latest state redraws when the outermost scope is disposed. It is not a transparent input handoff mode: normal host input routing and configured mouse forwarding still apply.

The input parser maps common keyboard, mouse, CSI, and SS3 sequences to TerminalInputEvent. Unsupported but syntactically complete terminal control sequences are consumed safely and ignored rather than leaking trailing bytes as typed text.

TabIndex defines wrapping logical navigation for Tab and Shift+Tab. Applications can opt into Spatial, Sequential, or Classic arrow strategies with UseArrowKeysForFocusNavigation = true; focused controls receive arrows first, so single-line TextBox controls retain Left/Right cursor editing while unhandled arrows can move focus. See docs/navigation.md.

MenuBar supports explicit nested submenu activation. Moving selection with Up/Down does not open child menus; branch items show a directional indicator and open with the expansion-direction arrow, Enter, or Space. MenuBar.Alignment = MenuBarAlignment.Right right-aligns top-level items, and SubmenuDirection = SubmenuExpansionDirection.Left creates mirrored left-expanding submenu trees for compact controls near the right edge.

Unicode

Text measurement, clipping, and WriteText share one grapheme-based terminal-cell metric path. Compact text symbols remain one cell; a checked-in Unicode Emoji 16.0 BMP presentation table, VS16, the practical supplementary emoji range, and emoji ZWJ graphemes provide deterministic two-cell rules. Selectors and combining marks do not independently add cells, and a wide text element is never partially written into a one-cell remainder. This is not a complete Unicode terminal-width engine: CJK, East Asian ambiguous width, complex shaping, and terminal/font-specific presentation remain compatibility-sensitive. TextBox editing still uses UTF-16 string indexes and is optimized for typical Latin input. See docs/unicode.md.

Examples

  • Cameek.GreenScreen.Gallery - the main control gallery, theme playground, Unicode diagnostics, images and safe in-memory/scoped workflows.
  • Cameek.GreenScreen.TerminalLab - exclusive shell/PTY, terminal handoff, JSONL and scrollback scenarios.

The 26 old example executables are now two. The core and Images packages, tests, PTY test host and package-smoke consumer remain separate. See the complete example migration map for every preserved scenario.

dotnet run --project Cameek.GreenScreen.Gallery -- --list
dotnet run --project Cameek.GreenScreen.Gallery -- --demo themes
dotnet run --project Cameek.GreenScreen.Gallery -- --demo live-grid
dotnet run --project Cameek.GreenScreen.Gallery -- --diagnostics
dotnet run --project Cameek.GreenScreen.Gallery -- --glyph-probe
dotnet run --project Cameek.GreenScreen.TerminalLab -- --list
dotnet run --project Cameek.GreenScreen.TerminalLab -- --scenario pty-stress

Theme Playground uses F2 for Dark/Light/GreenScreen/HighContrast, F4 for Rich/Classic, F6 for glyph mode, F8 for emoji fallback, and F9 for color output. These controls are also clickable; F2 works while a dialog/dropdown is open. Mock kill buttons only update demo data/logs. Edited fields, focus and selections survive theme changes.

Applications opt into themes with app.Theme = GreenScreenThemes.Light. Omitting a theme preserves legacy appearance. Native Windows console output receives scoped UTF-8 and VT setup; custom writers and Auto redirected output are preserved. See output policy and host verification before interpreting font/emoji differences as transport errors.

Build, Test, Pack

dotnet build Cameek.GreenScreen.sln -c Release
dotnet test Cameek.GreenScreen.Tests/Cameek.GreenScreen.Tests.csproj -c Release
dotnet pack Cameek.GreenScreen/Cameek.GreenScreen.csproj -c Release -o artifacts/nuget
dotnet pack Cameek.GreenScreen.Images/Cameek.GreenScreen.Images.csproj -c Release -o artifacts/nuget

Release scripts live in .scripts. Use .scripts/tag-latest-version.sh to tag the current version, or .scripts/increase-and-tag-version.sh --patch to bump, commit, push, and tag. Pushed vA.B.C tags trigger NuGet publishing.

Platform-specific PTY tests are written to pass without requiring root or sudo and skip their body when PTY support is unavailable.

Documentation

See:

  • docs/themes.md
  • docs/examples-migration.md
  • docs/implementation-report.md
  • docs/architecture.md
  • docs/terminal-colors.md
  • docs/rgb-surfaces.md
  • docs/pty.md
  • docs/overlays.md
  • docs/compatibility.md
  • docs/unicode.md
  • docs/application-lifecycle.md
  • docs/layout.md
  • docs/controls.md
  • docs/manual-smoke-test.md
  • docs/editor-foundation.md

License

Licensed under the MIT License. See the LICENSE file for full details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Cameek.GreenScreen:

Package Downloads
Cameek.GreenScreen.Images

Optional PNG image support for Cameek.GreenScreen.

Cameek.Run67.Tool

Human-first terminal workflow runner with planning, approvals, durable Run Records, interactive terminal execution, and resume support.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.10 176 9/12/2026
0.1.9 163 9/3/2026
0.1.7 130 9/3/2026
0.1.6 132 9/2/2026
0.1.5 217 8/7/2026
0.1.4 209 7/15/2026
0.1.3 146 7/15/2026
0.1.1 149 7/14/2026
0.0.1 127 7/5/2026