Truncater counts OSC sequence contents (hyperlinks) as printable width
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 1.1k
- Forks
- 57
- Avg merge
- 2h 55m
- Merged PRs (30d)
- 2
Description
Description
The CLI::UI::Truncater correctly skips CSI sequences (\x1b[...) when calculating printable width, but it doesn't handle OSC sequences (\x1b]...). This causes strings containing hyperlinks to be truncated much more aggressively than expected, since the URL inside the hyperlink escape codes is counted as printable characters.
Reproduction
require 'cli/ui'
# Create a hyperlink
url = "https://github.com/Shopify/shopify/pull/12345"
link = CLI::UI.link(url, "#12345") # displays as "#12345" but links to full URL
puts "Link string: #{link.inspect}"
puts "Printing width (ANSI.printing_width): #{CLI::UI::ANSI.printing_width(link)}"
# Try to truncate to 20 chars - should be plenty for "#12345"
truncated = CLI::UI::Truncater.call(link, 20)
puts "Truncated to 20: #{truncated.inspect}"
Expected behavior
ANSI.printing_widthcorrectly returns6(the length of#12345)Truncater.call(link, 20)should return the original string unchanged since#12345is only 6 characters
Actual behavior
ANSI.printing_widthcorrectly returns6✓Truncater.call(link, 20)truncates the string because it counts8;;https://github.com/Shopify/shopify/pull/12345(the URL inside the OSC sequence) as printable characters
Root cause
In lib/cli/ui/truncater.rb, the escape sequence parser only handles CSI sequences:
when PARSE_ESC
mode = case cp
when LEFT_SQUARE_BRACKET # 0x5b = '['
PARSE_ANSI
else
PARSE_ROOT # <-- OSC sequences start with ']' (0x5d), so they fall through here
end
OSC sequences have the format \x1b]...ST where ST is either \x07 (BEL) or \x1b\ (ESC + backslash). Since the Truncater doesn't recognize ] after ESC, it returns to PARSE_ROOT and counts the OSC content as visible characters.
Impact
This affects any use of CLI::UI::SpinGroup (spinners) with hyperlinks in titles. The spinner uses Truncater to fit titles to terminal width, causing hyperlink titles to be truncated far more than necessary.
Example output with a hyperlink in a spinner title:
┃ ⚠ https://github.com/Shop…
Even though there's plenty of terminal width remaining, the title is truncated because the hidden URL is counted.
Suggested fix
Add OSC sequence handling to the Truncater, similar to how ANSI.strip_codes already handles it:
RIGHT_SQUARE_BRACKET = 0x5d # ]
BACKSLASH = 0x5c # \
BEL = 0x07
# In the parser:
when PARSE_ESC
mode = case cp
when LEFT_SQUARE_BRACKET
PARSE_ANSI
when RIGHT_SQUARE_BRACKET
PARSE_OSC # New state for OSC sequences
else
PARSE_ROOT
end
when PARSE_OSC
# OSC sequences end with BEL or ESC+backslash
case cp
when BEL
mode = PARSE_ROOT
when ESC
mode = PARSE_OSC_END
end
when PARSE_OSC_END
# Expecting backslash to complete ST
mode = PARSE_ROOT
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/cli/ui/truncater.rb and compare its escape-sequence parsing with the OSC handling in ANSI.strip_codes. Update truncation so hyperlink URLs between OSC delimiters do not count toward printable width, then verify the reproduction: the hyperlink displaying as #12345 remains unchanged when truncated to 20 characters.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100