Skip to content

Fold text for clients without Unicode (AsciiFold) - #59

Merged
HarryCordewener merged 2 commits into
mainfrom
claude/project-thread-klqzka
Oct 9, 2026
Merged

HarryCordewener merged 2 commits into
mainfrom
claude/project-thread-klqzka

Conversation

@HarryCordewener

Copy link
Copy Markdown
Member

Requested by Grave · project thread

Before: with AsciiOnly, borders were drawn in ASCII but the text inside a block was left alone. A · in a title, a — or a café reached an ASCII client unchanged, and the caller's encoder turned it into ? or mojibake.

After: AsciiFold replaces each character the client cannot show with the nearest one it can. · and • become *, dashes -, curly quotes straight ones, é an e, a fullwidth letter the letter plus a space. Anything else becomes ?, once for each cell it took. new AsciiFold(latin1: true) keeps what Latin-1 has. A game's own stand-ins (new AsciiFold(translations)) come first and may be any width.

Every built-in stand-in is as wide as the character it replaces, so softcode-padded columns stay aligned. Set as LayoutContext.Fold, the fold runs on the text inside every block before the block is measured, so layouts stay aligned even with wider stand-ins.

How: AsciiFold.Fold(string | MarkupText) works on grapheme clusters, keeps each replaced character's markup and leaves point carriers alone. Accents and fullwidth forms come from built-in tables rather than string.Normalize, because Normalize does nothing under invariant globalization (checked with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1). New virtual Block.MapText is overridden by every built-in block and maps content and titles, not decoration. BlockLayout.Build/Lines/Relayout apply LayoutContext.Fold; the tree a LayoutMarkup carries stays unfolded. Docs in docs/layout.md, changelog under Unreleased.

This should ship after 2.16.0 (#58); it adds API, so it is a minor bump. The SharpMUSH side (charset plumbing, ascii_translations config) follows once it is released.

Tests: AsciiFoldTests (23) pass with and without invariant globalization; the full suite (1145) passes; whitespace format is clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wkz2sT8dyvFw7JXXNXvjYN


Generated by Claude Code

AsciiFold replaces each character an ASCII-only or Latin-1 client cannot
show with the nearest one it can, keeping markup and, for the built-in
stand-ins, each character's width. A game's own stand-ins come first.
LayoutContext.Fold folds the text inside every block before it is
measured, through Block.MapText, so layouts stay aligned.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wkz2sT8dyvFw7JXXNXvjYN
@HarryCordewener HarryCordewener self-assigned this Oct 9, 2026
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Warning

Review paused — included plan limit reached

Keep your review moving with free on-demand reviews.

  • Run this review for free

On-demand reviews are free for one more day.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Promotion and pricing details

On-demand reviews are free for one more day. After that, they cost $0.25 per reviewed file.

Review limit details

Or wait 27 minutes for your next included review.

Check out review usage here.

Limit details: You’ve used the included review currently available. Your 84 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Essentials
  • Run ID: e1731da8-f5f6-4775-97a8-030a89e89ff8
📥 Commits

Reviewing files that changed from the base of the PR and between c51d0c0 and 17f2b53.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • MarkupString.Tests/AsciiFoldTests.cs
  • MarkupString/AsciiFold.cs
  • MarkupString/Layout/Blocks/Block.cs
  • MarkupString/Layout/Blocks/BlockLayout.cs
  • MarkupString/Layout/Blocks/BlockText.cs
  • MarkupString/Layout/Blocks/BorderStyle.cs
  • MarkupString/Layout/Blocks/Bullets.cs
  • MarkupString/Layout/Blocks/Fields.cs
  • MarkupString/Layout/Blocks/Figure.cs
  • MarkupString/Layout/Blocks/Flex.cs
  • MarkupString/Layout/Blocks/Frame.cs
  • MarkupString/Layout/Blocks/Gauge.cs
  • MarkupString/Layout/Blocks/Modifiers.cs
  • MarkupString/Layout/Blocks/Table.cs
  • MarkupString/Layout/Blocks/TextBlock.cs
  • MarkupString/Layout/Blocks/Tree.cs
  • MarkupString/PublicAPI.Unshipped.txt
  • docs/layout.md
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wkz2sT8dyvFw7JXXNXvjYN
@HarryCordewener
HarryCordewener merged commit 3a33e36 into main Oct 9, 2026
7 checks passed
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.

2 participants