Repository: neovim
Issue: Lua stdlib feature parity against Vimscript
Labels: lua

Tracking issue to collect the current status of Lua stdlib against Vimscript.

As all functions listed here are accessible in Lua via `vim.fn.*`, the goal is **not** to achieve 100% parity, however the typval conversion may have perf concerns and/or functional issues for specific functions so a Lua equivalent may be desirable. Also some vimscript functions aren't particularly relevant in the Lua domain.

I've filled the table to the best of my current knowledge. I there are any mistakes/disagreements/omissions then please comment.

| Total                                 | 412 |
|---------------------------------------|-----|
| Equivalent exists :white_check_mark:  | 155 |
| Not required :heavy_minus_sign:       |  50 |
| Wanted :grey_exclamation:             |   5 |
| Uncategorised                         | 204 |

<details>
  <summary>Functions</summary>

<details>
  <summary>Math functions (29/29 :white_check_mark:)</summary>

| Vimscript function | Lua equivalent / Notes            | Equiv exists(:white_check_mark:)/wanted(:grey_exclamation:) /not required(:heavy_minus_sign:)     |
|--------------------|-----------------------------------|------------------------|
| `abs`              | `math.abs`                        | :white_check_mark:     |
| `acos`             | `math.acos`                       | :white_check_mark:     |
| `and`              | `bit.band`                        | :white_check_mark: *1  |
| `asin`             | `math.asin`                       | :white_check_mark:     |
| `atan2`            | `math.atan2`                      | :white_check_mark:     |
| `atan`             | `math.atan`                       | :white_check_mark:     |
| `ceil`             | `math.ceil`                       | :white_check_mark:     |
| `cos`              | `math.cos`                        | :white_check_mark:     |
| `cosh`             | `math.cosh`                       | :white_check_mark:     |
| `exp`              | `math.exp`                        | :white_check_mark:     |
| `float2nr`         | `math.floor(x+0.5)`               | :white_check_mark:     |
| `floor`            | `math.floor`                      | :white_check_mark:     |
| `fmod`             | `math.fmod`                       | :white_check_mark:     |
| `invert`           | `bit.bnot`                        | :white_check_mark: *1  |
| `log10`            | `math.log10`                      | :white_check_mark:     |
| `log`              | `math.log`                        | :white_check_mark:     |
| `max`              | `math.max`                        | :white_check_mark:     |
| `min`              | `math.min`                        | :white_check_mark:     |
| `or`               | `bit.bor`                         | :white_check_mark: *1  |
| `pow`              | `math.pow`                        | :white_check_mark:     |
| `rand`             | `math.random`, `vim.loop.random`  | :white_check_mark:     |
| `round`            | `math.floor(x+0.5)`               | :white_check_mark:     |
| `sin`              | `math.sin`                        | :white_check_mark:     |
| `sinh`             | `math.sinh`                       | :white_check_mark:     |
| `sqrt`             | `math.sqrt`                       | :white_check_mark:     |
| `srand`            | `math.randomseed`                 | :white_check_mark:     |
| `tan`              | `math.tan`                        | :white_check_mark:     |
| `tanh`             | `math.tanh`                       | :white_check_mark:     |
| `xor`              | `bit.bxor`                        | :white_check_mark: *1  |

