ascii() and unascii() to help with broken utf-8 or binary data
This commit is contained in:
parent
bb8c4cd070
commit
a36ef944a3
21
README.md
21
README.md
@ -262,6 +262,27 @@ You can still resume it by typing `/eval_resume <text>` - the argument
|
|||||||
text will be passed instead of the context of text area of the formspec.
|
text will be passed instead of the context of text area of the formspec.
|
||||||
|
|
||||||
|
|
||||||
|
### More utilities
|
||||||
|
|
||||||
|
#### Binary data
|
||||||
|
|
||||||
|
##### `ascii()` and `unascii()`
|
||||||
|
|
||||||
|
Have you ever encountered "<invalid UTF-8 string>" somewhere with no
|
||||||
|
easy way to display it?
|
||||||
|
|
||||||
|
`ascii()` will allow you to inspect these strings (which may be just
|
||||||
|
some broken unicode or arbitrary binary data).
|
||||||
|
|
||||||
|
`ascii(str)` will escape all control sequences and unprintable
|
||||||
|
characters so you can output it normally. It works well with broken
|
||||||
|
strings, because printable ASCII characters will be kept unchanged.
|
||||||
|
|
||||||
|
The reverse of this is `unascii(str)`, which will take the escaped
|
||||||
|
sequence and turn it back into raw bytes. This supports only `\xFF`
|
||||||
|
hex escapes, but it works well enough in pair with `ascii()`.
|
||||||
|
|
||||||
|
|
||||||
### Resetting your personal environment
|
### Resetting your personal environment
|
||||||
|
|
||||||
If your environment gets messed up, or you just want to get rid of the
|
If your environment gets messed up, or you just want to get rid of the
|
||||||
|
4
init.lua
4
init.lua
@ -222,7 +222,9 @@ fsinput(label, text) -- show a form that will return the text you entered
|
|||||||
core.show_formspec(player_name, "cmd_eval:input", table.concat(fs, ""))
|
core.show_formspec(player_name, "cmd_eval:input", table.concat(fs, ""))
|
||||||
local result = coroutine.yield(WAIT_FOR_FORMSPEC)
|
local result = coroutine.yield(WAIT_FOR_FORMSPEC)
|
||||||
return result
|
return result
|
||||||
end
|
end,
|
||||||
|
ascii = util.ascii,
|
||||||
|
unascii = util.unascii,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__index = function(_self, key)
|
__index = function(_self, key)
|
||||||
|
65
util.lua
65
util.lua
@ -1,3 +1,5 @@
|
|||||||
|
local fmt = string.format
|
||||||
|
|
||||||
|
|
||||||
-- get actual eye_pos of the player (including eye_offset)
|
-- get actual eye_pos of the player (including eye_offset)
|
||||||
local function player_get_eye_pos(player)
|
local function player_get_eye_pos(player)
|
||||||
@ -69,11 +71,74 @@ local function get_pointed_position(player, range, point_to_objects, point_to_li
|
|||||||
return pointed_pos, pointed_thing
|
return pointed_pos, pointed_thing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local escapes = {
|
||||||
|
['\a'] = '\\a',
|
||||||
|
['\b'] = '\\b',
|
||||||
|
['\f'] = '\\f',
|
||||||
|
['\n'] = '\\n',
|
||||||
|
['\r'] = '\\r',
|
||||||
|
['\t'] = '\\t',
|
||||||
|
['\v'] = '\\v',
|
||||||
|
['\\'] = '\\\\',
|
||||||
|
['"'] = '\\"',
|
||||||
|
}
|
||||||
|
|
||||||
|
local unescapes = {
|
||||||
|
['\\a'] = '\a',
|
||||||
|
['\\b'] = '\b',
|
||||||
|
['\\f'] = '\f',
|
||||||
|
['\\n'] = '\n',
|
||||||
|
['\\r'] = '\r',
|
||||||
|
['\\t'] = '\t',
|
||||||
|
['\\v'] = '\v',
|
||||||
|
['\\\\'] = '\\',
|
||||||
|
['\\"'] = '"',
|
||||||
|
}
|
||||||
|
|
||||||
|
local function escape_nonascii(c)
|
||||||
|
return escapes[c] or string.format('\\x%02x', string.byte(c))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function ascii(str)
|
||||||
|
str = str:gsub('[%c\r\n\\"\128-\255]', escape_nonascii)
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function unescape_hex(backslashes, hex)
|
||||||
|
if #backslashes % 2 == 0 then
|
||||||
|
-- Even number of backslashes, they escape each other, not the digits.
|
||||||
|
-- Return them so that next step can treat them.
|
||||||
|
return backslashes .. 'x' .. hex
|
||||||
|
else
|
||||||
|
-- Remove the odd backslash, which escapes the hex code.
|
||||||
|
-- The rest will be processed by the next step.
|
||||||
|
backslashes = backslashes:sub(1, -2)
|
||||||
|
end
|
||||||
|
local c = string.char(tonumber(hex, 16))
|
||||||
|
if c == '\\' then
|
||||||
|
-- will be unsecaped by the next step ("\x5cb" --> "\\b")
|
||||||
|
c = '\\\\'
|
||||||
|
end
|
||||||
|
return backslashes .. c
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function unascii(str)
|
||||||
|
--str = str:gsub('(\\+)(%d%d%d)', unescape_digits)
|
||||||
|
str = str:gsub('(\\+)x(%x%x)', unescape_hex)
|
||||||
|
str = str:gsub('\\[abfnrtv\\"]', unescapes)
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local util = {
|
local util = {
|
||||||
player_get_eye_pos = player_get_eye_pos,
|
player_get_eye_pos = player_get_eye_pos,
|
||||||
raycast_crosshair = raycast_crosshair,
|
raycast_crosshair = raycast_crosshair,
|
||||||
raycast_crosshair_to_object = raycast_crosshair_to_object,
|
raycast_crosshair_to_object = raycast_crosshair_to_object,
|
||||||
get_pointed_position = get_pointed_position,
|
get_pointed_position = get_pointed_position,
|
||||||
|
ascii = ascii,
|
||||||
|
unascii = unascii,
|
||||||
}
|
}
|
||||||
return util
|
return util
|
||||||
|
Loading…
Reference in New Issue
Block a user