luautf8 0.2.0 - Modernized API & New Truncation Features
🚨 Breaking Changes
This release modernizes the width-related APIs with breaking changes to parameter names and order. Most users are unaffected (if you only pass the string argument), but please review the migration guide below if you use the ambi_is_double parameter.
API Changes
utf8.width() and utf8.widthindex() now use:
Integer ambiwidth (1 or 2) instead of boolean ambi_is_double
New optional byte range parameters i, j for substring operations
Returns truncation position (safe character boundary) and remaining width
Examples:
-- Measure width of substring
local pos, width = utf8.widthlimit("你好world", nil, 1, 11)
-- pos=11, width=9
-- Truncate from front (keep prefix)
local pos, remain = utf8.widthlimit("hello world", 5)
-- pos=5, remain=0 → s:sub(1, pos) == "hello"
-- Truncate from back (keep suffix)
local pos, remain = utf8.widthlimit("/path/to/file.lua", -8)
-- pos=10, remain=0 → s:sub(pos) == "file.lua"
-- Handle fullwidth characters
local pos, remain = utf8.widthlimit("你好世界", 5)
-- pos=6, remain=1 (2 fullwidth chars fit, 1 width unused)
Use cases:
Terminal output formatting
Text truncation with ellipsis
Column-width calculations
Path shortening
Enhanced Width Functions
Both utf8.width() and utf8.widthindex() now support byte range parameters for substring operations:
-- Calculate width of bytes 6-11
local width = utf8.width("hello你好world", 6, 11)
-- width=4 ("你好")
-- Find character at width 3 within bytes 6-11
local idx = utf8.widthindex("hello你好world", 3, 6, 11)
-- Search only within "你好" substring
Version Constant
Added utf8.version constant (returns "0.2.0").
📚 Documentation Improvements
Rewritten API docs in Lua official manual style
Consistent parameter naming:
s = string
i, j = byte positions (1-based, inclusive)
n = character index
ambiwidth = ambiguous-width handling (1 or 2)
Comprehensive examples for all functions
Fixed grammar and formatting throughout README
🧪 Testing
Added extensive test coverage for utf8.widthlimit()
Basic truncation (positive/negative limits)
Fullwidth characters and mixed-width strings
Substring ranges and edge cases
Ambiguous-width character handling
Updated existing tests for new API signatures
All tests passing with 100% coverage
🔧 Technical Details
Why the API change?
Consistency: Integer ambiwidth is more intuitive than boolean ambi_is_double
Flexibility: Byte range parameters enable efficient substring width operations
Clarity: "ambiwidth=2" is clearer than "ambi_is_double=true means width 2"