Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:
outputs:
version: ${{ steps.version.outputs.version }}
prerelease: ${{ steps.version.outputs.prerelease }}
terminal_version: ${{ steps.version.outputs.terminal_version }}
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -70,7 +69,6 @@ jobs:

"version=$tagVersion" >> $env:GITHUB_OUTPUT
"prerelease=$($tagVersion.Contains('-').ToString().ToLowerInvariant())" >> $env:GITHUB_OUTPUT
"terminal_version=$terminalVersion" >> $env:GITHUB_OUTPUT

runtime:
needs: metadata
Expand Down Expand Up @@ -180,6 +178,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: ${{ env.PACKAGE_ARTIFACT }}
Expand All @@ -202,19 +201,12 @@ jobs:
GH_REPO: ${{ github.repository }}
run: |
$version = '${{ needs.metadata.outputs.version }}'
$terminalVersion = '${{ needs.metadata.outputs.terminal_version }}'
$assets = @(Get-ChildItem -LiteralPath 'artifacts/release-assets' -File | Sort-Object Name | ForEach-Object { $_.FullName })
$notes = @'
## Installation

```text
dotnet add package Icod.DCurses --version {0}
```

`Icod.DCurses` targets `net8.0`, `net9.0`, and `net10.0`. Its runtime package dependencies are
`Icod.Terminal {1}` directly; `Icod.TermInfo` is resolved transitively through Terminal.
'@ -f $version, $terminalVersion
$arguments = @('release', 'create', $env:GITHUB_REF_NAME, '--verify-tag', '--title', "Icod.DCurses $version", '--generate-notes', '--notes', $notes)
$notesPath = "docs/releases/$version.md"
if (-not (Test-Path -LiteralPath $notesPath -PathType Leaf)) {
throw "Curated release notes not found at '$notesPath'."
}
$arguments = @('release', 'create', $env:GITHUB_REF_NAME, '--verify-tag', '--title', "Icod.DCurses $version", '--notes-file', $notesPath)
if ('true' -eq '${{ needs.metadata.outputs.prerelease }}') {
$arguments += '--prerelease'
$arguments += '--latest=false'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ mono_crash.*
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
!docs/releases/
!docs/releases/*.md

[Dd]ebug/x64/
[Dd]ebugPublic/x64/
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable `Icod.DCurses` release-line changes are summarized here. Detailed tranche evidence, API fingerprints, roadmaps, and release qualification records remain under `docs/` and the versioned roadmap files.

## 2.5.1 — Raw shortcut input compatibility

- Updated the sole direct runtime dependency to stable `Icod.Terminal 1.29.1`.
- Qualified raw-mode `Ctrl+C` and `Ctrl+Z` delivery through the DCurses event stream as `CursesKey.Character` events carrying the `Control` modifier, allowing applications to bind copy and undo without those bytes being consumed by host signal processing.
- Inherited Terminal's corrected legacy Alt-prefix handling, including `Alt+F`, through the existing DCurses input adapter.
- Preserved the 2.5.0 public contract, `AssemblyVersion 2.0.0.0`, C# 13, .NET 8/9/10 targets, retained presentation behavior, and package dependency shape. Applications that want host signal behavior should continue using the default `CBreak` mode; applications that own `Ctrl+C`/`Ctrl+Z` shortcuts must select `Raw`.

## 2.5.0 — Color-surface qualification (stable-source candidate)

- Qualified existing independent foreground/background styles through logical mutation, wide-cell repair, pads, viewports, opaque and blank-transparent panels, style-only refresh, capability fallback, and resize/invalidation/lifecycle repaint.
Expand Down
15 changes: 8 additions & 7 deletions Icod.DCurses-Development-Roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
**Repository:** `https://github.com/uniblab/Icod.DCurses`\
**Published compatibility floor:** `1.0.0`\
**Published releases:** [GitHub Releases](https://github.com/uniblab/Icod.DCurses/releases) and [NuGet](https://www.nuget.org/packages/Icod.DCurses/)\
**Current stable source candidate:** `2.5.0` on PR #38; not merged, tagged or published\
**Latest published stable package:** `2.4.0`\
**Current stable source candidate:** `2.5.1` maintenance candidate on the active pull request\
**Latest published stable package:** `2.5.0`\
**Current development assembly version:** `2.0.0.0`\
**Current development runtime dependency:** direct stable `Icod.Terminal 1.29.0` only; TermInfo remains transitive\
**Current development runtime dependency:** direct stable `Icod.Terminal 1.29.1` only; TermInfo remains transitive\
**Stable 2.4 direct runtime dependency:** `Icod.Terminal 1.29.0`; no direct `Icod.TermInfo` reference\
**Target frameworks:** `net8.0`; `net9.0`; `net10.0`\
**Configurations:** `Debug`; `Staging`; `Release`\
**Active feature track:** 2.5.0 color-surface hardening for Icod.Widgets and dedit; stable source qualified on PR #38\
**Status:** Version 2.4.0 is the latest published stable package. Version 2.5.0 stable source has completed T2500–T2507, including unchanged public API, public-only color sample, package consumer, full Release gate, and successful RC/stable-source Windows/Linux/macOS x64/ARM64 PR matrices. Live terminal color visuals remain unverified; the maintainer controls merge, tag and publication. See the [2.5 roadmap](Icod.DCurses-2.5.0-Development-Roadmap.md) and [T2507 release gate](docs/T2507-2.5.0-Stable-Source-Gate.md).
**Active feature track:** 2.5.1 maintenance update for Terminal 1.29.1 shortcut-input compatibility\
**Status:** Version 2.5.0 is published. Version 2.5.1 updates the sole direct Terminal dependency, qualifies raw `Ctrl+C`/`Ctrl+Z` delivery through DCurses, and preserves the 2.5 public API and assembly identity. The maintainer controls merge, tag and publication. See the [2.5 roadmap](Icod.DCurses-2.5.0-Development-Roadmap.md), [T2507 release gate](docs/T2507-2.5.0-Stable-Source-Gate.md), and [2.5.1 curated release notes](docs/releases/2.5.1.md).

**Planning snapshot:** 2026-10-12
**Planning snapshot:** 2026-10-15

---

Expand Down Expand Up @@ -71,7 +71,8 @@ Historical 1.0-1.6 roadmaps, tranche records, public-API baselines/fingerprints,
| `2.3.0` | First-class `CursesRasterAtlas` coordination for cell-aligned tile presentation | Published 2026-10-09 |
| `2.3.1` | Package documentation and release-state correction | Stable maintenance patch; no runtime or public API changes |
| `2.4.0` | Widgets/dedit foundations: Terminal 1.29 clipboard/cursor facades, qualified visible projection and capture | Published 2026-10-12 |
| `2.5.0` | Complete foreground/background color-surface retention, composition, damage and fallback qualification | Stable source qualified on PR #38; merge/tag/publication pending |
| `2.5.0` | Complete foreground/background color-surface retention, composition, damage and fallback qualification | Published 2026-10-14 |
| `2.5.1` | Terminal 1.29.1 raw shortcut-input compatibility | Maintenance candidate; merge/tag/publication pending |
| Later | Higher-level `Icod.Widgets` themes and separately evidenced sprite/physical-placement work | Separate repositories/tracks; not implicitly in 2.5 |

The post-1.0 progression is intentionally cumulative:
Expand Down
8 changes: 4 additions & 4 deletions Icod.DCurses.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@
<AssemblyName>Icod.DCurses</AssemblyName>
<RootNamespace>Icod.DCurses</RootNamespace>
<Configurations>Debug;Staging;Release</Configurations>
<Version>2.5.0</Version>
<Version>2.5.1</Version>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup>
<PackageVersion>2.5.0</PackageVersion>
<PackageVersion>2.5.1</PackageVersion>
<PackageId>Icod.DCurses</PackageId>
<Title>Icod.DCurses</Title>
<Authors>Timothy J. Bruce</Authors>
<Description>Managed, cross-platform curses-style terminal UI for .NET with retained Unicode text, independently styled foreground/background color surfaces, viewports, panels, mixed media, deterministic interaction routing, bounded clipboard access, and scoped cursor styles.</Description>
<PackageReleaseNotes>2.5 qualifies existing foreground/background color retention, opaque-panel styled blanks, damage-aware rendition refresh, capability fallback, and lifecycle repaint across .NET 8/9/10; adds a public-only color sample and package consumer. No public API changes. Existing bounded clipboard and cursor-style APIs remain. The sole direct runtime dependency is stable Icod.Terminal 1.29.0.</PackageReleaseNotes>
<PackageReleaseNotes>2.5.1 updates the sole direct runtime dependency to Icod.Terminal 1.29.1 so raw-mode applications reliably receive Ctrl+C and Ctrl+Z as Control-modified character events and legacy Alt+character input remains available through the DCurses event stream. No public API or AssemblyVersion change.</PackageReleaseNotes>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://github.com/uniblab/Icod.DCurses</PackageProjectUrl>
Expand Down Expand Up @@ -116,6 +116,6 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Icod.Terminal" Version="1.29.0" />
<PackageReference Include="Icod.Terminal" Version="1.29.1" />
</ItemGroup>
</Project>
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ The application decides how to interpret `inputEvent`, when to refresh again,
and when to exit. DCurses does not start a callback dispatcher or a second input
reader.

## Input modes and application shortcuts

`CursesSessionOptions.InputMode` defaults to `CursesInputMode.CBreak`, which
keeps host signal processing enabled. Select `CursesInputMode.Raw` when the
application must receive `Ctrl+C`, `Ctrl+Z`, or similar control chords itself:

```csharp
CursesSessionOptions options = new() {
InputMode = CursesInputMode.Raw
};
await using CursesSession session = await CursesSession.OpenAsync( options );
```

In raw mode, `Ctrl+C` and `Ctrl+Z` are delivered as `CursesKey.Character`
events with `CursesKeyModifiers.Control`; the application decides whether they
mean copy, undo, exit, or another command. Use `CBreak` when the host should
retain its normal interrupt and suspend handling.

## Color surfaces and fallback

Each `CursesCell` carries a complete `CursesStyle`: independently requested
Expand Down
41 changes: 41 additions & 0 deletions docs/releases/2.5.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Icod.DCurses 2.5.1

Icod.DCurses 2.5.1 is a focused input-compatibility maintenance release. It
updates the sole direct runtime dependency to Icod.Terminal 1.29.1 while
preserving the complete 2.5 public API and retained-presentation behavior.

## What changed

- Raw-mode sessions now reliably surface `Ctrl+C` and `Ctrl+Z` through the
DCurses event stream as `CursesKey.Character` events with
`CursesKeyModifiers.Control`.
- Legacy Alt-prefix input, including `Alt+F`, benefits from Terminal 1.29.1's
corrected decoding through the existing DCurses adapter.
- Permanent byte-level acceptance coverage protects `Ctrl+C`, `Ctrl+Z`, and
legacy `Alt+F` delivery from the Terminal session through
`CursesSession.ReadEventAsync`.

## Choosing an input mode

DCurses continues to default to `CursesInputMode.CBreak`. That mode keeps host
signal processing enabled, so applications that want conventional interrupt and
suspend behavior do not need to change anything.

Applications that use `Ctrl+C` for copy, `Ctrl+Z` for undo, or otherwise own
control-key policy should open the session with `CursesInputMode.Raw`. In raw
mode, the application is also responsible for providing its own exit and
job-control policy.

## Compatibility

- No public API changes.
- `AssemblyVersion` remains `2.0.0.0`.
- Target frameworks remain .NET 8, .NET 9, and .NET 10.
- The only direct runtime dependency remains `Icod.Terminal`, now at 1.29.1;
Icod.TermInfo remains transitive.

## Install

```text
dotnet add package Icod.DCurses --version 2.5.1
```
26 changes: 26 additions & 0 deletions packaging/Assert-ReleaseNotes.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
param(
[ValidateSet('Debug', 'Staging', 'Release')]
[string]$Configuration = 'Release'
)

$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

$repositoryRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
Import-Module (Join-Path $PSScriptRoot 'RepositoryTools.psm1') -Force

$projectPath = Join-Path $repositoryRoot 'Icod.DCurses.csproj'
$version = Get-MSBuildProperty -ProjectPath $projectPath -Name 'PackageVersion' -Configuration $Configuration
if ($version -notmatch '^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z][0-9A-Za-z.-]*)?$') {
throw "Invalid DCurses package version '$version'."
}

$notesPath = Join-Path $repositoryRoot "docs/releases/$version.md"
if (-not (Test-Path -LiteralPath $notesPath -PathType Leaf)) {
throw "Package version '$version' requires curated notes at '$notesPath' before tagging."
}
if ([string]::IsNullOrWhiteSpace([System.IO.File]::ReadAllText($notesPath))) {
throw "Curated notes at '$notesPath' are empty."
}

Write-Host "Curated release notes found for Icod.DCurses $version."
1 change: 1 addition & 0 deletions packaging/Invoke-Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function Invoke-Pack {
function Invoke-Validate {
Write-Host ''
Write-Host "=== Validate ($Configuration) ==="
& (Join-Path $repositoryRoot 'packaging/Assert-ReleaseNotes.ps1') -Configuration $Configuration
if ($isWindowsHost) {
& cmd /c (Join-Path $repositoryRoot '.github/scripts/verify-release-package.cmd') $artifactDirectory $Configuration
} else {
Expand Down
8 changes: 4 additions & 4 deletions samples/Icod.DCurses.RasterAtlas.Sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ resize recreation and a text fallback driven by the same model.

## Current release boundary

The current 2.4.0 source consumes stable `Icod.Terminal 1.29.0` through DCurses.
The current 2.5.1 source consumes stable `Icod.Terminal 1.29.1` through DCurses.
Version 2.4 adds bounded clipboard and cursor-style session mechanisms without
changing this sample's retained raster contract. The maintainer has accepted the
sample's ATLAS, FRAME, and TEXT behavior,
Expand Down Expand Up @@ -99,7 +99,7 @@ the pixels correctly. Record that separately with the T2308/T2310 live checklist

## Live acceptance and known limits

The sample consumes stable Terminal 1.29.0 through DCurses, including bounded
The sample consumes stable Terminal 1.29.1 through DCurses, including bounded
persistent-transfer deadlines, immediate Linux/macOS byte input, Kitty DA1
compatibility, newline-safe cursor planning, and coalesced Sixel screen writes.
The public mode indicator is the acceptance authority: `ATLAS`, `FRAME`, or
Expand Down Expand Up @@ -187,8 +187,8 @@ dotnet list Icod.DCurses.csproj package
dotnet run --project samples/Icod.DCurses.RasterAtlas.Sample/Icod.DCurses.RasterAtlas.Sample.csproj -c Release -f net10.0
```

For the current 2.4.0 source, confirm the resolved direct package is
`Icod.Terminal 1.29.0`. Use
For the current 2.5.1 source, confirm the resolved direct package is
`Icod.Terminal 1.29.1`. Use
`-- --raster` to exercise FRAME directly and `-- --text` to force TEXT.
Record the mode indicator along with rendering behavior; a fallback is a
controlled result, not evidence that another mode rendered.
Expand Down
10 changes: 8 additions & 2 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
The repository contains fourteen executable samples. They are intentionally separate so the minimal session lifecycle stays easy to copy without mixing it with the interactive and acceptance-focused showcases.

All sample projects target `net8.0`, `net9.0`, and `net10.0` and consume the
repository `Icod.DCurses` project. Icod.DCurses 2.5.0 declares only stable
`Icod.Terminal 1.29.0` directly; Terminal may restore TermInfo transitively. See
repository `Icod.DCurses` project. Icod.DCurses 2.5.1 declares only stable
`Icod.Terminal 1.29.1` directly; Terminal may restore TermInfo transitively. See
the [changelog](../CHANGELOG.md) for historical package dependencies and the
[2.0 migration guide](../docs/2.0-Migration-Guide.md) when upgrading an external
application from the 1.x public surface.
Expand Down Expand Up @@ -118,6 +118,12 @@ The sample uses public `CursesTextLayout` source positions and geometry for Unic

Typing replaces the active selection, and Backspace/Delete remove it at complete text-element boundaries. `Ctrl+W` toggles wrap; `Ctrl+T` starts/stops keyboard selection; `Ctrl+C` and `Ctrl+V` copy and paste; `Ctrl+G` or `Ctrl+K Ctrl+G` opens the 1-based record prompt. Within that explicit prompt scope, `Ctrl+K Ctrl+C` or `Escape` cancels and `Enter` accepts. Arrows navigate; `PageUp`/`PageDown` jump records; `Home`/`End` jump within the current record; typing, `Tab`, `Enter`, `Backspace` and `Delete` edit. `Escape` exits from the document context. The interaction controller registers the lowercase modern and uppercase traditional character identities for each Control shortcut.

The editor sample explicitly opens `CursesInputMode.Raw`, so control bytes such
as `Ctrl+C` and `Ctrl+Z` reach the application as Control-modified character
events. The sample binds `Ctrl+C`; a full editor can bind `Ctrl+Z` to undo. Use
the default `CBreak` mode instead when the host should retain interrupt and
suspend processing.

Primary-button clicks place the caret in the document. Dragging extends the selection and remains captured when the pointer leaves the document; releasing the button, losing focus, opening the prompt, resizing, or disposing the controller ends capture. The final document column is an independently hit-tested scrollbar: clicking or dragging it maps its row onto the synthetic document without turning `Tab` into focus traversal.

The editor requests Raw input so the host delivers `Ctrl+C` to the command router instead of converting it into an interrupt; use `Escape` for orderly exit. Clipboard commands explicitly use the session OSC 52 boundary. The sample keeps a private application fallback when the host clipboard is unavailable, denied, malformed, or times out; a timeout is inconclusive and is not treated as proof that the host lacks clipboard support. Host consent and policy remain terminal concerns. The visible caret remains enabled, and the sample requests a steady bar cursor through a scoped lease; unsupported or inconclusive style negotiation leaves the host style unchanged. Resize recomputes the document, status, prompt and interaction regions and invalidates any live prefix. Minimum size is 30 columns by 6 rows.
Expand Down
2 changes: 1 addition & 1 deletion tests/Icod.DCurses.Tests/Icod.DCurses.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Icod.Terminal" Version="1.29.0" />
<PackageReference Include="Icod.Terminal" Version="1.29.1" />
<PackageReference Include="Icod.TermInfo" Version="1.17.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
Expand Down
Loading
Loading