Skip to content

fix(tui): fixed link bug with glamour update#86

Merged
ontehfritz merged 3 commits intomainfrom
85-bugtui-with-the-upgrade-of-glamour-links-broke
Mar 28, 2026
Merged

fix(tui): fixed link bug with glamour update#86
ontehfritz merged 3 commits intomainfrom
85-bugtui-with-the-upgrade-of-glamour-links-broke

Conversation

@ontehfritz
Copy link
Copy Markdown
Contributor

@ontehfritz ontehfritz commented Mar 28, 2026

Summary by CodeRabbit

  • New Features

    • Improved terminal input handling and more responsive mouse hover/motion; updated viewport and address-bar resizing; view rendering now uses a new wrapper that enables alt-screen and mouse-motion modes.
  • Bug Fixes

    • More reliable hyperlink handling: proper OSC 8 link detection (including BEL/ST terminations), accurate marker placement, and improved escape-sequence filtering during rendering.
  • Tests

    • Added tests for OSC 8 hyperlink handling and visible-text detection.
  • Documentation

    • Updated preflight instruction wording for session confirmation.

@ontehfritz ontehfritz linked an issue Mar 28, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Reworks TUI hyperlink handling to detect OSC 8 hyperlink regions, match links by URL/visible-text within those regions, and inject start/end markers accordingly; updates parsing to skip OSC (BEL/ST) and CSI escapes and adapts Bubble Tea API/viewport/mouse key changes and tests to exercise OSC 8 behavior.

Changes

Cohort / File(s) Summary
TUI hyperlink parsing & marker injection
client/cmd/demarkus-tui/main.go
Added OSC 8 parsing helpers (findHyperlinkRegions, parseOSC, textStartAfterOSC, hyperlinkRegion); refactored injectLinkMarkers to match links.LinkInfo to OSC 8 regions by URL and visible-text and insert sorted rune-based markers; updated escape scanning to handle CSI and OSC (BEL/ST) via shared escapeState/handleEscape.
Link marker unit tests
client/cmd/demarkus-tui/links_test.go
Added osc8(url, text) helper; updated TestInjectLinkMarkers to build inputs using OSC 8 sequences and assert marker presence/positions; extended TestFindVisibleText with cases for OSC terminated by BEL and ST.
Bubble Tea API & input handling updates
client/cmd/demarkus-tui/main.go, client/cmd/demarkus-tui/graphview.go
Switched Bubble Tea imports to v2; replaced tea.KeyMsg/tea.MouseMsg with tea.KeyPressMsg/tea.MouseClickMsg/tea.MouseMotionMsg; adapted handlers and message fields; changed viewport/address bar creation and runtime SetWidth/SetHeight APIs; View now returns tea.View.
Dependency changes
client/go.mod
Replaced charmbracelet packages with charm.land v2 equivalents (bubbletea, bubbles, lipgloss) and bumped various indirects (ultraviolet, x/sys, x/sync, go-runewidth).
Docs/meta tweak
CLAUDE.md
Updated preflight instruction text to direct stopping and asking the developer rather than the user.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Possibly related PRs


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive Title follows Conventional Commits format with valid type 'fix' and scope 'tui', but is vague—'glamour update' doesn't describe the actual changes (Bubbletea v2 migration, OSC 8 hyperlink handling, viewport API refactoring). Clarify the title to reflect the primary change. Consider 'fix(tui): handle OSC 8 hyperlinks with Bubbletea v2 migration' or similar to convey the scope of changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 85-bugtui-with-the-upgrade-of-glamour-links-broke

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/cmd/demarkus-tui/main.go`:
- Around line 1004-1016: The function textStartAfterOSC currently assumes end
points at the ESC and returns end+2, but the OSC-handling code returns end
pointing at the trailing '\' for ST terminators (see the earlier return of
end+1), so adjust textStartAfterOSC to advance only one rune for ST-terminated
sequences: detect BEL vs ST as before (runes[end] == '\x07' -> end+1) and for
the ST case return end+1 instead of end+2 so the visible textStart aligns with
the first visible rune; update the textStartAfterOSC function accordingly.
- Around line 937-942: The OSC URL comparison needs normalization to ignore URL
fragments: before computing urlMatch in the loop that iterates over hyperlinks
(variables: hyperlinks, used, hl.url, info.Dest, info.Text), strip or remove the
fragment portion (the part after '#') from hl.url and from info.Dest (or
normalize hl.url to the same form as LinkInfo.Dest which already has fragments
removed) and then perform the equality/suffix checks; update the urlMatch
computation to compare the fragment-stripped values (or use a parsed URL with
Fragment cleared) so links like page.md#top match LinkInfo.Dest and get markers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e4804128-b730-441b-8d3b-e91c54c02c8c

📥 Commits

Reviewing files that changed from the base of the PR and between 6da717e and 03b9862.

📒 Files selected for processing (2)
  • client/cmd/demarkus-tui/links_test.go
  • client/cmd/demarkus-tui/main.go

@ontehfritz
Copy link
Copy Markdown
Contributor Author

@coderabbitai what is left to get approval?

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== PR Status ==="
gh pr view 86 --repo latebit-io/demarkus --json state,reviewDecision,statusCheckRollup,reviews

echo "=== Open Review Comments ==="
gh pr view 86 --repo latebit-io/demarkus --json comments --jq '.comments[] | select(.author.login != null) | {author: .author.login, body: .body[:200]}'

echo "=== Review Threads ==="
gh api graphql -f query='
{
  repository(owner: "latebit-io", name: "demarkus") {
    pullRequest(number: 86) {
      reviewThreads(first: 20) {
        nodes {
          isResolved
          comments(first: 1) {
            nodes {
              author { login }
              body
            }
          }
        }
      }
    }
  }
}'

Length of output: 9628


@ontehfritz Nothing — the PR is already in good shape:

  • Review decision: APPROVED
  • CI: All checks passed (test-client SUCCESS, others SUCCESS/SKIPPED)
  • Review threads: Both flagged issues are resolved

You're clear to merge.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
client/cmd/demarkus-tui/main.go (2)

952-957: ⚠️ Potential issue | 🟠 Major

Normalize fragments before URL matching.

links.LinkInfo.Dest is fragment-stripped, but hl.url may still contain #fragment. This misses valid matches, so markers are not inserted and those links won’t be reachable by Tab/click.

Proposed fix
 		for j, hl := range hyperlinks {
 			if used[j] {
 				continue
 			}
-			urlMatch := hl.url == info.Dest || strings.HasSuffix(hl.url, info.Dest) || strings.HasSuffix(info.Dest, hl.url)
+			hlURL := hl.url
+			if idx := strings.IndexByte(hlURL, '#'); idx != -1 {
+				hlURL = hlURL[:idx]
+			}
+			dest := info.Dest
+			if idx := strings.IndexByte(dest, '#'); idx != -1 {
+				dest = dest[:idx]
+			}
+			urlMatch := hlURL == dest || strings.HasSuffix(hlURL, dest) || strings.HasSuffix(dest, hlURL)
 			if urlMatch && hl.text == info.Text {
 				insertions = append(insertions,
 					insertion{runePos: hl.textStart, marker: string(markerStart(i))},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/cmd/demarkus-tui/main.go` around lines 952 - 957, The URL matching
