Unicode Character Width in Luau

This article is also available on Medium.

I’ve released a new open-source package called luau-unicode-width.

This is a small, focused package that solves one specific problem: calculating the width of Unicode characters. If you’re building command-line tools in Luau and need to align text that contains emojis, accented characters, or other Unicode symbols, this might be what you’re looking for.

The Problem

Let’s say I want to generate some kind of header that looks like this:

------------
--- Name ---
------------

I have to know the length of the name, then add 6 for the - and 2 for the spaces. Then the lines can be generated with this:

local function display(name: string)
    local length = #name + 6 + 2
    print(string.rep("-", length))
    print(`--- {name} ---`)
    print(string.rep("-", length))
end

If the name is Luke, that works great:

------------
--- Luke ---
------------

But if I change the name for François, then it breaks:

-----------------
--- François ---
-----------------

The ç character takes more than a byte, so the string.len() or # operator cannot be used. Would using utf8.len() or utf8.graphemes() be better to get the width? In some cases yes. Let’s say I want to display Mike ✅:

# using utf8.len()
--------------
--- Mike ✅ ---
--------------
# using string.len()
----------------
--- Mike ✅ ---
----------------

It’s still not aligned in the terminal, since is one grapheme, but has a width of 2!

The Solution

This is where the library is helpful, it’ll give you the actual width you are looking for!

local UnicodeWidth = require('@pkg/luau-unicode-width')

local length = UnicodeWidth.width("Mike ✅") -- returns 7

That’s it! That’s only what is does. Now you can properly align your terminal output from a Unicode string.

Installation

For those using npm or yarn, simply add luau-unicode-width to your project dependencies by running:

npm install luau-unicode-width
# or
yarn add luau-unicode-width

You can also grab the Roblox model file attached to the latest release:

  1. Navigate to the GitHub releases
  2. Scroll to the Assets section and download the unicode-width.rbxm (Roblox model file)
  3. Drag the file into Roblox Studio

If you find any issues with the library, open an issue on GitHub.

End Notes

I’m aware that this library has a very specific use-case. People running code on Lune have a higher chance to find this useful. While it works in Roblox Studio, it’s not meant to replace TextService calculations at all. You will be able to align the text you print in the console like a pro though.

Useful Links

3 Likes