mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 06:48:17 +00:00
feat(lua): add vim.iconv (#18286)
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
@@ -881,6 +881,22 @@ vim.str_byteindex({str}, {index} [, {use_utf16}]) *vim.str_byteindex()*
|
|||||||
An {index} in the middle of a UTF-16 sequence is rounded upwards to
|
An {index} in the middle of a UTF-16 sequence is rounded upwards to
|
||||||
the end of that sequence.
|
the end of that sequence.
|
||||||
|
|
||||||
|
vim.iconv({str}, {from}, {to}[, {opts}]) *vim.iconv()*
|
||||||
|
The result is a String, which is the text {str} converted from
|
||||||
|
encoding {from} to encoding {to}. When the conversion fails `nil` is
|
||||||
|
returned. When some characters could not be converted they
|
||||||
|
are replaced with "?".
|
||||||
|
The encoding names are whatever the iconv() library function
|
||||||
|
can accept, see ":Man 3 iconv".
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{str} (string) Text to convert
|
||||||
|
{from} (string) Encoding of {str}
|
||||||
|
{to} (string) Target encoding
|
||||||
|
|
||||||
|
Returns: ~
|
||||||
|
Converted string if conversion succeeds, `nil` otherwise.
|
||||||
|
|
||||||
vim.schedule({callback}) *vim.schedule()*
|
vim.schedule({callback}) *vim.schedule()*
|
||||||
Schedules {callback} to be invoked soon by the main event-loop. Useful
|
Schedules {callback} to be invoked soon by the main event-loop. Useful
|
||||||
to avoid |textlock| or other temporary restrictions.
|
to avoid |textlock| or other temporary restrictions.
|
||||||
|
@@ -474,6 +474,52 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_ICONV)
|
||||||
|
|
||||||
|
/// Convert string from one encoding to another
|
||||||
|
static int nlua_iconv(lua_State *lstate)
|
||||||
|
{
|
||||||
|
int narg = lua_gettop(lstate);
|
||||||
|
|
||||||
|
if (narg < 3) {
|
||||||
|
return luaL_error(lstate, "Expected at least 3 arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 3; i++) {
|
||||||
|
if (lua_type(lstate, i) != LUA_TSTRING) {
|
||||||
|
return luaL_argerror(lstate, i, "expected string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t str_len = 0;
|
||||||
|
const char *str = lua_tolstring(lstate, 1, &str_len);
|
||||||
|
|
||||||
|
char_u *from = enc_canonize(enc_skip((char_u *)lua_tolstring(lstate, 2, NULL)));
|
||||||
|
char_u *to = enc_canonize(enc_skip((char_u *)lua_tolstring(lstate, 3, NULL)));
|
||||||
|
|
||||||
|
vimconv_T vimconv;
|
||||||
|
vimconv.vc_type = CONV_NONE;
|
||||||
|
convert_setup_ext(&vimconv, from, false, to, false);
|
||||||
|
|
||||||
|
char_u *ret = string_convert(&vimconv, (char_u *)str, &str_len);
|
||||||
|
|
||||||
|
convert_setup(&vimconv, NULL, NULL);
|
||||||
|
|
||||||
|
xfree(from);
|
||||||
|
xfree(to);
|
||||||
|
|
||||||
|
if (ret == NULL) {
|
||||||
|
lua_pushnil(lstate);
|
||||||
|
} else {
|
||||||
|
lua_pushlstring(lstate, (char *)ret, str_len);
|
||||||
|
xfree(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
|
void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
|
||||||
{
|
{
|
||||||
if (!is_thread) {
|
if (!is_thread) {
|
||||||
@@ -519,6 +565,13 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
|
|||||||
// vim.spell
|
// vim.spell
|
||||||
luaopen_spell(lstate);
|
luaopen_spell(lstate);
|
||||||
lua_setfield(lstate, -2, "spell");
|
lua_setfield(lstate, -2, "spell");
|
||||||
|
|
||||||
|
#if defined(HAVE_ICONV)
|
||||||
|
// vim.iconv
|
||||||
|
// depends on p_ambw, p_emoji
|
||||||
|
lua_pushcfunction(lstate, &nlua_iconv);
|
||||||
|
lua_setfield(lstate, -2, "iconv");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim.mpack
|
// vim.mpack
|
||||||
|
@@ -2721,6 +2721,39 @@ describe('lua stdlib', function()
|
|||||||
]]
|
]]
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('vim.iconv', function()
|
||||||
|
it('can convert strings', function()
|
||||||
|
eq('hello', exec_lua[[
|
||||||
|
return vim.iconv('hello', 'latin1', 'utf-8')
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can validate arguments', function()
|
||||||
|
eq({false, 'Expected at least 3 arguments'}, exec_lua[[
|
||||||
|
return {pcall(vim.iconv, 'hello')}
|
||||||
|
]])
|
||||||
|
|
||||||
|
eq({false, 'bad argument #3 to \'?\' (expected string)'}, exec_lua[[
|
||||||
|
return {pcall(vim.iconv, 'hello', 'utf-8', true)}
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can handle bad encodings', function()
|
||||||
|
eq(NIL, exec_lua[[
|
||||||
|
return vim.iconv('hello', 'foo', 'bar')
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can handle strings with NUL bytes', function()
|
||||||
|
eq(7, exec_lua[[
|
||||||
|
local a = string.char(97, 98, 99, 0, 100, 101, 102) -- abc\0def
|
||||||
|
return string.len(vim.iconv(a, 'latin1', 'utf-8'))
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('lua: builtin modules', function()
|
describe('lua: builtin modules', function()
|
||||||
|
Reference in New Issue
Block a user