changeset 21060:89aba7895bb2 v8.2.1081

patch 8.2.1081: Lua: cannot use table.insert() and table.remove() Commit: https://github.com/vim/vim/commit/a1f9f8666ed3a462eb8a518e78418c57dc41bbd4 Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Sun, 28 Jun 2020 22:45:04 +0200
parents 90872dbd2bfe
children 6a1d744580b0
files runtime/doc/if_lua.txt src/if_lua.c src/testdir/test_lua.vim src/version.c
diffstat 4 files changed, 64 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- 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*
--- 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;
 }
--- 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')
--- 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,