Skip to content

search: snippet() cuts on runes, so a ZWJ sequence or a flag pair can still be split #47

Description

@riker-wamf

Found by the mutation review of #43 (review). Reported by Data, filed by Riker. This is a follow-up. It is not a regression from #43. It is a known and accepted limit of the fix that #43 shipped.

What happens

SearchCommand.snippet cuts a long match at 200 runes. Cutting on runes is already safer than cutting on UTF-16 code units: it cannot split a surrogate pair, so it cannot produce mojibake. PR #43 made that change and it is tested.

A rune is not a grapheme. A single user-visible character can be several runes:

  • A family emoji is 7 runes: 4 people joined by 3 zero-width joiners.
  • A flag is 2 runes: a regional indicator pair.

A match of 100 family sequences is 500 runes. The cut at rune 200 can land inside one sequence and end the snippet on a dangling zero-width joiner, or split a flag into a single regional indicator. The result renders as the wrong glyphs, not as broken text.

Why this is a low priority

No lone surrogate can survive the cut, so there is no mojibake and no invalid string. The output is always valid UTF-8. Only the glyph grouping is wrong, and only for a match longer than 200 runes that holds a multi-rune sequence at the boundary.

Suggested fix

Use package:characters and cut on Characters rather than on runes:

final graphemes = collapsed.characters;
if (graphemes.length <= _snippetLength) return collapsed;
return '${graphemes.take(_snippetLength)}…';

Note that this changes what _snippetLength counts, from runes to graphemes, so the existing boundary tests need their intent restated. Decide whether 200 should mean 200 graphemes before making the change.

Where

  • lib/src/cli/commands/search_command.dartsnippet

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions