Text::MiscUtils
WorksFour small text utilities under one distribution — English plurals and ordinals, terminal-aware wrapping and column widths, and the variation selectors that decide whether a glyph is drawn as emoji.
- Version
0.0.13zef:japhb- Depends
Terminal::ANSIColor- License
- Artistic-2.0
- Its own test suite
- 4 files, green
- Checked
- 2026-09-14 against Raku++ 3.28.0 and Rakudo 2026.08
Install it #
$ rakupp install Text::MiscUtilszef install Text::MiscUtils writes the same store; either installer leaves the module usable by both engines.
What it is for #
These are the functions you write badly, in a hurry, at the bottom of a script: the one that decides between "1 file" and "2 files", the one that turns 22 into "22nd", the one that wraps a paragraph to the terminal without cutting a CJK character in half. Each is a few lines and each has an edge case — 11 is not "11st", and a wide character is not one column — so having them written once and tested is worth more than the line count suggests.
The distribution is a namespace rather than a single module: ::English, ::Layout and ::Emojify are separate units, imported separately.
English, and layout #
::English is two subs. _s gives the plural suffix for a count, taking the suffix pair as optional arguments when "s" is not the right one, and ordinal gets the teens right:
use Text::MiscUtils::English;
say (1, 2, 3, 11, 22).map({ ordinal($_) }).join(' ');
for 0, 1, 2 -> $n { say "$n file{_s($n)}" }
say '3 bo', _s(3, 'xes', 'x');1st 2nd 3rd 11th 22nd
0 files
1 file
2 files
3 boxes::Layout measures and wraps in columns rather than characters, so it agrees with what a terminal will actually draw:
use Text::MiscUtils::Layout;
say '[' ~ $_ ~ ']' for wrap-text(24, 'The quick brown fox jumps over the lazy dog');
say duospace-width('hello 世界'), ' columns, ', 'hello 世界'.chars, ' characters';[The quick brown fox ]
[jumps over the lazy dog ]
10 columns, 8 charactersThe brackets are there to show something the fence would otherwise hide: wrap-text returns a list of lines each padded out to the full width, not trimmed. That is what you want when the block is going into a column beside another one, and a surprise if you were expecting bare text — pass :!fill-trailing to wrap-text's sibling text-wrap when you want it off.
::Emojify is the smallest of the three: emojify appends U+FE0F to a character so a dual-presentation glyph is drawn in colour, and textify appends U+FE0E so it is drawn as text.
The one thing to know #
use Text::MiscUtils; imports nothing at all. The top-level unit exists to hold the namespace and exports no subs, so the natural first line gets you a clean compile and then Undefined routine 'ordinal' at the point of use — the same message on both engines, which is at least an unambiguous one.
Import the unit you want by name: use Text::MiscUtils::English;, use Text::MiscUtils::Layout;, use Text::MiscUtils::Emojify;. There is no single import that brings in all three.