Back-merge v2.1.0-beta.1 from main into develop#5244
Merged
Conversation
…5115) * Bump ReportGenerator from 5.5.5 to 5.5.6 --- updated-dependencies: - dependency-name: ReportGenerator dependency-version: 5.5.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Update Examples link in README.md (#5104) * Reframe layout docs around responsive UI and instructional style (#5110) * Initial plan * docs: reframe layout docs around responsive UI Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a6b913bd-38e5-4d80-ac23-9dc8e6716045 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: polish responsive layout wording Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a6b913bd-38e5-4d80-ac23-9dc8e6716045 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: tighten instructional sentence style Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d453216b-6d43-4261-aa23-0dad98805e91 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: fix remaining instructional prose Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d7be6123-896e-4b95-8e3f-0cee1d6d35d1 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> * Fixes #5114. Remove main from publish branch triggers; use tags only Main branch pushes were triggering the publish workflow without a release tag, causing GitVersion to produce invalid NuGet versions (e.g. 2.0.0-5420). - Remove main from branches trigger; stable releases now publish only on v* tag push - Develop branch pushes continue publishing pre-release packages automatically - Update template dispatch conditions to match tag-based flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: tig <585482+tig@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add tests for ShadowStyle inheritance and reset behavior Added two unit tests to ShadowTests.cs: - ShadowStyle_Getter_Does_Not_Inherit_From_SuperView ensures a child view does not inherit ShadowStyle from its SuperView and that round-tripping the property does not create a MarginView or add shadow thickness. - Setting_ShadowStyle_Null_Resets_ShadowSize verifies that setting ShadowStyle to null resets the MarginView's ShadowSize to Size.Empty, preventing residual state. * Fixes #5088 - Changed Margin.ShadowStyle to only use the local value and reset ShadowSize to Size.Empty when unset. Adjusted related tests to match new behavior. Refactored ShadowStyleDemo window and editor initialization for clarity and consistency, updated shadow window positioning and scheme usage, and improved child view arrangement. * Update Tests/UnitTestsParallelizable/ViewBase/Adornment/ShadowTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ut (#5083) * Fixes #5072. TableView reserves space for later columns when laying out A wide column (e.g. a long Description) previously consumed all available viewport width and pushed subsequent columns off-screen. Each visible column now reserves at least its header width (or configured MinWidth) during layout so wide columns are clamped instead of starving later columns. The reservation only inspects column headers and styles — it never iterates cell rows — so paginated or very large ITableSource implementations remain performant. * Tighten TableView column-bounds test to use strict inequality Right-edge check now uses < Viewport.Width instead of <= per code review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Restore foreach loop in TableView.CalculateContentSize Use a manual index counter rather than converting the loop to for, and revert the unrelated borderWidth local-variable extraction. The fix only needs the index to compute the slice of remaining columns to reserve space for. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Updated table col width calculation and added wide example * Fixed tests and updated comment wording based on copilot pr feedback --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Tig <tig@users.noreply.github.com>
…iteration unnecessarily. (#5123)
… custom ColorGetter (#5128) * Fixes #5075. TableView ShowVerticalCellLines=false renders incorrectly with custom ColorGetter When ShowVerticalCellLines is false and a ColumnStyle.ColorGetter is in use (e.g. FileDialog), the 1-char gap between cells retained the row scheme's attribute, producing visible "stripes" through custom-colored cells. TruncateOrPad intentionally renders cells to (Width - 1) chars, leaving 1 char for the cell boundary. RenderRow now extends the cell's own background into that gap when the separator is the default invisible space. RenderSeparator skips drawing in the same case (RenderRow owns the gap). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * FileDialog: use ShowVerticalCellLines=false now that #5075 fix is in. Per PR review on #5128, switch FileDialog's TableView to render without vertical cell lines so its custom ColorGetter (file-type colors) shows through cleanly. The TableView fix in this PR ensures the 1-char gap between cells now picks up the cell's own background instead of the row scheme's, so removing the lines no longer leaves color stripes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
* Revert "Fixes #5132. TableView Home/End navigation with FullRowSelect (#5133)" This reverts commit 6361f33. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Docs: Document Home/End rebinding for FullRowSelect in TableView Adds a tip to the FullRowSelect section showing how to rebind Home/End to Command.Start/Command.End for row-level navigation, referencing the UICatalogRunnable pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5131) * Adds concurrency test for OutputBufferImpl race condition Adds AddStr_And_ClearContents_Concurrent_DoesNotThrow test that reproduces the race condition in OutputBufferImpl where ClearContents replaces the Contents reference while AddStr is concurrently iterating. See #5130. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Adds concurrency tests, benchmark, and plan for #5130 - Expanded OutputBufferImplConcurrencyTests with 4 tests covering: AddStr+ClearContents, FillRect+ClearContents, Move+AddStr+ClearContents, and a three-way concurrent test - Added OutputBufferBenchmark for perf baseline (AddStr, FillRect, ClearContents, SetSize, TypicalDrawCycle) - Added implementation plan in plans/ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor OutputBufferImpl for thread safety Replaced locking on Contents with a dedicated _contentsLock object to ensure safe concurrent access to buffer state (Contents, DirtyLines, Clip, etc.). Refactored buffer management methods (ClearContents, SetSize, FillRect, Move, IsValidLocation) to use the new lock. Updated FillRect and AddGrapheme to avoid race conditions. Improved documentation and comments for concurrency. Moved SetCellUrl/GetCellUrl implementations under the lock. In OutputBufferImplConcurrencyTests, reordered and moved helper methods for clarity; no test logic changes. No public API changes, but internal concurrency is now robust. * Refactor StringExtensions for style and consistency Refactored methods to use expression-bodied members and improved code style (constants, variable declarations, and formatting). Added and then removed `IsSurrogatePair` and `MakePrintable` extension methods, resulting in no net functional changes. All updates are stylistic and organizational. * Fix race condition in FillRect(Rectangle, char) overload The char overload called Move() + AddRune() without holding _contentsLock, allowing concurrent threads to corrupt Col/Row between the two calls and write characters to wrong positions. Fix: delegate to FillRect(Rectangle, Rune) which holds the lock atomically. Added test proving the race (detected wrong-position writes in <13ms before fix). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Added null check in OutputBufferImpl.cs WriteGrapheme. Introduced locking in RuneExtensions.cs for thread-safe Unicode width calculation. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
…bleSelection.SelectedCell` (#5142) * Initial plan * Rename TableSelection.Cursor to TableSelection.SelectedCell Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/8d9d1a5e-97bb-4c6e-862a-948119c94fca 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>
…inal character in v2.0.1 (#5146)
* Initial plan * Add custom header styling for TableView (Options B+C) - Add HeaderColorGetterArgs class for contextual header color info - Add HeaderColorGetterDelegate for per-column header color override - Add ColumnStyle.HeaderColorGetter property - Add TableStyle.HeaderScheme property for global header scheme - Update RenderHeaderMidline to apply header styling - Update CharacterMap scenario to italicize sorted column header - Add unit tests for both per-column and global header styling Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/157d9f83-14ee-4f74-9d4a-a6b879105d50 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>
* Fix NativeAOT configuration cloning and warning cleanup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix config converter regressions and serialization cleanup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove stale AOT propagation annotations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix NativeAOT configuration cloning and warning cleanup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix config converter regressions and serialization cleanup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove stale AOT propagation annotations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix PR 5134 config review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify AttributeJsonConverter style parsing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Correctly serialize null properties in ScopeJsonConverter --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tig <tig@users.noreply.github.com>
* Initial plan * Improve DropDownList keyboard: Space to open, Up/Down to navigate, CollectionNavigation support Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/c07c6615-2cdd-40a1-b0c0-86f0f31c26bb Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address code review: split compound conditions into separate guard clauses Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/c07c6615-2cdd-40a1-b0c0-86f0f31c26bb Co-authored-by: tig <585482+tig@users.noreply.github.com> * Code cleanup --------- 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>
…eadOnlyList<string>?> (#5160)
…#5150) * Initial plan * Fixes #5103. Disable NerdFonts default in FileDialogExamples scenario Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/49264ca7-5e02-4e48-aa49-e81b08ddcf23 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>
…ity (#5170) (#5179) Key.Equals(object?) included Handled in the comparison while GetHashCode returned only _keyCode.GetHashCode(), violating the .NET contract that equal objects must have equal hash codes. This broke KeyBindings (a ConcurrentDictionary<Key, KeyBinding>) when Handled flipped between storing and lookup. Handled is per-event state, not part of binding identity, so it is removed from the equality comparison. KeyEqualityComparer already used KeyCode-only equality and is consistent. Two existing tests in KeyTests.cs that asserted the buggy behavior (Equals_ShouldReturnTrue_WhenEqual and Equals_Handled_Changed_ShouldReturnFalse_WhenNotEqual) have been updated to assert the correct contract-honoring behavior. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv Co-authored-by: Claude <noreply@anthropic.com>
…eptable (#5189) CLAUDE.md and .claude/rules/testing-patterns.md disagreed on the AI marker convention (one said "// Claude - Opus 4.5", the other "// CoPilot - ChatGPT v4"). Empirically both are used: Tests/UnitTestsParallelizable + Tests/UnitTests.NonParallelizable contain ~105 files with "// Claude" markers and ~93 with "// CoPilot". Update both guidance files to list the two forms as equally acceptable and tell reviewers not to flag inconsistency between them. Triggered by Copilot review nits across PRs #5177-#5188. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv Co-authored-by: Claude <noreply@anthropic.com>
…) (#5186) * fix: UnixRawModeHelper safe restore on crash + valid-state guard (#5164) When the input thread crashes before the driver Dispose() runs, the Unix terminal is left in raw mode and the user's shell is left unusable. This change adds three safety nets so the original termios is restored on any abnormal exit path: - Finalizer: last-resort restore if Dispose() is bypassed (e.g. fatal native crash, immediate process abort). - AppDomain.ProcessExit hook registered after a successful TryEnable; unregistered in Dispose() to avoid leaking the helper for the lifetime of the process. - Console.CancelKeyPress hook so Ctrl+C also restores cleanly. Also adds a _haveSavedTermios guard so Restore() is a hard no-op unless tcgetattr previously succeeded - preventing an uninitialized termios struct from ever being written back to the terminal. Tests in UnitTests.Parallelizable cover: - Restore() without TryEnable() is a no-op and does not throw. - Restore() is idempotent. - Dispose() without TryEnable() is a no-op and double-Dispose is safe. - The type has a finalizer (last-resort restore contract). - TryEnable() failure paths leave _haveSavedTermios = false. The full crash-during-input-thread scenario is integration-only (requires a real tty); the unit tests cover the observable contract. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv * fix: check tcsetattr return; document CancelKeyPress limitation (#5164) Address Copilot review feedback on PR #5186: - Restore() and the finalizer now check the tcsetattr return code. On non-zero return, log the errno via the existing Logging infrastructure. Restore() leaves IsRawModeEnabled set to true when the syscall fails so callers and the finalizer know the terminal was not restored. The finalizer logs only and never throws. - Document the Console.CancelKeyPress limitation: with ISIG disabled in raw mode, a keyboard Ctrl+C arrives as a 0x03 byte rather than SIGINT, so the hook is unlikely to fire while raw mode is active. The subscription remains as belt-and-braces defense for hosts that do not disable ISIG and for externally-delivered SIGINT events; the primary safety nets are AppDomain.ProcessExit and the finalizer. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv * fix: drop unreachable finalizer from UnixRawModeHelper (#5164 review) The finalizer in UnixRawModeHelper was dead code: the instance is rooted by its AppDomain.CurrentDomain.ProcessExit and Console.CancelKeyPress event-handler subscriptions, so it can never become finalization-eligible while those hooks are wired. Drop the finalizer and the now-unneeded GC.SuppressFinalize call. Restoration relies on explicit Dispose as the primary path with the ProcessExit hook as the safety net for normal process exit; CancelKeyPress remains a best-effort fallback. Update the class-level remarks and the obsolete reflection-based finalizer test accordingly (6 tests -> 5). https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv --------- Co-authored-by: Claude <noreply@anthropic.com>
…) (#5188) * docs: clarify SessionBegun/SessionEnded as token lifecycle hooks (#5162) https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv * docs: tighten SessionBegun/SessionEnded XML accuracy (#5162) Address Copilot review feedback on PR #5188 by aligning the SessionBegun and SessionEnded XML docs with the actual ordering and contract in ApplicationImpl.Begin/End. - SessionBegun summary: describe the real firing point (after the token is pushed onto SessionStack and TopRunnable is set, but before IsRunningChanged/IsModalChanged fire) instead of "immediately after token construction". - SessionEnded summary: drop "token-disposal hook"/"about to be released" framing; SessionToken is not IDisposable. Describe the real state (state has unwound, IsRunningChanged(false) has fired, Runnable is null) without overstating the SessionStack invariant (End only pops when wasModal && popped == token). - Replace "manually dispose of the SessionToken" guidance in both remarks blocks with the actual caller responsibility: subscribe to SessionEnded and call End(SessionToken) themselves. - End(SessionToken) remarks: replace "disposes the sessionToken" with "clears SessionToken.Runnable on sessionToken" to match the code. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
…ose (#5163) (#5185) * fix: ApplicationImpl.Invoke throws NotInitializedException after Dispose (#5163) Both `Invoke(Action)` and `Invoke(Action<IApplication>)` overloads silently dropped actions when called before `Init()` or after `Dispose()`: the thread-affinity fast path is skipped (no main thread or top runnable) and the `TimedEvents.Add` fallback queues onto a stopped queue. Add an `Initialized` guard at the top of both overloads so the post- Dispose / pre-Init case fails loudly with `NotInitializedException`, matching the pattern already used by `Run(IRunnable, ...)` in the same file. The deeper thread-affinity race between the fast-path read of `TopRunnableView` / `MainThreadId` and concurrent shutdown is intentionally out of scope - that requires a redesign noted in the issue and is not covered here. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv * fix: address review comments on Invoke disposed-throws (#5163) - Pass nameof(Invoke) to NotInitializedException so the formatted "{member} cannot be accessed before Initialization" message is grammatically correct. - Add ArgumentNullException.ThrowIfNull(action) to the non-generic Invoke(Action) overload so a null action fails deterministically (consistent with Begin/Run argument validation). - Wrap Init in try/finally in the AfterDispose tests so a thrown Init does not leak the process-wide SynchronizationContext. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
…#5181) * fix: ConcurrentDictionaryJsonConverter rejects duplicate keys (#5173) The Read implementation was calling TryAdd and ignoring its return value, so duplicate keys in input JSON were silently dropped. Now throws a JsonException on duplicate, mirroring the DictionaryJsonConverter fix. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv * style: normalize space-before-paren in ConcurrentDictionaryJsonConverter (#5173 review) Apply project's space-before-paren convention to the Read method body, matching DictionaryJsonConverter<T>. Addresses review feedback on PR #5181 where the new TryAdd duplicate-key check used the convention but adjacent calls in the same method body did not. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
Per maintainer feedback, DrawOuterBoundary was a debug helper added during Region's development phase, not a supported public API. There are zero internal callers across the framework (verified via grep); the only consumer was the RegionScenario UICatalog demo, which now iterates GetRectangles() and adds rectangle edges to the LineCanvas directly. Shared edges between adjacent rectangles overlap; LineCanvas line-style joining handles the visual result, matching how Border/Adornment already draw. The 30+ structural smoke tests in DrawOuterBoundaryTests.cs are removed; none used DriverAssert or verified visual output. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
…5177) The KeyBindings constructor passed a binding factory to CommandBindingsBase that dropped the key parameter, calling `new KeyBinding(commands, source)` where `source` was bound to the View? overload's target/data slot. Result: every binding created via Add(key, ...) had Key = null and Target = null. Forward the key (and explicit nulls for target/data) to the (commands, key, source, target, data) constructor so KeyBinding.Key is populated. https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv Co-authored-by: Claude <noreply@anthropic.com>
The XOR branch in Region.Combine mutated `this` via Exclude(region) and then computed (region - this) against the already-mutated `this`, producing a non-symmetric result. Snapshot both operands first and compute (thisOriginal \ regionOriginal) ∪ (regionOriginal \ thisOriginal). https://claude.ai/code/session_01CdoS4YQ7v9aNPZaNsYnxjv Co-authored-by: Claude <noreply@anthropic.com>
) * Initial plan * Add selection, copy, and context menu to Markdown view - Add MarkdownView.Selection.cs with selection state, SelectAll(), Copy(), ClearSelection(), IsInSelection(), GetSelectedText(), context menu lifecycle - Update MarkdownView.Mouse.cs: add Command.SelectAll/Copy/Context, OnMouseEvent for drag selection, update OnActivated for drag-aware link handling, update OnHasFocusChanged for context menu lifecycle - Update MarkdownView.Drawing.cs to highlight selected cells - Update Markdown.cs: clear selection on text change, update docs - Add MarkdownViewSelectionTests.cs with 12 tests Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/ecbe0462-5243-4c9a-9464-f0e66acd0b9f Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix code review issues: use explicit type int and App is not null pattern Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/ecbe0462-5243-4c9a-9464-f0e66acd0b9f Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix selection visibility and persistence after mouse release - Fix selection attribute: use GetAttributeForRole(VisualRole.Focus) instead of reversing per-segment colors — gives reliable contrast across all schemes/themes - Fix selection disappearing on mouse release: remove the LeftButtonReleased → Activate binding (inherited from base SetupMouse) so OnActivated fires only on LeftButtonClicked; previously OnActivated fired twice causing _isDragging to be reset before the Click, which then cleared the selection - Add two regression tests: Selection_Persists_After_LeftButtonReleased and Plain_Click_Clears_Selection Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/23c59c05-1db9-43bb-8f36-2dcceb3db746 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Code cleanup * Refactor MarkdownView mouse selection handling Route mouse press and drag events through OnActivated by binding LeftButtonPressed and LeftButtonPressed|PositionReport to Command.Activate. Update selection logic accordingly and add unit tests to verify mouse bindings and drag-selection behavior. * Add SelectedText property and markdown fidelity tests Added public SelectedText property to Markdown view, returning the current selection as plain text or null if inactive. Documented that the output may differ from the markdown source. Introduced Copilot-marked tests verifying that selection and copy operations should preserve markdown structure (e.g., list markers, code fences). Tests currently fail, documenting known fidelity issues in the selection/copy implementation. No changes to selection/copy logic yet. * Preserve markdown syntax in selection and copy Improves MarkdownView selection/copy fidelity by reconstructing code block fences (with language tags) and list markers in selected/copied text. Returns original markdown source for full-document selections. Updates and adds tests to verify round-trip and partial selection correctness. * Add test for table markdown preservation in selection Adds PartialSelection_IncludingTable_SelectedText_Preserves_Table_Markdown to verify that partial selections including tables retain Markdown syntax. Documents current failure: table rows are missing from selected text due to placeholder rendering. * Support GFM table markdown copy from selection Reconstruct and output valid GitHub Flavored Markdown pipe-table syntax when selecting and copying table content. Store TableData in RenderedLine, and use it to generate markdown table lines with correct alignment and structure during selection. * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix right-click on unfocused Markdown view being a no-op Handle RightButtonClicked in OnMouseEvent before command bindings fire: - If view is not focused, SetFocus() first — this synchronously triggers OnHasFocusChanged(true) which creates the ContextMenu - Then call ShowContextMenu(mouse.ScreenPosition) so the menu appears at the click location - Remove RightButtonClicked → Command.Context mouse binding (now handled entirely in OnMouseEvent) - Also fix keyboard context menu anchor: GetContextMenuScreenPosition() already provides ViewportToScreen fallback for the keyboard path; simplified the null-check in ShowContextMenu to use it - Rename ambiguous local 'anchor' → 'viewportPosition' in GetContextMenuScreenPosition() - Simplify LeftButtonReleased ungrab: remove redundant IsGrabbed check (UngrabMouse is a no-op when not grabbed) - Add regression tests: RightClick_On_Unfocused_View_Creates_And_Shows_ContextMenu and RightClick_On_Focused_View_Shows_ContextMenu Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/e3212c71-6a8b-4c36-97c8-cb32602852a7 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix drag clamping, table duplication, SubView selection drawing, and IsFullDocumentSelected Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/39d748ab-7987-458b-902a-2a9cb47a9c6d Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix code review: use explicit int types in CountOccurrences helper Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/39d748ab-7987-458b-902a-2a9cb47a9c6d 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> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…publish + release tag (#5197) * Initial plan * Add notify-clet.yml: dispatch to gui-cs/clet on develop publish + release tag Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/4c58f4a8-a920-4d6a-a908-7e49f34c7bb6 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>
…with tables (#5194) * Initial plan * Fix MarkdownView GetContentHeight overestimating height with tables In BuildRenderedLines, tableView.Frame.Height was read after Recalculate() set the Height Dim but before layout could update Frame. The Frame retained a stale value from the initial Recalculate(80) in the TableData setter (where width defaulted to 80 because Frame.Width was 0). Fix: Add RenderedHeight property to MarkdownTable that is always up-to-date after Recalculate(), and use it instead of Frame.Height in BuildRenderedLines. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/c3c41ab6-99f5-4a09-938e-01519f6012cb Co-authored-by: tig <585482+tig@users.noreply.github.com> * Improve XML doc for RenderedHeight property Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/c3c41ab6-99f5-4a09-938e-01519f6012cb Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix table height overestimate in mixed-width documents When a long unwrapped line (e.g. code) makes contentWidth > viewportWidth, tables (Dim.Fill) render at the wider content width and may need fewer wrapped rows. Add a pre-scan pass to compute _maxLineWidth from unwrapped blocks first, then use max(viewportWidth, _maxLineWidth) as the table layout width. This ensures table placeholder lines match the actual rendered height at the final content width. Add regression test proving the fix for this mixed-width scenario. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/49f44619-798d-400e-83e3-c4c0b8743f12 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address review: use OfType pattern matching instead of string comparison Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/49f44619-798d-400e-83e3-c4c0b8743f12 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>
* Initial plan * Emit OSC 8 hyperlink sequences in BuildAnsiForRegion for ToAnsi() output When cells have associated URLs (set by Link/Markdown views via Driver.CurrentUrl), ToAnsi() now emits OSC 8 open/close sequences around the link text. This makes links clickable in terminals that support OSC 8 (Windows Terminal, iTerm2, GNOME Terminal, etc.). The live rendering path (OutputBase.Write) already handled this; only the ToAnsi() export path was missing URL tracking. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/2aa76383-5fae-42a5-9aac-1b681930e8a5 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Add fast-path in GetCellUrl to skip lock when no URLs exist, add row-boundary test Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/0f3f41a6-4d54-43d7-a72e-660b48ad54b0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix thread-safety: re-check _urlMap inside lock after fast-path null check Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/0f3f41a6-4d54-43d7-a72e-660b48ad54b0 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> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The previous notify-clet.yml used `dotnet package search` to discover the version that publish.yml just pushed. That hit NuGet's search/ registration index, which is eventually consistent. On 2026-05-05 a develop publish triggered notify-clet two seconds after Terminal.Gui 2.0.2-develop.37 hit NuGet, but `dotnet package search` still returned .36 — so the gui-cs/clet workflow built and published .36 a second time (silently no-op'd by --skip-duplicate). Result: testers stuck on .36; the markdown rendering fix shipped in .37 never reached them. Two changes fix the race: publish.yml writes the just-pushed version (the GitVersion SemVer it already computes) to a `published-version` artifact. Deterministic; no round-trip through any NuGet API. notify-clet.yml downloads that artifact via workflow_run + actions/ download-artifact, then polls NuGet's *flat-container* API (the endpoint `dotnet restore` actually uses, which indexes within seconds — not the search/registration index that lags by minutes) until the version is restorable. Cap is 10 minutes; in practice flat-container is sub-minute. If the cap trips, the workflow fails loudly rather than silently dispatching a stale or unbuildable version. Channel detection (release vs develop) now derives from the SemVer suffix on the artifact contents, so the dual on: triggers (release + workflow_run) collapse to a single workflow_run trigger — publish.yml already runs on both develop pushes and v* tags, so workflow_run covers both channels. `actions: read` permission added so notify-clet can read artifacts from the triggering run. Repro of the bug: gui-cs/clet workflow run 25406348354 dispatched TG_VERSION=2.0.2-develop.36 even though the triggering TG publish (run 25406288505 on this repo) had pushed .37. The clet build that fixed the symptom required a manual `gh workflow run` dispatch.
- Bump, add, and reorder NuGet package versions in Directory.Packages.props, including new test and utility dependencies - Remove Solution Items reference to docfx\docs\borders.md from Terminal.sln - Refactor ConfigurationMangerTests.cs to use non-nullable types for improved null-safety
…List (#5199) * Initial plan * Replace ColorPicker TextField+autocomplete with DropDownList for color names Fixes the ColorPicker to use a DropDownList control instead of a TextField with AppendAutocomplete for selecting color names. This provides a better user experience with a proper dropdown list of available color names. Changes: - Replace _tfName (TextField) with _ddlName (DropDownList) - Use ListWrapper<string> with color names as the DropDownList source - Set DropDownList to ReadOnly mode for selection-only behavior - Add _syncingSubViews guard to prevent re-entrancy when syncing values - Update tests to reflect the new DropDownList behavior Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/e96bf855-571a-41ff-81f1-f1102b84486c Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix var usage: use explicit string type per codebase conventions Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/e96bf855-571a-41ff-81f1-f1102b84486c Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix App_EnableForDesign_DrawsCorrectly test for DropDownList toggle button The DropDownList renders a ▼ toggle button that the old TextField didn't have. Update the expected output in TabsTests to include the arrow character in the ColorPicker Name field rendering. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/04da7957-99cb-4aa2-b81a-bef8f66e8dec 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>
… string assignment (#5205) * Initial plan * Add TrySetValueFromString to IValue with default IParsable-based impl Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/6c89d797-144a-49e4-8ae5-2cead8fc01d7 Co-authored-by: tig <585482+tig@users.noreply.github.com> * polish: improve test class comment wording per code review Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/6c89d797-144a-49e4-8ae5-2cead8fc01d7 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Update examples to demonstrate IValue.TrySetValueFromString - InlineColorPicker: Add --initial <color> CLI arg with error on invalid - InlineSelect: Add --initial <label|index> with label matching and error - UICatalog Popovers: Add Initial Value TextField, apply via TrySetValueFromString - PromptExample: Add Initial Value TextField, apply to all prompt views - OptionSelector: Sync FocusedItem when Value changes via OnValueChanged Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor argument parsing to use switch statement Refactored command-line argument parsing from if/else to a switch statement with pattern matching for better clarity and maintainability. Improved error handling for missing argument values and changed orientation variable to explicit Orientation type. --------- 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> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Initial plan * Render to /dev/tty (Unix) / CONOUT$ (Windows) when stdio is redirected Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/882d62e1-b36c-4d97-8db5-faf391ceedbf Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address review feedback: clarify ttyFd ownership; drop unused Windows P/Invokes Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/882d62e1-b36c-4d97-8db5-faf391ceedbf Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address review comments with clarifying documentation Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/882d62e1-b36c-4d97-8db5-faf391ceedbf 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>
…te (#5210) * Initial plan * Fix TableView header separator lines drawing with focus attribute The RenderHeaderMidline method was setting the focus/header color attribute before drawing separator lines (│), causing the vertical lines between column headers to be rendered with the focus scheme instead of the normal scheme. This fix resets to Normal attribute before drawing separators and only applies the focus attribute to the header text content itself. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a4c155ae-c77c-493c-8ef2-80b80b7ad6e2 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>
* Initial plan * Fix FlagSelector ENTER to only accept without toggling Add virtual ActivateOnAccept property to SelectorBase (defaults true for OptionSelector). FlagSelector overrides it to return false so Enter just accepts without toggling the focused item. Fixes #4473 Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/09dfd0cb-27bb-492f-96b9-591785e1a870 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>
…ue<T> (#5204) * Add design plan for LinearRange IValue<T> refactor and clet * Refactor LinearRange to implement IValue<T> with three subclasses Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/57da70ed-e15b-4920-bd6b-93632a201607 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Remove redundant with {} expression in LinearRange.SpanFromIndices Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/57da70ed-e15b-4920-bd6b-93632a201607 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address PR review: split tests, add visual tests, fix mouse drag, remove legend styling Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/9d0abd93-a506-4979-85bb-22af119cf919 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix CI: update HardCoded cache test to new LinearRangeDefaults config key Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/f3929ef5-6b66-40b7-a053-0e3720beb424 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add IDesignable.EnableForDesign() to each LinearRange subclass with meaningful demo data Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/43266cee-38bb-4815-a0ce-ff63e04a47ea Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix mouse drag for LinearRange: anchor-based drag for Closed; set semantics for Left/Right Bounded Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/71b66d9b-c491-4a62-8a0c-7ffef88baea4 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add non-generic LinearSelector / LinearMultiSelector / LinearRange so AllViewsTester can discover them Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d920e093-379a-4605-8b6b-07b1534379e7 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Default DragChar to ContinuousMeterSegment so it matches SetChar Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/cca84663-bd59-4b21-9e91-b98cd066370e Co-authored-by: tig <585482+tig@users.noreply.github.com> * Remove redundant ClearViewport in LinearRange draw to fix drag flicker Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/5eb88b7e-3e39-48b9-94d3-54e195158efd Co-authored-by: tig <585482+tig@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Add SelectedIndex to LinearSelector for unambiguous "no selection" with value-type T Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/e66c5848-2678-4c7b-ad85-65bd43f9441a Co-authored-by: tig <585482+tig@users.noreply.github.com> * Use HashSet to dedupe indices in LinearMultiSelector.Value setter (O(n) instead of O(n^2)) Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/276579a1-65c0-4471-8259-316631a8697b Co-authored-by: tig <585482+tig@users.noreply.github.com> --------- Co-authored-by: Claude <noreply@anthropic.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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…rd.SetClipboardDataImpl (#5218) * Initial plan * Fix PowerShell command injection in WSLClipboard.SetClipboardDataImpl Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/c07e3cd8-aa15-4626-bdd0-86c06af73814 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: BDisp <bd.bdisp@gmail.com>
… symlinks in search (#5222) * Initial plan * Fix FileDialog path-traversal in Rename/New and symlink-loop in search - Add IsContainedIn() and ContainsInvalidNameCharacters() validation to DefaultFileOperations.Rename and DefaultFileOperations.New to reject names that would traverse outside the parent directory. - Add reparse-point check in FileDialog.SearchState.RecursiveFind to prevent infinite recursion through symlink loops. - Make FileSystemTreeBuilder.IsReparsePoint internal for reuse. - Add fdPathTraversalError string resource. - Add unit tests for path validation helpers. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/711b726c-fb95-4ee0-83e3-685962f6ae15 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refactor: validate name characters before Path.Combine for early detection Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/711b726c-fb95-4ee0-83e3-685962f6ae15 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>
…njection (#5223) * Initial plan * Security: Sanitize control characters in MakePrintable to prevent terminal escape injection Fix CVE: Untrusted text containing ESC bytes (and other C0/C1 control characters) was being emitted verbatim to the terminal, enabling terminal hijacking via MarkdownView, Label, TextView, FileDialog, etc. The fix strengthens MakePrintable (both string and Rune overloads) to: - Handle multi-character graphemes containing control characters (previously only single-char strings were sanitized) - Map C0 controls (U+0000-U+001F except TAB) and DEL (U+007F) to Unicode Control Pictures (U+2400-U+247F) - Map C1 controls (U+0080-U+009F) to space (no standard pictures exist) - Preserve TAB (U+0009) which is handled by higher layers Also fixes FillRect path in OutputBufferImpl which bypassed MakePrintable entirely. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d29b6d3b-b419-4fa8-86d5-08fbfa0d8c47 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address code review: fix ternary formatting and test comment style Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d29b6d3b-b419-4fa8-86d5-08fbfa0d8c47 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix TAB passthrough, restore C1 control pictures, remove per-char scan - TAB no longer passes through raw (maps to U+2409 like all C0 controls) - C1 controls (U+0080-U+009F) map via +U+2400 offset (distinct visuals) - Remove per-char loop scan for multi-char graphemes: per UAX #29, controls are always grapheme cluster boundaries, so only first char needs checking - Rune.MakePrintable reverted to original one-liner (all controls: +0x2400) Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/86f1970c-dfbd-4840-800c-694a7c58ee6f 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>
…lace cmd /c start with ShellExecute on Windows (#5220) * Initial plan * Fix: Link.OpenUrl - scheme allowlist + Windows ShellExecute instead of cmd /c start Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/8a20670d-ff32-4746-8148-c18c8662d0ce Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix: wrap Process.Start calls in try/catch in OpenUrl; log failures via Logging.Warning Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a67fc977-19a7-41e3-97a8-74e992e2a374 Co-authored-by: tig <585482+tig@users.noreply.github.com> * docs: expand SafeSchemes XML docs with file:// migration path guidance Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/3dd2f7cc-01bd-4c26-b35d-48c0265cb2a8 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>
) * Initial plan * Security: Bound held content in ANSI parser to prevent memory DoS Add MaxHeldLength (8 KiB) cap to AnsiResponseParserBase that releases held content when exceeded, preventing unbounded memory growth from malformed/unterminated escape sequences. Add MaxMouseSequenceLength (64) guard to AnsiMouseParser to prevent regex evaluation against pathologically large inputs. Add MaxKeyboardSequenceLength (64) guard to AnsiKeyboardParser to prevent pattern evaluation against oversized inputs. Fixes gui-cs/Terminal.Gui#5268 Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/f5bd020a-34cc-4ccb-b87a-f3b2869cc291 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address review: add model name to test file comment Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/f5bd020a-34cc-4ccb-b87a-f3b2869cc291 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>
…#5228) * Initial plan * Fix links inside markdown table cells not being clickable Add OnActivated handler and HitTestLink method to MarkdownTable that detects clicks on link segments within table cells. Wire up table LinkClicked events to parent Markdown.RaiseLinkClicked during layout. Add Link Shortcut to MarkdownTester and Deepdives scenario status bars that displays the URL when a link is clicked. Fixes #4194 Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/2964a27b-2b38-420f-9a4c-58370d56481a Co-authored-by: tig <585482+tig@users.noreply.github.com> * Apply guard clause pattern in table link event handler Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/2964a27b-2b38-420f-9a4c-58370d56481a Co-authored-by: tig <585482+tig@users.noreply.github.com> * Remove Link shortcut from status bars; update EnableForDesign with link in table and opt-in pattern - Revert MarkdownTester and Deepdives scenario status bar changes - Update MarkdownTable.EnableForDesign: "Markdown" feature is now a link to the API docs URL - Update Markdown.EnableForDesign: opt-in to links (e.Handled = true) - Update DefaultMarkdownSample table to include a Markdown link - Add LinkClicked opt-in handler in MarkdownTester scenario Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/f22d1b3d-f89f-490b-b473-6d377cecf888 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add OSC8 rendering, Tab navigation, and focus support for links in MarkdownTable - Set Driver.CurrentUrl when drawing link segments for OSC8 hyperlink support - Add link region tracking and Tab/Shift-Tab cycling through table links - Make table focusable when it contains links (CanFocus/TabStop) - Highlight active link with reversed colors when focused - Add OnAdvancingFocus, OnHasFocusChanged, and Command.Accept handler - Refactor link activation into RaiseLinkClicked helper Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/52a328bc-4eed-4105-99cb-c275980815ad Co-authored-by: tig <585482+tig@users.noreply.github.com> * Enhance Markdown sample and UI Catalog docs Updated README to link UI Catalog to Terminal.Gui repo. Improved MarkdownTester preview layout and link handling. Expanded DefaultMarkdownSample with a TOC and richer markdown feature examples for better demonstration and testing. * Expand [!INCLUDE] in Deepdives Markdown viewer Added support for expanding Markdown [!INCLUDE] directives in the Deepdives scenario by fetching, caching, and substituting include files from the GitHub API. Introduced async loading of includes and updated document rendering to process includes before display. * Fix link region dedup: track by position (row/col), not just URL - TableLinkRegion now stores RowIndex and ColIndex for unique identification - BuildLinkRegions deduplicates within a cell only (same URL in different cells creates separate navigable entries) - IsActiveLinkAt checks position + URL so only the focused link highlights - HitTestLinkIndex maps click position to exact link region index - Active highlight no longer gated on absolute-URI (relative URLs and anchors now render reversed when focused) - Deepdives scenario sets e.Handled=true to prevent Link.OpenUrl from firing Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/a0be0231-70d1-45f0-b871-6e2e52af36c2 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add unit tests for Tab/Shift-Tab link navigation and Enter activation in MarkdownTable Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/188a4908-34b9-4078-b74e-4e213a039764 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix style: use explicit List<string> type instead of var Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/188a4908-34b9-4078-b74e-4e213a039764 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix anchor links in table cells not scrolling to headings Table links with #anchor URLs now call ScrollToAnchor on the parent MarkdownView, matching the behavior of paragraph anchor links. Also prevent Link.OpenUrl from being called for anchor URLs (meaningless). Added tests proving: - Issue 1 (anchor links don't navigate): confirmed and fixed - Issue 2 (duplicate URL dedup): confirmed false - the dedup is correctly scoped per-cell only; same URL in different cells creates separate navigable entries Co-authored-by: Copilot <223556219+Copilot@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> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Updated the supported versions and reporting instructions.
* Initial plan * Add IValue<int> support to ScrollSlider ScrollSlider now implements IValue<int> with Value as an alias for Position. Raises ValueChanging, ValueChanged, and ValueChangedUntyped events. Position property remains for backwards compatibility. ScrollBar already implements IValue<int> - no changes needed. Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/63c3a7ee-d671-449a-a1e1-a912d0cf9c95 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Improve XML docs on ScrollSlider.Value property Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/63c3a7ee-d671-449a-a1e1-a912d0cf9c95 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: BDisp <bd.bdisp@gmail.com>
* Fixes #5153. Make Markdown forward HotKey to next peer like Label When CanFocus is false and a valid HotKey is set, Markdown now forwards Command.HotKey to the next peer in SuperView.SubViews — mirroring the existing Label behavior. This lets a non-focusable Markdown view describe a focusable peer (e.g. a TextField) and move focus there when its hotkey is pressed, addressing the inline-clickable-link use case from #5153 without adding new markup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix Markdown text-derived hotkeys Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document Markdown.HotKeySpecifier divergence from Label Add <remarks> noting that Markdown derives HotKey from Text (raw markdown) rather than Title — because Markdown.Text doesn't flow through Title the way Label.Text does. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… type-to-search (#5232) The CollectionNavigator property doc says "Set to null to disable this feature," but the property type was non-nullable and CycleToNextTableEntryBeginningWith dereferenced it without a guard, so setting it to null would NRE. Make the property nullable and add an early-return guard in CycleToNextTableEntryBeginningWith. With CollectionNavigator = null, printable keys not otherwise bound now bubble through normal key handling instead of being consumed for incremental row navigation — letting apps use single-letter shortcuts while focus remains in the table. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: BDisp <bd.bdisp@gmail.com>
…any cell (#5233) * Fixes #5126. TableView: don't raise Activating when click is outside any cell Override OnActivating to cancel activation when a left-click lands in the header area or below the last data row. Previously, ScreenToCell-returned- null was only handled inside OnActivated, by which time the Activating event had already fired with no real selection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Address review: reject clicks in horizontal whitespace; expand tests ScreenToCell maps far-right X positions onto the last rendered column (its column lookup picks the largest X with X <= clientX, with no upper-bound check). When ExpandLastColumn is false there is visible whitespace to the right of the last column; without an X-bound check those clicks would still raise Activating. Add IsXWithinAnyRenderedColumn and apply it inside TryGetMouseCellHit so the check runs only on the activation path; ScreenToCell's public API behavior is unchanged. Add tests: - Click_RightOfLastColumn_DoesNotRaise_Activating (ExpandLastColumn=false) - Click_OnHeader_DoesNotRaise_Activating - Click_EmptyTable_DoesNotRaise_Activating - Click_TableWithZeroRows_DoesNotRaise_Activating Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Fixes #5076. Allow hiding TableView outer vertical lines Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update TableView test scenario for outer vertical lines Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tig <tig@users.noreply.github.com>
* Initial plan * Use glyphs for markdown checklist items Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Document markdown list marker translation Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Clarify markdown checkbox marker alignment Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Tidy markdown marker review feedback Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Refine markdown checkbox marker readability Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Simplify markdown marker translation helper Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Use ordinal markdown marker comparisons Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Complete markdown marker helper docs Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/fc4319e1-6267-4b21-ae7b-b88593a2ffa0 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Address review: StartsWith in TranslateListMarkerText, consistent GetColumns in indent calc - TranslateListMarkerText: use StartsWith + slice instead of string.Equals so clipboard output stays correct even if prefix+content segments merge. - Indent calc: use marker.GetColumns() instead of marker.Length in both task-item and regular-item paths for consistent column-count units. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * code cleanup. Refactor for code style, clarity, and cleanup Refactored variable declarations to use explicit types per code style. Renamed functions and variables for naming consistency. Simplified logic using pattern matching and inlined conditionals. Reformatted switch expressions for readability. Removed unused `HitTestLink` method. Updated comments and XML docs for clarity. --------- 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> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Initial plan * Initial investigation - identified root cause of table height bug Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/45793f28-879a-4343-aeae-67c066c28785 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Fix table row height calculation: capture RenderedHeight before Add() triggers EndInit cascade Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/45793f28-879a-4343-aeae-67c066c28785 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>
* Initial plan * Fix AOT hard-coded key binding clone Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/275ee9b0-ace3-402a-a75e-18ca75db4388 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Match nullable key array test helper Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d1e76594-a3c8-4c84-b738-3decfdb73987 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Use precise nullable warning suppression Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d1e76594-a3c8-4c84-b738-3decfdb73987 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Use record with expression for key binding clone Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/094cf268-64cd-42e9-9179-af0d70e786a2 Co-authored-by: tig <585482+tig@users.noreply.github.com> * Add AOT-safety comment to CloneHardCodedPropertyValue Co-authored-by: Copilot <223556219+Copilot@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> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic back-merge after release v2.1.0-beta.1. Merge this to keep
developin sync withmain.