*1: Not yet available with PUC Lua (#21222)

</details>

| Vimscript function        | Lua equivalent / Notes                             | Equiv exists(:white_check_mark:)/wanted(:grey_exclamation:) /not required(:heavy_minus_sign:)     |
|---------------------------|----------------------------------------------------|------------------------------|
| `add`                     | `table.insert`                                     | :white_check_mark:   |
| `api_info`                | `vim.api.nvim_get_api_info`                        | :white_check_mark:           |
| `append`                  | `vim.api.nvim_buf_set_lines`                       | :white_check_mark:           |
| `appendbufline`           | `vim.api.nvim_buf_set_lines`                       | :white_check_mark:           |
| `argc`                    |                                                    |                              |
| `argidx`                  |                                                    |                              |
| `arglistid`               |                                                    |                              |
| `argv`                    |                                                    |                              |
| `assert_beeps`            |                                                    | :heavy_minus_sign:           |
| `assert_equal`            |                                                    | :heavy_minus_sign:           |
| `assert_equalfile`        |                                                    | :heavy_minus_sign:           |
| `assert_exception`        |                                                    | :heavy_minus_sign:           |
| `assert_fails`            |                                                    | :heavy_minus_sign:           |
| `assert_false`            | `assert(not value)`                                | :heavy_minus_sign:           |
| `assert_inrange`          |                                                    | :heavy_minus_sign:           |
| `assert_match`            |                                                    | :heavy_minus_sign:           |
| `assert_nobeep`           |                                                    | :heavy_minus_sign:           |
| `assert_notequal`         |                                                    | :heavy_minus_sign:           |
| `assert_notmatch`         |                                                    | :heavy_minus_sign:           |
| `assert_report`           |                                                    | :heavy_minus_sign:           |
| `assert_true`             | `assert`                                           | :heavy_minus_sign:           |
| `browse`                  |  Does nothing in Neovim                                                  |   :heavy_minus_sign:        |
| `browsedir`               |  Does nothing in Neovim                                                  |  :heavy_minus_sign:     |
| `bufadd` (to create bufs) | `vim.api.nvim_create_buf`                          | :white_check_mark:           |
| `bufexists`               | `vim.api.nvim_buf_is_valid`                        | :white_check_mark:           |
| `buflisted`               |                                                    |                              |
| `bufload`                 |                                                    |                              |
| `bufloaded`               | `vim.api.nvim_buf_is_loaded`                       | :white_check_mark:           |
| `bufname`                 | `vim.api.nvim_buf_get_name`                        | :white_check_mark:           |
| `bufnr`                   |                                                    |                              |
| `bufnr()`                 | `vim.api.nvim_get_current_buf`                     | :white_check_mark:           |
| `bufwinid`                | Easy to implement (see below)                      | :heavy_minus_sign:           |
| `bufwinnr`                |                                                    |                              |
| `byte2line`               |                                                    |                              |
| `byteidx`                 |                                                    |                              |
| `byteidxcomp`             |                                                    |                              |
| `call`                    | NA (typval)                                        | :heavy_minus_sign:           |
| `chanclose`               |                                                    |                              |
| `changenr`                |                                                    |                              |
| `chansend`                | `vim.api.nvim_chan_send`                           | :white_check_mark:           |
| `char2nr`                 | `string.byte` *only works with ASCII               | :white_check_mark:           |
| `charcol`                 |                                                    |                              |
| `charidx`                 |                                                    |                              |
| `chdir`                   | `vim.api.nvim_set_current_dir`                     | :white_check_mark:           |
| `cindent`                 |                                                    | :heavy_minus_sign:           |
| `clearmatches`            |                                                    |                              |
| `col`                     |                                                    |                              |
| `complete_add`            |                                                    |                              |
| `complete_check`          |                                                    |                              |
| `complete_info`           |                                                    |                              |
| `complete`                |                                                    |                              |
| `confirm`                 | `vim.ui.select`                                    | :white_check_mark:           |
| `copy`                    | `{table.unpack(obj)}`                              | :white_check_mark:           |
| `count`                   |                                                    |                              |
| `ctxget(0)`               | `vim.api.nvim_get_context`                         | :white_check_mark:           |
| `ctxget`                  |                                                    |                              |
| `ctxpop`                  |                                                    |                              |
| `ctxpush`                 |                                                    |                              |
| `ctxset`                  |                                                    |                              |
| `ctxsize`                 |                                                    |                              |
| `cursor`                  | `vim.api.nvim_win_set_cursor`                      | :white_check_mark:           |
| `debugbreak`              |                                                    |                              |
| `deepcopy`                | `vim.deepcopy`                                     | :white_check_mark:           |
| `delete`                  |                                                    |                              |
| `deletebufline`           | `vim.api.nvim_buf_set_lines`                       | :white_check_mark:           |
| `dictwatcheradd`          | `__index` metamethod + autocmd                     | :heavy_minus_sign:           |
| `dictwatcherdel`          | `__index` metamethod + autocmd                     | :heavy_minus_sign:           |
| `did_filetype`            |                                                    |                              |
| `diff_filler`             |                                                    |                              |
| `diff_hlID`               |  Obscure                                           | :heavy_minus_sign:           |
| `digraph_get{,list}`      |                                                    |                              |
| `digraph_set{,list}`      |                                                    |                              |
| `empty`                   | `vim.tbl_isempty`                                  | :white_check_mark:           |
| `environ`                 | `vim.loop.uv.os_environ`                           | :white_check_mark:           |
| `escape`                  |                                                    |                              |
| `eval`                    | `loadstring`                                       | :white_check_mark:           |
| `eventhandler`            |                                                    | :heavy_minus_sign:?          |
| `executable`              |                                                    |                              |
| `execute`                 | `vim.api.nvim_exec,` `vim.cmd`                     | :white_check_mark:           |
| `exepath`                 |                                                    | :white_check_mark:           |
| `exists`                  |                                                    |                              |
| `expand`                  |                                                    |                              |
| `expandcmd`               |                                                    |                              |
| `extend`                  | `vim.list_extend,` `vim.tbl_extend`                | :white_check_mark:           |
| `feedkeys`                | `vim.api.nvim_feedkeys`                            | :white_check_mark:           |
| `filereadable`            | `vim.loop.fs_stat`                                 | :white_check_mark:           |
| `filewritable`            | `vim.loop.fs_stat`                                 | :white_check_mark:           |
| `filter`                  | `vim.tbl_filter`                                   | :white_check_mark:           |
| `finddir`                 |                                                    |                              |
| `findfile`                | `vim.fs.find`                                      | :white_check_mark:           |
| `flatten`                 | `vim.tbl_flatten`                                  |                              |
| `fnameescape`             |                                                    |                              |
| `fnamemodify`             |                                                    |                              |
| `foldclosed`              |                                                    |                              |
| `foldclosedend`           |                                                    |                              |
| `foldlevel`               |                                                    |                              |
| `foldtext`                |                                                    |                              |
| `foldtextresult`          |                                                    |                              |
| `foreground`              |                                                    |                              |
| `fullcommand`             |                                                    |                              |
| `funcref`                 | NA (typval)                                        | :heavy_minus_sign:           |
| `function`                | NA (typval)                                        | :heavy_minus_sign:           |
| `garbagecollect`          |                                                    | :heavy_minus_sign:           |
| `get`                     | lua `<table>.<key_or_idx> or <default>`            | :white_check_mark:           |
| `getbufinfo`              | `vim.api.nvim_list_bufs` + `vim.api.nvim_buf_*`    | :white_check_mark:           |
| `getbufline`              |                                                    |                              |
| `getbufvar`               | `vim.api.nvim_buf_get_var`, `vim.b[idx][name]`     | :white_check_mark:           |
| `getchangelist`           |                                                    |                              |
| `getchar`                 |                                                    |                              |
| `getcharmod`              |                                                    |                              |
| `getcharpos`              |                                                    |                              |
| `getcharsearch`           |                                                    |                              |
| `getcharstr`              |                                                    |                              |
| `getcmdline`              |                                                    |                              |
| `getcmdpos`               |                                                    |                              |
| `getcmdtype`              |                                                    |                              |
| `getcmdwintype`           |                                                    | :grey_exclamation: (#10735)  |
| `getcompletion`           |                                                    |                              |
| `getcurpos`               |                                                    |                              |
| `getcursorcharpos`        |                                                    |                              |
| `getcwd`                  | `vim.loop.cwd` *does not work for window/tab local | :white_check_mark:           |
| `getenv`                  | `vim.loop.os_getenv`, `os.getenv`                  | :white_check_mark:           |
| `getfontname`             |                                                    |                              |
| `getfperm`                | `vim.loop.fs_stat(...).mode`                       | :white_check_mark:           |
| `getfsize`                | `vim.loop.fs_stat(...).size`                       | :white_check_mark:           |
| `getftime`                | `vim.loop.fs_stat(...).mtime`                      | :white_check_mark:           |
| `getftype`                | `vim.loop.fs_stat(...).type`                       | :white_check_mark:           |
| `getjumplist`             |                                                    |                              |
| `getline`                 | `vim.api.nvim_buf_get_lines`                       | :white_check_mark:           |
| `getloclist`              |                                                    |                              |
| `getmarklist`             | `vim.api.nvim_get_mark`                            | :white_check_mark:           |
| `getmatches`              |                                                    |                              |
| `getmousepos`             |                                                    |                              |
| `getpid`                  | `vim.loop.os_getpid`                               | :white_check_mark:           |
| `getpos('.')`             | `vim.api.nvim_win_get_cursor`                      |                              |
| `getpos`                  |                                                    |                              |
| `getqflist`               |                                                    |                              |
| `getreg`                  |                                                    |                              |
| `getreginfo`              |                                                    |                              |
| `getregtype`              |                                                    |                              |
| `gettabinfo`              |                                                    |                              |
| `gettabvar`               | `vim.api.nvim_tab_get_var`, `vim.t[idx][name]`     | :white_check_mark:           |
| `gettabwinvar`            | `vim.api.nvim_win_get_var`, `vim.w[idx][name]`     | :white_check_mark:           |
| `gettagstack`             |                                                    |                              |
| `getwininfo`              | Partially with #15248                              | :grey_exclamation:           |
| `getwinpos`               |                                                    |                              |
| `getwinposx`              |                                                    |                              |
| `getwinposy`              |                                                    |                              |
| `getwinvar`               | `vim.api.nvim_win_get_var`, `vim.w[idx][name]`     | :white_check_mark:           |
| `glob2regpat`             |                                                    |                              |
| `glob`                    |                                                    |                              |
| `globpath`                |                                                    |                              |
| `has_key`                 | `<table>[key] ~= nil`                              | :white_check_mark:           |
| `has`                     |                                                    |                              |
| `haslocaldir`             |                                                    |                              |
| `hasmapto`                |                                                    |                              |
| `histadd`                 |                                                    |                              |
| `histdel`                 |                                                    |                              |
| `histget`                 |                                                    |                              |
| `histnr`                  |                                                    |                              |
| `hlID`                    | `vim.api.nvim_get_hl_id_by_name`                   | :white_check_mark:           |
| `hlexists`                | `vim.api.nvim_get_hl_*`                            | :white_check_mark:           |
| `hostname`                | `vim.loop.os_gethostname()`                        | :white_check_mark:           |
| `iconv`                   | `vim.iconv`                                        | :white_check_mark:           |
| `id`                      | NA (typval)                                        | :heavy_minus_sign:           |
| `indent`                  |                                                    |                              |
| `index`                   |                                                    |                              |
| `input`                   | `vim.ui.input`                                     | :white_check_mark:           |
| `inputlist`               | `vim.ui.select`                                    | :white_check_mark:           |
| `inputrestore`            |                                                    |                              |
| `inputsave`               |                                                    |                              |
| `inputsecret`             |                                                    |                              |
| `insert`                  |                                                    |                              |
| `interrupt`               | No args or return so no typval conversion          | :heavy_minus_sign:           |
| `isdirectory`             | `vim.loop.fs_stat(...).type == 'directory'`        | :white_check_mark:           |
| `isinf`                   | Easy to implement, see below                       | :heavy_minus_sign:           |
| `islocked`                |                                                    | :heavy_minus_sign:           |
| `isnan`                   | Easy to implement, see below                       | :heavy_minus_sign:           |
| `items`                   | `pairs`                                            | :white_check_mark:           |
| `jobpid`                  | `vim.loop.process_get_pid`                         | :white_check_mark:           |
| `jobresize`               |                                                    |                              |
| `jobstart`                | `vim.loop.spawn`                                   | :white_check_mark:           |
| `jobstop`                 | `vim.loop.shutdown` and `vim.loop.close`           | :white_check_mark:           |
| `jobwait`                 |                                                    |                              |
| `join`                    | `table.concat`                                     | :white_check_mark:           |
| `json_decode`             | `vim.json.decode`                                  | :white_check_mark:           |
| `json_encode`             | `vim.json.encode`                                  | :white_check_mark:           |
| `keys`                    | `vim.tbl_keys`                                     | :white_check_mark:           |
| `len`                     | Lua `#` operator, `#vim.tbl_keys()`                | :white_check_mark:           |
| `libcall`, `libcallnr`    | package.loadlib, ffi.load                          | :white_check_mark:           |
| `line2byte`               |                                                    |                              |
| `line`                    |                                                    |                              |
| `lispindent`              |                                                    |                              |
| `list2str`                | `vim.inspect,` table.concat                        | :white_check_mark:           |
| `localtime`               | `vim.loop.gettimeofday`                            | :white_check_mark:           |
| `luaeval`                 | loadstring                                         | :white_check_mark:           |
| `map`                     | `vim.tbl_map`                                      | :white_check_mark:           |
| `maparg`                  |                                                    |                              |
| `mapcheck`                |                                                    |                              |
| `match`                   | `vim.regex` with `regex:match_str`                 | :white_check_mark:           |
| `matchadd`                |                                                    |                              |
| `matchaddpos`             | Extmarks                                           | :white_check_mark:           |
| `matcharg`                |                                                    |                              |
| `matchdelete`             |                                                    |                              |
| `matchend`                |                                                    |                              |
| `matchfuzzy`              |                                                    |                              |
| `matchfuzzypos`           |                                                    |                              |
| `matchlist`               |                                                    |                              |
| `matchstr`                |                                                    |                              |
| `matchstrpos`             |                                                    |                              |
| `menu_get`                |                                                    |                              |
| `mkdir`                   | `vim.loop.fs_mkdir`                                | :white_check_mark:           |
| `mode`                    | `vim.api.nvim_get_mode`                            | :white_check_mark:           |
| `msgpackdump`             | `vim.mpack.encode`                                 | :white_check_mark:           |
| `msgpackparse`            | `vim.mpack.decode`                                 | :white_check_mark:           |
| `nextnonblank`            |                                                    |                              |
| `nr2char`                 | `string.char` *only works with ASCII               | :white_check_mark:           |
| `pathshorten`             |                                                    |                              |
| `perleval`                |                                                    |                              |
| `prevnonblank`            |                                                    |                              |
| `printf`                  | `print(string.format(...))`                        | :white_check_mark:           |
| `prompt_getprompt`        |                                                    |                              |
| `prompt_setcallback`      |                                                    |                              |
| `prompt_setinterrupt`     |                                                    |                              |
| `prompt_setprompt`        |                                                    |                              |
| `pum_getpos`              |                                                    |                              |
| `pumvisible`              |                                                    |                              |
| `py3eval`                 |                                                    |                              |
| `pyeval`                  |                                                    |                              |
| `pyxeval`                 |                                                    |                              |
| `range`                   | Various ways depending on context                  | :white_check_mark:           |
| `readdir`                 |                                                    |                              |
| `readfile`                | `vim.loop.fs_read`                                 | :white_check_mark:           |
| `reduce`                  |                                                    |                              |
| `reg_executing`           |                                                    |                              |
| `reg_recorded`            |                                                    |                              |
| `reg_recording`           |                                                    |                              |
| `reltime[,float,str]`     | `vim.loop.hrtime,` `vim.loop.gettimeofday`         | :white_check_mark:           |
| `remove`                  | `os.remove`                                        | :white_check_mark:           |
| `rename`                  | `vim.loop.fs_rename`, `os.rename`                  | :white_check_mark:           |
| `repeat`                  | `string.rep`                                       | :white_check_mark:           |
| `resolve`                 | `vim.loop.fs_readlink`                             | :white_check_mark:           |
| `reverse`                 | Easy to implement, see below                       | :heavy_minus_sign:           |
| `rpcnotify`               | `vim.rpcnotify`                                    | :white_check_mark:           |
| `rpcrequest`              | `vim.rpcrequest`                                   | :white_check_mark:           |
| `rpcstart`                |                                                    |                              |
| `rubyeval`                |                                                    |                              |
| `screenattr`              |                                                    |                              |
| `screenchar`              |                                                    |                              |
| `screenchars`             |                                                    |                              |
| `screencol`               |                                                    |                              |
| `screenpos`               |                                                    |                              |
| `screenrow`               |                                                    |                              |
| `screenstring`            |                                                    |                              |
| `search`                  |                                                    |                              |
| `searchcount`             |                                                    |                              |
| `searchdecl`              |                                                    |                              |
| `searchpair`              |                                                    |                              |
| `searchpairpos`           |                                                    |                              |
| `searchpos`               |                                                    |                              |
| `serverlist`              | Covered by vim.loop.*?                             | :heavy_minus_sign:           |
| `serverstart`             | Covered by vim.loop.*?                             | :heavy_minus_sign:           |
| `serverstop`              | Covered by vim.loop.*?                             | :heavy_minus_sign:           |
| `setbufline`              | `vim.api.nvim_buf_set_lines`                       | :white_check_mark:           |
| `setbufvar`               | `vim.api.nvim_buf_set_var,` `vim.b[idx][name]`     | :white_check_mark:           |
| `setcharpos`              |                                                    |                              |
| `setcharsearch`           |                                                    |                              |
| `setcmdpos`               |                                                    |                              |
| `setcursorcharpos`        |                                                    |                              |
| `setenv`                  | `vim.loop.os_setenv`                               | :white_check_mark:           |
| `setfperm`                | `vim.loop.fs_chmod`                                | :white_check_mark:           |
| `setline`                 | `vim.api.nvim_buf_set_lines`                       | :white_check_mark:           |
| `setloclist`              |                                                    |                              |
| `setmatches`              |                                                    |                              |
| `setpos`                  |                                                    |                              |
| `setqflist`               |                                                    |                              |
| `setreg`                  |                                                    |                              |
| `settabvar`               | `vim.api.nvim_tabpage_set_var,` `vim.t[idx][name]` | :white_check_mark:           |
| `settabwinvar`            |                                                    |                              |
| `settagstack`             |                                                    |                              |
| `setwinvar`               | `vim.api.nvim_win_set_var,` `vim.w[idx][name]`     | :white_check_mark:           |
| `sha256`                  | Typval conversion is costly                        | :grey_exclamation:           |
| `shellescape`             |                                                    |                              |
| `shiftwidth`              |                                                    |                              |
| `sign_define`             | extmarks                                           | :heavy_minus_sign:           |
| `sign_getdefined`         | extmarks                                           | :heavy_minus_sign:           |
| `sign_getplaced`          | extmarks                                           | :heavy_minus_sign:           |
| `sign_jump`               | extmarks                                           | :heavy_minus_sign:           |
| `sign_place`              | extmarks                                           | :heavy_minus_sign:           |
| `sign_placelist`          | extmarks                                           | :heavy_minus_sign:           |
| `sign_undefine`           | extmarks                                           | :heavy_minus_sign:           |
| `sign_unplace`            | extmarks                                           | :heavy_minus_sign:           |
| `sign_unplacelist`        | extmarks                                           | :heavy_minus_sign:           |
| `simplify`                |                                                    |                              |
| `sockconnect`             | Should be covered in `vim.loop.*`                  | :heavy_minus_sign:           |
| `sort`                    | `table.sort`                                       | :white_check_mark:           |
| `soundfold`               |                                                    |                              |
| `spellbadword`            | `vim.spell.check`                                  | :white_check_mark:           |
| `spellsuggest`            |                                                    |                              |
| `split`                   | `vim.split`                                        | :white_check_mark:           |
| `stdioopen`               |                                                    |                              |
| `stdpath`                 |                                                    |                              |
| `str2float`               | `tonumber`                                         | :white_check_mark:           |
| `str2list`                | `vim.inspect`, `table.concat`                      | :white_check_mark:           |
| `str2nr`                  | `tonumber`                                         | :white_check_mark:           |
| `strcharpart`             | `string.sub`                                       | :white_check_mark:           |
| `strchars`                | `string.len`                                       | :white_check_mark:           |
| `strdisplaywidth`         |                                                    |                              |
| `strftime`                | `date.format`                                      | :white_check_mark:           |
| `strgetchar`              | `string.sub`                                       | :white_check_mark:           |
| `stridx`                  |                                                    |                              |
| `string`                  | `tostring`                                         | :white_check_mark:           |
| `strlen`                  | string.len or Lua # operator                       | :white_check_mark:           |
| `strpart`                 |                                                    |                              |
| `strptime`                |                                                    |                              |
| `strridx`                 | `string.find`                                      | :white_check_mark:           |
| `strtrans`                |                                                    |                              |
| `strwidth`                | `vim.api.nvim_strwidth`                            | :white_check_mark:           |
| `submatch`                |                                                    |                              |
| `substitute`              | `vim.gsub` (Lua patterns instead of regex)         | :white_check_mark:           |
| `swapinfo`                |                                                    |                              |
| `swapname`                |                                                    |                              |
| `synID`                   |                                                    |                              |
| `synIDattr`               |                                                    |                              |
| `synIDtrans`              |                                                    |                              |
| `synconcealed`            |                                                    |                              |
| `synstack`                |                                                    |                              |
| `system`                  | `vim.loop.spawn`                                   | :white_check_mark:           |
| `systemlist`              | `vim.loop.spawn`                                   | :white_check_mark:           |
| `tabpagebuflist`          |                                                    |                              |
| `tabpagenr`               | `vim.api.nvim_get_current_tabpage`                 | :white_check_mark:           |
| `tabpagewinnr`            |                                                    |                              |
| `tagfiles`                |                                                    |                              |
| `taglist`                 |                                                    |                              |
| `tempname`                | `vim.loop.fs_mktemp`, `os.tmpname`                 | :white_check_mark:           |
| `termopen`                |                                                    |                              |
| `test_garbagecollect_now` |                                                    | :heavy_minus_sign:           |
| `test_write_list_log`     |                                                    | :heavy_minus_sign:           |
| `timer_info`              | `vim.loop.timer_{get_repeat,get_due_in}`           | :white_check_mark:           |
| `timer_pause`             |                                                    |                              |
| `timer_start`             | `vim.loop.timer_start`                             | :white_check_mark:           |
| `timer_stop`              | `vim.loop.timer_stop`                              | :white_check_mark:           |
| `timer_stopall`           | No args or return so no typval conversion          | :heavy_minus_sign:           |
| `tolower`                 | `string.lower`                                     | :white_check_mark:           |
| `toupper`                 | `string.upper`                                     | :white_check_mark:           |
| `tr`                      |                                                    |                              |
| `trim`                    | `vim.trim`                                         | :white_check_mark:           |
| `trunc`                   |                                                    |                              |
| `type`                    | NA (typval)                                        | :heavy_minus_sign:           |
| `undofile`                |                                                    |                              |
| `undotree`                |                                                    |                              |
| `uniq`                    |                                                    | :grey_exclamation:           |
| `values`                  | `vim.tbl_values`                                   | :white_check_mark:           |
| `virtcol`                 |                                                    |                              |
| `visualmode`              |                                                    |                              |
| `wait`                    | `vim.wait`                                         | :white_check_mark:           |
| `wildmenumode`            |                                                    |                              |
| `win_execute`             | `vim.api.nvim_win_call`                            | :white_check_mark:           |
| `win_findbuf`             |                                                    |                              |
| `win_getid`               |                                                    |                              |
| `win_getid()`             | `vim.api.nvim_get_current_win`                     | :white_check_mark:           |
| `win_gettype`             |                                                    |                              |
| `win_gotoid`              | `vim.api.nvim_set_current_win`                     | :white_check_mark:           |
| `win_id2tabwin`           |                                                    |                              |
| `win_id2win`              |                                                    |                              |
| `win_move_separator`      | `vim.api.nvim_win_set_width`                       | :heavy_minus_sign:           |
| `win_move_statusline`     |                                                    |                              |
| `win_screenpos`           | `vim.api.nvim_win_get_position`                    | :white_check_mark:           |
| `win_splitmove`           |                                                    |                              |
| `winbufnr`                | `vim.api.nvim_win_get_buf`                         | :white_check_mark:           |
| `wincol`                  |                                                    |                              |
| `windowsversion`          |                                                    |                              |
| `winheight`               | `vim.api.nvim_win_get_height`                      | :white_check_mark:           |
| `winlayout`               |                                                    |                              |
| `winline`                 |                                                    |                              |
| `winnr('$') ('#')` ...    |                                                    |                              |
| `winnr()`                 | `vim.api.nvim_win_get_number`                      | :white_check_mark:           |
| `winrestcmd`              |                                                    |                              |
| `winrestview`             |                                                    |                              |
| `winsaveview`             |                                                    |                              |
| `winwidth`                | `vim.api.nvim_win_get_width`                       | :white_check_mark:           |
| `wordcount`               | Typval conv is negligible                          | :heavy_minus_sign:           |
| `writefile`               | `vim.loop.fs_write`                                | :white_check_mark:           |


</details>


<details>
<summary>Commands</summary>

| Vimscript command           | Lua equivalent / Notes             | Equiv exists(:white_check_mark:)/wanted(:grey_exclamation:) /not required(:heavy_minus_sign:) |
|-----------------------------|------------------------------------|--------------------|
| `abbrev` (and variants)     |                                    | :grey_exclamation: |
| `augroup`                   | `vim.api.nvim_create_augroup`      | :white_check_mark: |
| `autocmd`                   | `vim.api.nvim_create_autocmd`      | :white_check_mark: |
| `colorscheme`                   |      |  |
| `highlight`                 | `vim.api.nvim_set_hl`              | :white_check_mark: |
| `set` (and variants)        | `vim.api.nvim_set_option_value`    | :white_check_mark: |
| `sign`                      | Extmarks API                       | :heavy_minus_sign: |
| `map`                       | `vim.keymap`                       | :white_check_mark: |
| `command`                   | `vim.api.nvim_create_user_command` | :white_check_mark: |

</details>

<details>
<summary>Lua equivalent snippets</summary>

### `bufwinid()`

**_NOTE:_** This works for all tabpages, unlike `vim.fn.bufwinid()` which only works for the current tabpage.

<details>
<summary>Expand</summary>

```lua
local function bufwinid(buf)
  for _, w in ipairs(vim.api.nvim_list_wins()) do
    if vim.api.nvim_win_get_buf(w) == buf then
      return w
    end
  end
  return -1
end
```
</details>

### `reverse()`
<details>
  <summary>Expand</summary>

```lua
function reverse(t)
  local n = #t
  local i = 1
  for i = 1, n do
    t[i],t[n] = t[n],t[i]

    n = n - 1
  end
end
```
</details>

### `isinf()`
<details>
<summary>Expand</summary>

```lua
local function isinf(value)
  return value == math.huge and 1 or value == -math.huge and -1 or 0
end
```
</details>

### `isnan()`
<details>
<summary>Expand</summary>

```lua
local function isnan(value)
  return value ~= value
end
```
</details>

</details>


### Other Notes:
- Does typconv conversion carry a heavy cost compared to the rest of the function execution? It may if the function can input large objects for it arguments or return values, or if the function is expected to be run in hot loops.
- Vimscript doesn't have proper booleans, so any vimscript function which should return boolean woud probably benefit from a Lua equivalent.