misses cases where hl.url contains a fragment (e.g., `#anchor`) while info.Dest is
already fragment-stripped; update the matching logic in the loop over hyperlinks
(variables: hyperlinks, used, hl.url, info.Dest, info.Text) to normalize hl.url
by removing any fragment before comparing — e.g., parse or split hl.url to strip
the part after '#' and then perform the equality and HasSuffix checks against
info.Dest and keep the existing hl.text == info.Text check so markers are
inserted correctly for fragmented links.

1025-1032: ⚠️ Potential issue | 🟠 Major

ST-terminated OSC links start one rune late.

For ST (ESC \), parseOSC returns the trailing \ index, but textStartAfterOSC advances by 2. The start marker shifts right by one visible rune, causing partial highlight/click regions.

Proposed fix
-// textStartAfterOSC returns the rune index where visible text begins after an
-// OSC terminator. end points to the BEL or first byte of ST.
+// textStartAfterOSC returns the rune index where visible text begins after an
+// OSC terminator. parseOSC returns the BEL index or the trailing '\' of ST.
 func textStartAfterOSC(runes []rune, end int) int {
 	if end < len(runes) && runes[end] == '\x07' {
 		return end + 1
 	}
-	return end + 2 // skip \x1b\\
+	return end + 1
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/cmd/demarkus-tui/main.go` around lines 1025 - 1032, textStartAfterOSC
currently advances two runes for ST-terminated OSCs, which shifts the visible
start one rune too far; change the logic in textStartAfterOSC (and adjust
related handling in parseOSC if needed) so that when end points to BEL ('\x07')
or the ST backslash ('\\') you return end+1, and only return end+2 for the
legacy two-rune sequence case; reference the textStartAfterOSC function (and
parseOSC which returns the trailing '\' index) to locate and correct the ST
handling so ST-terminated OSC links start at the correct rune.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@client/cmd/demarkus-tui/main.go`:
- Around line 952-957: The URL matching misses cases where hl.url contains a
fragment (e.g., `#anchor`) while info.Dest is already fragment-stripped; update
the matching logic in the loop over hyperlinks (variables: hyperlinks, used,
hl.url, info.Dest, info.Text) to normalize hl.url by removing any fragment
before comparing — e.g., parse or split hl.url to strip the part after '#' and
then perform the equality and HasSuffix checks against info.Dest and keep the
existing hl.text == info.Text check so markers are inserted correctly for
fragmented links.
- Around line 1025-1032: textStartAfterOSC currently advances two runes for
ST-terminated OSCs, which shifts the visible start one rune too far; change the
logic in textStartAfterOSC (and adjust related handling in parseOSC if needed)
so that when end points to BEL ('\x07') or the ST backslash ('\\') you return
end+1, and only return end+2 for the legacy two-rune sequence case; reference
the textStartAfterOSC function (and parseOSC which returns the trailing '\'
index) to locate and correct the ST handling so ST-terminated OSC links start at
the correct rune.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8aef247a-c139-4dfd-b7aa-7b67ca60f533

📥 Commits

Reviewing files that changed from the base of the PR and between 03b9862 and 39d7acb.

⛔ Files ignored due to path filters (1)
  • client/go.sum is excluded by !**/*.sum
📒 Files selected for processing (4)
  • CLAUDE.md
  • client/cmd/demarkus-tui/graphview.go
  • client/cmd/demarkus-tui/main.go
  • client/go.mod

@ontehfritz ontehfritz merged commit 2d3321b into main Mar 28, 2026
5 checks passed
@ontehfritz ontehfritz deleted the 85-bugtui-with-the-upgrade-of-glamour-links-broke branch March 28, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(tui): with the upgrade of glamour links broke

1 participant