Adds 'Link' View providing OSC 8 Hyperlink Support#4741
Adds 'Link' View providing OSC 8 Hyperlink Support#4741ccoulioufr wants to merge 31 commits intogui-cs:v2_developfrom
OSC 8 Hyperlink Support#4741Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v2_develop #4741 +/- ##
==============================================
+ Coverage 77.54% 77.60% +0.05%
==============================================
Files 461 462 +1
Lines 46088 46222 +134
Branches 6835 6864 +29
==============================================
+ Hits 35741 35869 +128
+ Misses 8350 8347 -3
- Partials 1997 2006 +9
... and 4 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
|
Really nice, I've often wanted to do this (have a hyperlink but shorter text representation). Didn't know it was possible! Are there any older terminals where the output escape sequences are not supported or worse break output rendering? Is it worth adding a configuration manager setting for disabling the output? |
tig
left a comment
There was a problem hiding this comment.
See my ask. This is very cool. Windows Terminal automatically makes things hat look like URLs be clickable. But other terminals don't. I think this is a great add to the library.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new Link view to Terminal.Gui that enables OSC 8 hyperlink support, allowing developers to create clickable links in console applications when supported by the host terminal.
Changes:
- Adds a new
Linkview that displays text with an associated URL using OSC 8 escape sequences - Extends the rendering infrastructure (Cell, IOutputBuffer, IDriver, OutputBase) to track and render URL metadata
- Provides comprehensive test coverage with 14 unit tests covering various scenarios
- Includes a UICatalog scenario demonstrating Link functionality
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Terminal.Gui/Views/Link.cs | New Link view implementation with URL property, hyperlink rendering, and hotkey support |
| Terminal.Gui/Drawing/Cell.cs | Adds optional Url property to Cell record struct for OSC 8 support |
| Terminal.Gui/Drivers/IDriver.cs | Adds CurrentUrl property to IDriver interface |
| Terminal.Gui/Drivers/DriverImpl.cs | Implements CurrentUrl property by delegating to OutputBuffer |
| Terminal.Gui/Drivers/Output/IOutputBuffer.cs | Adds CurrentUrl property to IOutputBuffer interface |
| Terminal.Gui/Drivers/Output/OutputBufferImpl.cs | Implements CurrentUrl property and sets it on cells during drawing |
| Terminal.Gui/Drivers/Output/OutputBase.cs | Handles OSC 8 escape sequence generation during ANSI rendering |
| Tests/UnitTestsParallelizable/Views/LinkTests.cs | Comprehensive test suite with 14 tests covering Link functionality |
| Examples/UICatalog/Scenarios/Links.cs | Interactive demonstration scenario for the Link view |
| docfx/apispec/namespace-views.md | Updates documentation to include Link in the navigation controls category |
Comments suppressed due to low confidence (2)
Terminal.Gui/Views/Link.cs:5
- The class summary should be more descriptive and follow the pattern used by other views. Consider: "A view that displays clickable text with an associated URL. When supported by the terminal, the link is rendered using OSC 8 hyperlink sequences." This provides more context about the feature and how it works.
/// <summary>
/// Displays a clickable link with text and url.
/// </summary>
Examples/UICatalog/Scenarios/Links.cs:91
- Trailing comma on the last property in the object initializer. This line appears to be incomplete or could be cleaned up. If no additional properties are intended, the trailing comma should be removed.
Button copyButton = new ()
{
Title = "_Copy",
X = Pos.Center (),
Y = Pos.Bottom (link) + 2,
OSC 8 Hyperlink Support
en doc translation Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
url doc fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Hi there, All requested changes have now been implemented:
Coverage has been improved, although it can likely be increased further if needed. Regarding documentation: Please let me know if any further adjustments are required. |
Super great work!
Please see
Did you try: .\docfx\scripts\Build.ps1This will let you verify any new warnings. The docs are regenerated by the GH workflows on merge to v2_develop. |
According to my research, it will work in terminals supporting OSC 8:
So it's not a full support but not bad though. |
I'll have a look on it this week.
Here's the output error when trying to build doc (sorry for th french output):
|
Not supported is ok as long as it doesn't actively corrupt the output on any terminals. i.e. if a terminal ignores the codes because it doesn't understand them its fine but if its outputting them as literals it would be bad. |
@tig A test rendering a link on the driver was implemented using
|
Update Url property validation to retain previous value on invalid input.
tig
left a comment
There was a problem hiding this comment.
I looked at this again and I have questions. Are we sure this is the most efficient impl of this idea. This basically adds 8 bytes to every Cell and then each IDriver and IOutput impl
hold a string ref too.
All for a feature that will get used very rarely.
I wonder if there's a way to do this in a much less expensive way?
|
@tig Thanks for your feedback on the memory overhead issue! I've implemented some optimizations. 1. Removed
|
|
I'll take a closer look again soon. |
- Added static Link.OpenUrl for platform-specific URL opening; removed OpenUrl from UICatalogRunnable. - Link now handles mouse clicks and keyboard activation, opening URLs directly. - Improved drawing: shows Url if Text is empty, disables link if Url is invalid, always clears Driver.CurrentUrl. - Copy() now copies Text, not Url. - SetUrl validates URLs; invalid URLs revert to DEFAULT_URL. - IDesignable.EnableForDesign sets default Title and Text. - Refactored Links scenario UI for clarity and usability; status bar now shows Link's Text. - Updated all tests for new Link API and behaviors; improved test clarity. - Minor code style improvements and use of System.Diagnostics for process launching.
- IDesignable.EnableForDesign now sets Title and Url, not Text. - Copy() now copies Url to clipboard instead of Text. - Text, Title, and Url are now independent; setting one does not affect the others. - TextFormatter displays Url if Text is empty; otherwise uses Text. - DimAuto sizing uses Text width if set, otherwise Url, including wide chars. - Url property now accepts any string (no URI validation). - Setting the same Url does not fire change events. - UrlChanging event can cancel Url changes. - Rendering tests ensure invalid URLs do not produce OSC 8 hyperlinks and are styled as disabled. - Tests updated and expanded to cover all new behaviors and edge cases. - Minor test code cleanups and clarifications.
Add comprehensive XML docs for the Link class covering the three independent text properties (Text, Title, Url), OSC 8 hyperlink rendering, draw-time URL validation, CWP event pattern, HotKey-to-next-peer behavior, and Dim.Auto sizing. Enhance docs for all public members. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@ccoulioufr I did not mean to push directly to your branch! I meant to submit a PR to your PR but goofed. Hopefully that's ok, and you like the changes I made. Here's what I did: Refactored
Rewrote and expanded
|
|
Closing this in lieu of #4815. @ccoulioufr you can now revert your v2_develop branch back to head. |
|
@tig was there a problem with the branch name? should I have named it v2_develop/feat/link? |
Yea, you should have created a branch off of v2_develop (name doesn't really matter). No biggie though! Thank you for your awesome contribution. |
|
@tig One small point of attention regarding the URI validation. I noticed that In most cases this probably has negligible impact, but since rendering can occur frequently in a TUI (e.g., layout invalidation, refresh cycles, animations, etc.), repeatedly parsing the same URI could become unnecessary work if many An alternative approach could be to validate the URI when the Of course this is not a blocker, just a small performance consideration depending on how often the control might be redrawn. |
|
Great point. Would you please file this as an issue? |
New Feature:
LinkView (OSC 8 Hyperlink Support)Summary
This PR introduces a new feature to Terminal.Gui: a
Linkview.The
Linkview allows associating a visible text with a URL using the OSC 8 escape sequence when supported by the host terminal.Example: