# HG changeset patch # User Bram Moolenaar # Date 1593377104 -7200 # Node ID 89aba7895bb265642b58c4eec098d0fa89eaa09d # Parent 90872dbd2bfeceb3efdcb053a4db8135e4106afe patch 8.2.1081: Lua: cannot use table.insert() and table.remove() Commit: https://github.com/vim/vim/commit/a1f9f8666ed3a462eb8a518e78418c57dc41bbd4 Author: Bram Moolenaar Date: Sun Jun 28 22:41:26 2020 +0200 patch 8.2.1081: Lua: cannot use table.insert() and table.remove() Problem: Lua: cannot use table.insert() and table.remove(). Solution: Add the list functions. (Prabir Shrestha, closes https://github.com/vim/vim/issues/6353) diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -227,8 +227,17 @@ Properties in Vim. o "l[k]" returns the k-th item in "l"; "l" is one-indexed, as in Lua. To modify the k-th item, simply do "l[k] = newitem"; in - particular, "l[k] = nil" removes the k-th item from "l". + particular, "l[k] = nil" removes the k-th item from "l". Item can + be added to the end of the list by "l[#l + 1] = newitem" o "l()" returns an iterator for "l". + o "table.insert(l, newitem)" inserts an item at the end of the list. + (only Lua 5.3 and later) + o "table.insert(l, position, newitem)" inserts an item at the + specified position. "position" is one-indexed. (only Lua 5.3 and + later) + o "table.remove(l, position)" removes an item at the specified + position. "position" is one-indexed. + Methods ------- @@ -246,8 +255,11 @@ Examples: :lua l[1] = nil -- remove first item :lua l:insert(true, 1) :lua print(l, #l, l[1], l[2]) + :lua l[#l + 1] = 'value' + :lua table.insert(l, 100) + :lua table.insert(l, 2, 200) + :lua table.remove(l, 1) :lua for item in l() do print(item) end -< ============================================================================== 4. Dict userdata *lua-dict* diff --git a/src/if_lua.c b/src/if_lua.c --- a/src/if_lua.c +++ b/src/if_lua.c @@ -913,19 +913,32 @@ luaV_list_newindex(lua_State *L) if (l->lv_lock) luaL_error(L, "list is locked"); li = list_find(l, n); - if (li == NULL) return 0; - if (lua_isnil(L, 3)) // remove? + if (li == NULL) { - vimlist_remove(l, li, li); - listitem_free(l, li); + if (!lua_isnil(L, 3)) + { + typval_T v; + luaV_checktypval(L, 3, &v, "inserting list item"); + if (list_insert_tv(l, &v, li) == FAIL) + luaL_error(L, "failed to add item to list"); + clear_tv(&v); + } } else { - typval_T v; - luaV_checktypval(L, 3, &v, "setting list item"); - clear_tv(&li->li_tv); - copy_tv(&v, &li->li_tv); - clear_tv(&v); + if (lua_isnil(L, 3)) // remove? + { + vimlist_remove(l, li, li); + listitem_free(l, li); + } + else + { + typval_T v; + luaV_checktypval(L, 3, &v, "setting list item"); + clear_tv(&li->li_tv); + copy_tv(&v, &li->li_tv); + clear_tv(&v); + } } return 0; } diff --git a/src/testdir/test_lua.vim b/src/testdir/test_lua.vim --- a/src/testdir/test_lua.vim +++ b/src/testdir/test_lua.vim @@ -353,6 +353,32 @@ func Test_lua_list_table() call assert_fails('lua vim.list(true)', '[string "vim chunk"]:1: table expected, got boolean') endfunc +func Test_lua_list_table_insert_remove() + let luaver = split(split(luaeval('_VERSION'), ' ')[1], '\.') + let major = str2nr(luaver[0]) + let minor = str2nr(luaver[1]) + + if major < 5 || (major == 5 && minor < 3) + throw 'Skipped: Lua version < 5.3' + endif + + let l = [1, 2] + lua t = vim.eval('l') + lua table.insert(t, 10) + lua t[#t + 1] = 20 + lua table.insert(t, 2, 30) + call assert_equal(l, [1, 30, 2, 10, 20]) + lua table.remove(t, 2) + call assert_equal(l, [1, 2, 10, 20]) + lua t[3] = nil + call assert_equal(l, [1, 2, 20]) + lua removed_value = table.remove(t, 3) + call assert_equal(luaeval('removed_value'), 20) + lua t = nil + lua removed_value = nil + unlet l +endfunc + " Test l() i.e. iterator on list func Test_lua_list_iter() lua l = vim.list():add('foo'):add('bar') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1081, +/**/ 1080, /**/ 1079,