Release v2.2.0-rc.1#5324
Merged
Merged
Conversation
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/259ae3cf-ff29-45bc-83a9-ba299adadaff Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/259ae3cf-ff29-45bc-83a9-ba299adadaff Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/259ae3cf-ff29-45bc-83a9-ba299adadaff Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/259ae3cf-ff29-45bc-83a9-ba299adadaff Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/259ae3cf-ff29-45bc-83a9-ba299adadaff Co-authored-by: tig <585482+tig@users.noreply.github.com>
Back-merge v2.1.0 from main into develop
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Map char offsets back to columns in SyncAutoUrlsForRowCore so that multi-codepoint graphemes (ZWJ emoji, base + combining mark) before a URL no longer shift the auto-link metadata onto the wrong cells. - Null out _explicitUrlMap and _autoUrlMap in ClearContentsCore (and when SyncAutoUrlsForRowCore leaves _autoUrlMap empty) so GetCellUrl's null fast-path stays effective and RowContainsUrls doesn't acquire the contents lock per cell on URL-free buffers. Bump a UrlStateVersion counter so OutputBase can detect resets. - Track buffer reference, dimensions, and UrlStateVersion in OutputBase; drop _rowsWithUrls when any of those change so resize/clear no longer leaves stale row indices that would emit a spurious OSC 8 close at the start of the next render. - Refresh the Write XML summary that still mentioned WrapOsc8. - Add regression tests for the grapheme alignment, post-resize state, and GetCellUrl fast-path restoration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ity (#5279) * Fixes #5127. Anchor fixed-width button delimiters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixes #5127. Keep button highlight continuous Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fixes #5127. Refine OnDrawingText: cache GetDrawRegion, FillRect for full highlight - Cache _interiorTextFormatter.GetDrawRegion result; pass to GetDelimiterRow instead of recomputing it, eliminating a redundant layout pass. - Replace Driver.AddStr(new string(' ', width)) with Driver.FillRect(drawRect) so focus highlight covers all rows of a multi-row button, not just the text row. - Remove redundant Region.Combine union (interior region is always a subset of drawRect). - Add comment linking GetDecoratedText / GetInteriorText dual-path responsibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: guard _interiorTextFormatter assignments, mirror missing TextFormatter settings, add multi-row highlight test - Guard every _interiorTextFormatter property assignment with a value-equality check so NeedsFormat is not set spuriously on unchanged values - Mirror MultiLine, WordWrap, TabWidth, and PreserveTabs from TextFormatter to _interiorTextFormatter (previously unmirrored, potential behavioral regression) - Add Focused_FixedWidth_Button_MultiRow_Highlight_Is_Continuous test verifying all rows carry the Focus attribute when Height > 1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add ButtonDrawBenchmark to measure OnDrawingText guard performance Adds Tests/Benchmarks/Views/ButtonDrawBenchmark.cs with two methods: - DrawButton_Unchanged: steady-state draw (no property changes) — the guard-optimized path where NeedsFormat is never set spuriously - DrawButton_TextChanging: text rotates each iteration — forces a real reformat, approximating the old unguarded behaviour [MemoryDiagnoser] exposes the allocation difference between the two paths, quantifying the benefit of the guards added in the preceding commit. Run: dotnet run --project Tests/Benchmarks -c Release -- --filter "*ButtonDraw*" Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…5282) * Fixes #5273. Code block partial selection should not include fence delimiters When copying a partial selection that starts or ends inside a fenced code block, the copied text should not include the fence delimiters unless the selection actually crosses from non-code content into the code block. Root cause: GetSelectedText() unconditionally injected the opening fence whenever it first encountered a code-block line, and unconditionally injected the closing fence at the end of the loop if still inside a code block. This meant any selection touching a code block line would include fences, even if the selection was entirely within the code block. Fix: Replace the unconditional fence injection with two tracking flags: - selectionHasNonCodeContent: set true when any non-code line is processed. Opening fence is only emitted when transitioning from non-code -> code. - codeOpenFenceEmitted: tracks whether an opening fence was actually emitted for the current code block. Closing fence is only emitted when the matching opening fence was emitted. This ensures: - Selection entirely within a code block -> no fences (regardless of position) - Selection starting before a code block -> opening fence included - Selection ending after a code block -> closing fence included Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify the comment to reflect the adjacent-code-block case Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fixes #5270. Correct screen-row lookup in DrawSelectionOverlayOnSubViewRows ContentToScreen expects content-relative coordinates (where 0 = top of the content area), not viewport-relative coordinates. The old code passed drawRow (= lineIdx - Viewport.Y), so ContentToScreen subtracted Viewport.Y a second time, reading graphemes from the wrong screen row. With a non-zero scroll offset this caused the selection overlay to copy characters from an incorrect row (e.g. the table header) over the correct row (the table body), making body cell values disappear. Fix: pass lineIdx (content-relative) instead of drawRow. Added regression test SelectionOverlay_On_Table_Is_Synced_When_Scrolled that scrolls a Markdown view past introductory text so only a table is visible, activates a full selection, and asserts the body-row values (1, 2) remain in the screen buffer. The test height (5) is intentionally less than the total content height (7) so Viewport.Y = 2 is not clamped. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix partial selection highlight on code-block and table rows DrawSelectionOverlayOnSubViewRows was applying the selection attribute to every column of a subview row unconditionally. On the start/end lines of a selection this caused unselected columns to be highlighted, making it look as though the entire line was selected even when only part of it was. Fix: call IsInSelection(lineIdx, col + Viewport.X) per column, mirroring the per-grapheme check already in DrawRenderedLine for plain text lines. For non-selected columns the original Cell.Attribute from ScreenContents is restored so the subview styling is preserved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix selection overlay erasing popover content in code blocks DrawSelectionOverlayOnSubViewRows reads graphemes from ScreenContents (previous frame) and re-draws them with the selection attribute. Popovers draw before MarkdownView in the application draw loop, so their menu items are already written to the screen buffer when the overlay runs. Re-drawing those cells with stale ScreenContents graphemes silently erases the popover's content. Fix: compute the active popover's content view screen rect before the cell loop and skip any cell that falls inside it. The popover's draws are preserved; the selection highlight still covers all other cells. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…enu (#5283) Remove the base class Ctrl+LeftButtonReleased -> Command.Context mouse binding from Markdown.SetupBindingsAndCommands(). The base View registers this binding so Ctrl+Click can open a context menu, but the Markdown view already handles right-click directly in OnMouseEvent and uses Ctrl+Click for link following. Without this removal, Ctrl+Click would fire Command.Context -> ShowContextMenu() via the LeftButtonReleased event, showing the Select All/Copy popover at the upper-left corner (because no selection is active, GetContextMenuScreenPosition falls back to Point(0,0)). Add two regression tests: - MouseBindings_CtrlLeftButtonReleased_IsNotBoundTo_Context: verifies the binding is absent on a fresh Markdown instance - CtrlClick_On_Link_Opens_Link_And_Does_Not_Show_Context_Menu: end-to-end verification that Ctrl+Click fires LinkClicked without making the context menu visible Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…context menu (#5285) When the user right-clicks on a hyperlink in the Markdown view, the context menu now includes a 'Copy Link' item at the top (followed by a separator) that copies only the raw URL to the clipboard — not the display text. - Add _contextMenuLinkUrl field and FindLinkUrlAt helper (Mouse.cs) - ShowContextMenu detects link under right-click position and rebuilds context menu accordingly (Selection.cs) - CreateContextMenu prepends 'Copy Link' + separator when a link URL is detected (Selection.cs) Keyboard context menu (Shift+F10) is unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5289) Move value-update logic from OnMouseEvent into a Command.Activate handler bound via MouseBindings.Add. This makes mouse interaction cancellable by external code (e.g. TerminalGuiDesigner) which can clear the bindings. Add GrabMouse/UngrabMouse in OnMouseEvent so drag events are routed exclusively to the originating bar, preventing cross-bar drag contamination. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…state updates for terminal drivers
- Switch ConcurrentDictionary to Dictionary for _attributeCache - Use integer math for scaling logic to avoid double conversions - Implement reusable buffer for scaled image to reduce allocations during resize
…g and add coordinate conversion methods
…nt potential null reference exceptions
The condition added in 56eef0c ("emit OSC 8 close at row start whenever the row had URLs previously") was a defensive workaround for the apparent floating-underline symptom on Warp/Windows Terminal. Investigation of WT source shows the bug is in ControlCore::_updateHoveredCell()'s stale _lastHoveredCell cache (no callback fires when buffer content changes under a stationary cursor) — not in Terminal.Gui's emission. The cells themselves get _hyperlinkId = 0 correctly via AdaptDispatch::EndHyperlink when we emit `OSC 8 ; ; ST` followed by new cell content. Restoring the original (rowHadUrlsPreviously && \!rowHasUrlsNow) condition avoids a redundant escape on every row that still contains a URL after redraw. Also drops the regression test that pinned the redundant behavior. Separately, fix a real bookkeeping bug: _rowsWithUrls.Add/Remove was placed after the empty-builder early-exit at the end of the per-row block. Rows whose dirty cells were entirely flushed mid-loop via WriteToConsole (leaving the builder empty and _lastUrl null) skipped the row-tracking update, leaving stale entries that trigger spurious row-start OSC 8 closes on subsequent frames. Move the Add/Remove before the early-exit, and add a regression test that fails without the fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… gate Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/3b443135-7f15-4c33-8e7e-15547a017689 Co-authored-by: tig <585482+tig@users.noreply.github.com>
…#5290) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactored all scrolling benchmark and performance test classes to follow project code style: - Adopted uppercase constants for screen dimensions. - Reordered and grouped setup/cleanup and Params for clarity. - Used explicit types and target-typed new() per guidelines. - Moved PageDown_OneStep benchmarks for logical grouping. - Added new ListView performance tests for large datasets. - Relocated helper methods and updated var usage for built-in types. No functional changes; all updates are for style, structure, and maintainability.
… to 300 ms Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/2d6db6a8-5b60-441b-8a9a-d460c509c184 Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/8f0e14fd-f941-4c23-b417-91490e8bf050 Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/d8580cc4-ee57-4525-9fed-a3095db1b405 Co-authored-by: tig <585482+tig@users.noreply.github.com>
…//github.com/gui-cs/Terminal.Gui into copilot/add-code-token-visualrole-vocabulary
DeriveAccent now copies every Code* attribute from baseScheme (resolved via GetAttributeForRole) into the accent scheme as explicitly set values. Because GetAttributeForRole walks the derivation chain, even unset code-token roles on the base scheme become explicit on the accent. This means: (a) accent schemes will report TryGetExplicitlySetAttributeForRole(VisualRole.CodeXxx) as true even though the original theme didn't set them, and (b) future changes to baseScheme's Code attribute will no longer propagate to the accent's code tokens because the accent now pins concrete copies. Consider only copying values that were explicitly set on the base scheme (using TryGetExplicitlySetAttributeForRole) so derivation continues to work. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/89b866c3-6b09-44f6-b2b0-e4f10515d475 Co-authored-by: tig <585482+tig@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/89b866c3-6b09-44f6-b2b0-e4f10515d475 Co-authored-by: tig <585482+tig@users.noreply.github.com>
…-separated Agent-Logs-Url: https://github.com/gui-cs/Terminal.Gui/sessions/2dcbd1e9-8ca7-4562-ae6b-5fb1472cf0d2 Co-authored-by: tig <585482+tig@users.noreply.github.com>
…//github.com/gui-cs/Terminal.Gui into copilot/add-code-token-visualrole-vocabulary
…e-vocabulary Add code-token VisualRoles, Code view, theme palettes, and Markdown highlighting fixes
…onfig-manager Fixes #5310. Add ConfigurationManager / Scheme / Theme benchmark baseline
The configurable keybinding surface (Application/View DefaultKeyBindings, ViewKeyBindings, ApplyKeyBindings) is keyed by Command, so a View that needs a command the enum doesn't define has no sanctioned way to register it. Multi-caret editors (e.g. gui-cs/Editor's vertical multi-caret) need "add caret above/below"; nothing in the enum fits, forcing magic-int casts that don't round-trip through config by name. Adds two named members mirroring VS Code's editor.action.insertCursor Above / Below. Appended at the END of the enum so no existing member's implicit value changes (serialization-stable; no renumbering). No behavior change in TG itself — these are command ids for consumers to AddCommand + bind. A general Command-extensibility API (string ids / registry, bubbling/bridging) is tracked separately. Refs: #5318. Related: #4888. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#5319 shipped the two enum members with no tests. Add coverage for the parts of the contract that matter: - CommandInsertCaretEnumTests: members are defined, distinct, carry their readable names, and are appended at the END of the enum (no existing member renumbered) — the property that keeps persisted configs stable. - CommandInsertCaretKeyBindingTests: the #5318 acceptance criterion — Dictionary<Command, PlatformKeyBinding> round-trips through the config serializer (SourceGenerationContext) BY READABLE NAME, deserializes from the hand-written user-config form, and works nested under a per-view [ConfigurationProperty] dict ("Editor" → bindings) — exactly the gui-cs/Editor scenario the magic-int cast broke. All 9 new tests green in UnitTests.Parallelizable. Mirrors the existing KeyBindingSchemaTests style and uses the same canonical JSON options. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: add Command.InsertCaretAbove / .InsertCaretBelow (#5318)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8269e6c5ed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
This was referenced May 21, 2026
This was referenced May 28, 2026
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.
Release v2.2.0-rc.1
This is a rc pre-release.
Version:
2.2.0-rc.1NuGet Package:
Terminal.Gui 2.2.0-rc.1What happens when this PR is merged
v2.2.0-rc.1main→developwill be openedChecklist
2.2.0-rc.1