7

How can I get the 'right' formatting using string.format with strings containing UTF-8 characters?

Example:

local str = "\xE2\x88\x9E"
print(utf8.len(str), string.len(str))
print(str)
print(string.format("###%-5s###", str))
print(string.format("###%-5s###", 'x'))

Output:

1   3
∞
###∞  ###
###x    ###

It looks like the string.format uses the byte length of the infinity sign instead of the "character length". Is there an UTF-8 string.format equivalent?

2 Answers 2

4
function utf8.format(fmt, ...)
   local args, strings, pos = {...}, {}, 0
   for spec in fmt:gmatch'%%.-([%a%%])' do
      pos = pos + 1
      local s = args[pos]
      if spec == 's' and type(s) == 'string' and s ~= '' then
         table.insert(strings, s)
         args[pos] = '\1'..('\2'):rep(utf8.len(s)-1)
      end
   end
   return (
      fmt:format(table.unpack(args))
         :gsub('\1\2*', function() return table.remove(strings, 1) end)
   )
end

local str = "\xE2\x88\x9E"
print(string.format("###%-5s###", str))  --> ###∞  ###
print(string.format("###%-5s###", 'x'))  --> ###x    ###
print(utf8.format  ("###%-5s###", str))  --> ###∞    ###
print(utf8.format  ("###%-5s###", 'x'))  --> ###x    ###
Sign up to request clarification or add additional context in comments.

Comments

1

Lua added the UTF-8 library with version 5.3 with just small functionality for minimal needs. It's "fresh" and not really in focus for this language. Your issue is how the characters are interpreted & rendered but graphics isn't a point for the standard library or usual use of Lua.

For now, you should just fix your pattern for the input.

2 Comments

What do you mean with the "pattern for the input"? Do you say that I have not to use UTF-8 characters?
@Mario You already know to find the difference between bytes and characters number of your utf8 string. This difference you add to your width in pattern (to counter the wrong assumption of string.format).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.