Drafter.CharacterWidth behaviour (drafter v0.3.1)

Copy Markdown View Source

Terminal display width of text, in columns.

Widths are per grapheme cluster, not per codepoint. Every measurement Drafter makes goes through here: strip widths, truncation, wrapping, cursor placement, and the compositor's column arithmetic.

Examples

iex> Drafter.CharacterWidth.string("drafter")
7

iex> Drafter.CharacterWidth.grapheme("漢")
2

iex> Drafter.CharacterWidth.grapheme("e\u0301")
1

Choosing an implementation

Drafter.CharacterWidth.Default is used when nothing is configured. A host that owns the grid Drafter draws into can supply its own tables instead:

config :drafter, character_width: ETee.CharacterWidth

The setting is read with Application.compile_env/3, so these functions compile to direct calls into the chosen module. Changing it takes effect on recompiling Drafter:

mix deps.compile drafter --force

Conformance

An implementation must measure printable ASCII as one column, C0 controls and combining marks as zero, and East Asian wide characters as two; U+FE0F and U+FE0E override the base character's presentation; and string/1 equals the sum of its graphemes. Drafter.CharacterWidthConformanceTest asserts all of this and can be run against a candidate module.

Summary

Types

A module implementing this behaviour.

Callbacks

Columns a single codepoint occupies, ignoring any cluster it belongs to.

Columns one grapheme cluster occupies. Zero for an empty string.

Whether a binary is entirely printable ASCII.

Columns a whole string occupies, summed over its grapheme clusters.

Types

implementation()

@type implementation() :: module()

A module implementing this behaviour.

Callbacks

codepoint(non_neg_integer)

@callback codepoint(non_neg_integer()) :: non_neg_integer()

Columns a single codepoint occupies, ignoring any cluster it belongs to.

grapheme(t)

@callback grapheme(String.t()) :: non_neg_integer()

Columns one grapheme cluster occupies. Zero for an empty string.

printable_ascii?(binary)

@callback printable_ascii?(binary()) :: boolean()

Whether a binary is entirely printable ASCII.

A true answer means the binary's byte size equals its column width, so callers may skip grapheme segmentation.

string(t)

@callback string(String.t()) :: non_neg_integer()

Columns a whole string occupies, summed over its grapheme clusters.

Functions

codepoint(codepoint)

See Drafter.CharacterWidth.Default.codepoint/1.

default?()

@spec default?() :: boolean()

Whether Drafter is measuring with its own tables rather than a host's.

grapheme(grapheme)

See Drafter.CharacterWidth.Default.grapheme/1.

implementation()

@spec implementation() :: implementation()

The implementation in use.

printable_ascii?(binary)

See Drafter.CharacterWidth.Default.printable_ascii?/1.

string(text)

See Drafter.CharacterWidth.Default.string/1.