* Initial plan * Refactor Application.Mouse - Create IMouse interface and Mouse implementation Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add enhanced documentation for Application.Mouse property Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add parallelizable unit tests for IMouse interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor Application.Mouse for decoupling and parallelism Co-authored-by: tig <585482+tig@users.noreply.github.com> * Move HandleMouseGrab method to IMouseGrabHandler interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add parallelizable tests for IMouse and IMouseGrabHandler interfaces Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add MouseEventRoutingTests - 27 parallelizable tests for View mouse event handling Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix terminology: Replace parent/child with superView/subView in MouseEventRoutingTests Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix coding standards: Use explicit types and target-typed new() in test files Co-authored-by: tig <585482+tig@users.noreply.github.com> * Update coding standards documentation with explicit var and target-typed new() guidance Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor Application classes and improve maintainability Refactored `Sixel` property to be immutable, enhancing thread safety. Cleaned up `ApplicationImpl` by removing redundant fields, restructuring methods (`CreateDriver`, `CreateSubcomponents`), and improving exception handling. Updated `Run<T>` and `Shutdown` methods for consistency. Standardized logging/debugging messages and fixed formatting issues. Reorganized `IApplication` interface, added detailed XML documentation, and grouped related methods logically. Performed general code cleanup, including fixing typos, improving readability, and removing legacy/unnecessary code to reduce technical debt. * Code cleanup * Remove unreferenced LayoutAndDraw method from ApplicationImpl * Code cleanup and TODOs - Updated namespaces to reflect the new structure. - Added `Driver`, `Force16Colors`, and `ForceDriver` properties. - Introduced `Sixel` collection for sixel image management. - Added lifecycle methods: `GetDriverTypes`, `Shutdown`, and events. - Refactored `Init` to support legacy and modern drivers. - Improved driver event handling and screen abstraction. - Updated `Run` method to align with the application lifecycle. - Simplified `IConsoleDriver` documentation. - Removed redundant methods and improved code readability. * Refactor LayoutAndDraw logic for better encapsulation Refactored `Application.Run` to delegate `LayoutAndDraw` to `ApplicationImpl.Instance.LayoutAndDraw`, improving separation of concerns. Renamed `forceDraw` to `forceRedraw` for clarity and moved `LayoutAndDraw` implementation to `ApplicationImpl`. Added a new `LayoutAndDraw` method in `ApplicationImpl` to handle layout and drawing, including managing `TopLevels`, handling active popovers, and refreshing the screen. Updated the `IApplication` interface to reflect the new method and improved its documentation. Implemented `RequestStop` in `ApplicationImpl` and fixed formatting inconsistencies in `Run<T>`. Added TODOs for future refactoring to encapsulate `Top` and `TopLevels` into an `IViewHierarchy` and move certain properties to `IApplication`. * Refactor ApplicationImpl to enhance mouse and keyboard support Added a new `Mouse` property to the `ApplicationImpl` class, replacing its previous declaration, to improve mouse functionality. Updated `MouseGrabHandler` to initialize with a default instance of `MouseGrabHandler`. Added comments to ensure the preservation of existing keyboard settings (`QuitKey`, `ArrangeKey`, `NextTabKey`) for backward compatibility. These changes enhance clarity, functionality, and maintainability of the class. * Merge IMouseGrabHandler into IMouse - consolidate mouse handling into single interface Co-authored-by: tig <585482+tig@users.noreply.github.com> * Rename Mouse to MouseImpl and Keyboard to KeyboardImpl for consistency Co-authored-by: tig <585482+tig@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tig <585482+tig@users.noreply.github.com> Co-authored-by: Tig <tig@users.noreply.github.com>
11 KiB
Terminal.Gui - Copilot Coding Agent Instructions
This file provides onboarding instructions for GitHub Copilot and other AI coding agents working with Terminal.Gui.
Project Overview
Terminal.Gui is a cross-platform UI toolkit for creating console-based graphical user interfaces in .NET. It's a large codebase (~1,050 C# files, 333MB) providing a comprehensive framework for building interactive console applications with support for keyboard and mouse input, customizable views, and a robust event system.
Key characteristics:
- Language: C# (net8.0)
- Size: ~496 source files in core library, ~1,050 total C# files
- Platform: Cross-platform (Windows, macOS, Linux)
- Architecture: Console UI toolkit with driver-based architecture
- Version: v2 (Alpha), v1 (maintenance mode)
- Branching: GitFlow model (v2_develop is default/active development)
Building and Testing
Required Tools
- .NET SDK: 8.0.0 (see
global.json) - Runtime: .NET 8.x (latest GA)
- Optional: ReSharper/Rider for code formatting
Build Commands (In Order)
ALWAYS run these commands from the repository root:
-
Restore packages (required first, ~15-20 seconds):
dotnet restore -
Build solution (Debug, ~50 seconds):
dotnet build --configuration Debug --no-restore- Expect ~326 warnings (nullable reference warnings, unused variables, etc.) - these are normal
- 0 errors expected
-
Build Release (for packaging):
dotnet build --configuration Release --no-restore
Test Commands
Two test projects exist:
-
Non-parallel tests (depend on static state, ~10 min timeout):
dotnet test Tests/UnitTests --no-build --verbosity normal- Uses
Application.Initand static state - Cannot run in parallel
- Includes
--blameflags for crash diagnostics
- Uses
-
Parallel tests (can run concurrently, ~10 min timeout):
dotnet test Tests/UnitTestsParallelizable --no-build --verbosity normal- No dependencies on static state
- Preferred for new tests
-
Integration tests:
dotnet test Tests/IntegrationTests --no-build --verbosity normal
Important: Tests may take significant time. CI uses blame flags for crash detection:
--diag:logs/UnitTests/logs.txt --blame --blame-crash --blame-hang --blame-hang-timeout 60s --blame-crash-collect-always
Running Examples
UICatalog (comprehensive demo app):
dotnet run --project Examples/UICatalog/UICatalog.csproj
Repository Structure
Root Directory Files
Terminal.sln- Main solution fileTerminal.sln.DotSettings- ReSharper code style settings.editorconfig- Code formatting rules (111KB, extensive)global.json- .NET SDK version pinningDirectory.Build.props- Common MSBuild propertiesDirectory.Packages.props- Central package version managementGitVersion.yml- Version numbering configurationAGENTS.md- General AI agent instructions (also useful reference)CONTRIBUTING.md- Contribution guidelinesREADME.md- Project documentation
Main Directories
/Terminal.Gui/ - Core library (496 C# files):
App/- Application lifecycle (Application.csstatic class,RunState,MainLoop)Configuration/-ConfigurationManagerfor settingsDrivers/- Console driver implementations (IConsoleDriver,NetDriver,UnixDriver,WindowsDriver)Drawing/- Rendering system (attributes, colors, glyphs)Input/- Keyboard and mouse input handlingViewBase/- CoreViewclass hierarchy and layoutViews/- Specific View subclasses (Window, Dialog, Button, ListView, etc.)Text/- Text manipulation and formatting
/Tests/:
UnitTests/- Non-parallel tests (useApplication.Init, static state)UnitTestsParallelizable/- Parallel tests (no static dependencies)IntegrationTests/- Integration testsStressTests/- Long-running stress tests (scheduled daily)coverlet.runsettings- Code coverage configuration
/Examples/:
UICatalog/- Comprehensive demo app for manual testingExample/- Basic exampleNativeAot/,SelfContained/- Deployment examplesReactiveExample/,CommunityToolkitExample/- Integration examples
/docfx/ - Documentation source:
docs/- Conceptual documentation (deep dives)api/- Generated API docs (gitignored)docfx.json- DocFX configuration
/Scripts/ - PowerShell build utilities (requires PowerShell 7.4+)
/.github/workflows/ - CI/CD pipelines:
unit-tests.yml- Main test workflow (Ubuntu, Windows, macOS)build-release.yml- Release build verificationintegration-tests.yml- Integration test workflowpublish.yml- NuGet package publishingapi-docs.yml- Documentation building and deploymentcodeql-analysis.yml- Security scanning
Code Style and Quality
Formatting
- Do NOT add formatting tools - Use existing
.editorconfigandTerminal.sln.DotSettings - Format code with:
- ReSharper/Rider (
Ctrl-E-C) - JetBrains CleanupCode CLI tool (free)
- Visual Studio (
Ctrl-K-D) as fallback
- ReSharper/Rider (
- Only format files you modify
Code Style Tenets
- Six-Year-Old Reading Level - Readability over terseness
- Consistency, Consistency, Consistency - Follow existing patterns ruthlessly
- Don't be Weird - Follow Microsoft/.NET conventions
- Set and Forget - Rely on automated tooling
- Documentation is the Spec - API docs are source of truth
Coding Conventions
⚠️ CRITICAL - These rules MUST be followed in ALL new code:
Type Declarations and Object Creation
-
ALWAYS use explicit types - Never use
varexcept for basic types (int,string,bool,double,float,decimal,char,byte)// ✅ CORRECT - Explicit types View view = new () { Width = 10 }; MouseEventArgs args = new () { Position = new Point(5, 5) }; List<View?> views = new (); var count = 0; // OK - int is a basic type var name = "test"; // OK - string is a basic type // ❌ WRONG - Using var for non-basic types var view = new View { Width = 10 }; var args = new MouseEventArgs { Position = new Point(5, 5) }; var views = new List<View?>(); -
ALWAYS use target-typed
new()- Usenew ()instead ofnew TypeName()when the type is already declared// ✅ CORRECT - Target-typed new View view = new () { Width = 10 }; MouseEventArgs args = new (); // ❌ WRONG - Redundant type name View view = new View() { Width = 10 }; MouseEventArgs args = new MouseEventArgs();
Other Conventions
- Follow
.editorconfigsettings (e.g., braces on new lines, spaces after keywords) - 4-space indentation
- No trailing whitespace
- See
CONTRIBUTING.mdfor full guidelines
These conventions apply to ALL code - production code, test code, examples, and samples.
Testing Requirements
Code Coverage
- Never decrease code coverage - PRs must maintain or increase coverage
- Target: 70%+ coverage for new code
- CI monitors coverage on each PR
Test Patterns
- Parallelizable tests preferred - Add new tests to
UnitTestsParallelizablewhen possible - Avoid static dependencies - Don't use
Application.Init,ConfigurationManagerin tests - Don't use
[AutoInitShutdown]- Legacy pattern, being phased out - Make tests granular - Each test should cover smallest area possible
- Follow existing test patterns in respective test projects
Test Configuration
xunit.runner.json- xUnit configurationcoverlet.runsettings- Coverage settings (OpenCover format)
API Documentation Requirements
All public APIs MUST have XML documentation:
- Clear, concise
<summary>tags - Use
<see cref=""/>for cross-references - Add
<remarks>for context - Include
<example>for non-obvious usage - Complex topics →
docfx/docs/*.mdfiles - Proper English and grammar
Common Build Issues
Issue: Build Warnings
- Expected: ~326 warnings (nullable refs, unused vars, xUnit suggestions)
- Action: Don't add new warnings; fix warnings in code you modify
Issue: Test Timeouts
- Expected: Tests can take 5-10 minutes
- Action: Use appropriate timeout values (60-120 seconds for test commands)
Issue: Restore Failures
- Solution: Ensure
dotnet restorecompletes before building - Note: Takes 15-20 seconds on first run
Issue: NativeAot/SelfContained Build
- Solution: Restore these projects explicitly:
dotnet restore ./Examples/NativeAot/NativeAot.csproj -f dotnet restore ./Examples/SelfContained/SelfContained.csproj -f
CI/CD Validation
The following checks run on PRs:
-
Unit Tests (
unit-tests.yml):- Runs on Ubuntu, Windows, macOS
- Both parallel and non-parallel test suites
- Code coverage collection
- 10-minute timeout per job
-
Build Release (
build-release.yml):- Verifies Release configuration builds
- Tests NativeAot and SelfContained builds
- Packs NuGet package
-
Integration Tests (
integration-tests.yml):- Cross-platform integration testing
- 10-minute timeout
-
CodeQL Analysis (
codeql-analysis.yml):- Security vulnerability scanning
To replicate CI locally:
# Full CI sequence:
dotnet restore
dotnet build --configuration Debug --no-restore
dotnet test Tests/UnitTests --no-build --verbosity normal
dotnet test Tests/UnitTestsParallelizable --no-build --verbosity normal
dotnet build --configuration Release --no-restore
Branching and PRs
GitFlow Model
v2_develop- Default branch, active developmentv2_release- Stable releases, matches NuGetv1_develop,v1_release- Legacy v1 (maintenance only)
PR Requirements
- Title: "Fixes #issue. Terse description"
- Description: Include "- Fixes #issue" for each issue
- Tests: Add tests for new functionality
- Coverage: Maintain or increase code coverage
- Scenarios: Update UICatalog scenarios when adding features
Key Architecture Concepts
View System
Viewbase class in/Terminal.Gui/ViewBase/- Two layout modes: Absolute and Computed
- Event-driven architecture
- Adornments: Border, Margin, Padding
Console Drivers
IConsoleDriverinterface- Platform-specific:
WindowsDriver,UnixDriver,NetDriver FakeDriverfor testing
Application Lifecycle
Applicationstatic class manages lifecycleMainLoophandles event processingRunStatetracks application state
What NOT to Do
- ❌ Don't add new linters/formatters (use existing)
- ❌ Don't modify unrelated code
- ❌ Don't remove/edit unrelated tests
- ❌ Don't break existing functionality
- ❌ Don't add tests to
UnitTestsif they can be parallelizable - ❌ Don't use
Application.Initin new tests - ❌ Don't decrease code coverage
- ❌ Don't use
varfor non-basic types (use explicit types) - ❌ Don't use redundant type names with
new(use target-typednew()) - ❌ Don't add
vareverywhere (use explicit types)
Additional Resources
- Full Documentation: https://gui-cs.github.io/Terminal.Gui
- API Reference: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.App.html
- Deep Dives:
/docfx/docs/directory - AGENTS.md: Additional AI agent instructions
- CONTRIBUTING.md: Detailed contribution guidelines
Trust these instructions. Only search for additional information if instructions are incomplete or incorrect.