├── .gitattributes ├── README.md ├── README.pt-br.md ├── doc └── nvim-lua-guide.txt └── scripts ├── docgen.sh ├── sections_tags.awk └── to_vimdoc.sed /.gitattributes: -------------------------------------------------------------------------------- 1 | scripts/* -linguist-detectable 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :arrow_upper_left: (Feeling lost? Use the GitHub TOC!) 2 | 3 | **:warning: :warning: :warning: A more up-to-date version of this guide is available in the Neovim documentation, see [`:help lua-guide`](https://neovim.io/doc/user/lua-guide.html#lua-guide) :warning: :warning: :warning:** 4 | 5 | --- 6 | 7 | # Getting started using Lua in Neovim 8 | 9 | ## Translations 10 | 11 | - [Chinese version](https://github.com/glepnir/nvim-lua-guide-zh) 12 | - [Spanish version](https://github.com/RicardoRien/nvim-lua-guide/blob/master/README.esp.md) 13 | - [Portuguese version](https://github.com/npxbr/nvim-lua-guide/blob/master/README.pt-br.md) 14 | - [Japanese version](https://github.com/willelz/nvim-lua-guide-ja/blob/master/README.ja.md) 15 | - [Russian version](https://github.com/kuator/nvim-lua-guide-ru) 16 | - [Ukrainian version](https://github.com/famiclone/nvim-lua-guide-ua) 17 | - [Korean version](https://github.com/krapjost/nvim-lua-guide-kr) 18 | 19 | ## Introduction 20 | 21 | The [integration of Lua](https://www.youtube.com/watch?v=IP3J56sKtn0) as a [first-class language inside Neovim](https://github.com/neovim/neovim/wiki/FAQ#why-embed-lua-instead-of-x) is shaping up to be one of its killer features. 22 | However, the amount of teaching material for learning how to write plugins in Lua is not as large as what you would find for writing them in Vimscript. This is an attempt at providing some basic information to get people started. 23 | 24 | This guide assumes you are using at least version 0.5 of Neovim. 25 | 26 | ### Learning Lua 27 | 28 | If you are not already familiar with the language, there are plenty of resources to get started: 29 | 30 | - The [Learn X in Y minutes page about Lua](https://learnxinyminutes.com/docs/lua/) should give you a quick overview of the basics 31 | - [This guide](https://github.com/medwatt/Notes/blob/main/Lua/Lua_Quick_Guide.ipynb) is also a good resource for getting started quickly 32 | - If videos are more to your liking, Derek Banas has a [1-hour tutorial on the language](https://www.youtube.com/watch?v=iMacxZQMPXs) 33 | - Want something a little more interactive with runnable examples? Try [the LuaScript tutorial](https://www.luascript.dev/learn) 34 | - The [lua-users wiki](http://lua-users.org/wiki/LuaDirectory) is full of useful information on all kinds of Lua-related topics 35 | - The [official reference manual for Lua](https://www.lua.org/manual/5.1/) should give you the most comprehensive tour of the language (exists as a Vimdoc plugin if you want to read it from the comfort of your editor: [milisims/nvim-luaref](https://github.com/milisims/nvim-luaref)) 36 | 37 | It should also be noted that Lua is a very clean and simple language. It is easy to learn, especially if you have experience with similar scripting languages like JavaScript. You may already know more Lua than you realise! 38 | 39 | Note: the version of Lua that Neovim embeds is [LuaJIT](https://staff.fnwi.uva.nl/h.vandermeer/docs/lua/luajit/luajit_intro.html) 2.1.0, which maintains compatibility with Lua 5.1. 40 | 41 | ### Existing tutorials for writing Lua in Neovim 42 | 43 | A few tutorials have already been written to help people write plugins in Lua. Some of them helped quite a bit when writing this guide. Many thanks to their authors. 44 | 45 | - [teukka.tech - From init.vim to init.lua](https://teukka.tech/luanvim.html) 46 | - [dev.to - How to write neovim plugins in Lua](https://dev.to/2nit/how-to-write-neovim-plugins-in-lua-5cca) 47 | - [dev.to - How to make UI for neovim plugins in Lua](https://dev.to/2nit/how-to-make-ui-for-neovim-plugins-in-lua-3b6e) 48 | - [ms-jpq - Neovim Async Tutorial](https://github.com/ms-jpq/neovim-async-tutorial) 49 | - [oroques.dev - Neovim 0.5 features and the switch to init.lua](https://oroques.dev/notes/neovim-init/) 50 | - [Building A Vim Statusline from Scratch - jdhao's blog](https://jdhao.github.io/2019/11/03/vim_custom_statusline/) 51 | - [Configuring Neovim using Lua](https://icyphox.sh/blog/nvim-lua/) 52 | - [Devlog | Everything you need to know to configure neovim using lua](https://vonheikemen.github.io/devlog/tools/configuring-neovim-using-lua/) 53 | 54 | ### Companion plugins 55 | 56 | - [Vimpeccable](https://github.com/svermeulen/vimpeccable) - Plugin to help write your .vimrc in Lua 57 | - [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - All the lua functions I don't want to write twice 58 | - [popup.nvim](https://github.com/nvim-lua/popup.nvim) - An implementation of the Popup API from vim in Neovim 59 | - [nvim_utils](https://github.com/norcalli/nvim_utils) 60 | - [nvim-luadev](https://github.com/bfredl/nvim-luadev) - REPL/debug console for nvim lua plugins 61 | - [nvim-luapad](https://github.com/rafcamlet/nvim-luapad) - Interactive real time neovim scratchpad for embedded lua engine 62 | - [nlua.nvim](https://github.com/tjdevries/nlua.nvim) - Lua Development for Neovim 63 | - [BetterLua.vim](https://github.com/euclidianAce/BetterLua.vim) - Better Lua syntax highlighting in Vim/NeoVim 64 | 65 | ## Where to put Lua files 66 | 67 | ### init.lua 68 | 69 | Neovim supports loading an `init.lua` file for configuration instead of the usual `init.vim`. 70 | 71 | Note: `init.lua` is of course _completely_ optional. Support for `init.vim` is not going away and is still a valid option for configuration. Do keep in mind that some features are not 100% exposed to Lua yet. 72 | 73 | See also: 74 | 75 | - [`:help config`](https://neovim.io/doc/user/starting.html#config) 76 | 77 | ### Modules 78 | 79 | Lua modules are found inside a `lua/` folder in your `'runtimepath'` (for most users, this will mean `~/.config/nvim/lua` on \*nix systems and `~/AppData/Local/nvim/lua` on Windows). You can `require()` files in this folder as Lua modules. 80 | 81 | Let's take the following folder structure as an example: 82 | 83 | ```text 84 | 📂 ~/.config/nvim 85 | ├── 📁 after 86 | ├── 📁 ftplugin 87 | ├── 📂 lua 88 | │ ├── 🌑 myluamodule.lua 89 | │ └── 📂 other_modules 90 | │ ├── 🌑 anothermodule.lua 91 | │ └── 🌑 init.lua 92 | ├── 📁 pack 93 | ├── 📁 plugin 94 | ├── 📁 syntax 95 | └── 🇻 init.vim 96 | ``` 97 | 98 | The following Lua code will load `myluamodule.lua`: 99 | 100 | ```lua 101 | require('myluamodule') 102 | ``` 103 | 104 | Notice the absence of a `.lua` extension. 105 | 106 | Similarly, loading `other_modules/anothermodule.lua` is done like so: 107 | 108 | ```lua 109 | require('other_modules.anothermodule') 110 | -- or 111 | require('other_modules/anothermodule') 112 | ``` 113 | 114 | Path separators are denoted by either a dot `.` or a slash `/`. 115 | 116 | A folder containing an `init.lua` file can be required directly, without having to specify the name of the file. 117 | 118 | ```lua 119 | require('other_modules') -- loads other_modules/init.lua 120 | ``` 121 | 122 | Requiring a nonexistent module or a module which contains syntax errors aborts the currently executing script. 123 | `pcall()` may be used to prevent errors. 124 | 125 | ```lua 126 | local ok, _ = pcall(require, 'module_with_error') 127 | if not ok then 128 | -- not loaded 129 | end 130 | ``` 131 | 132 | See also: 133 | 134 | - [`:help lua-require`](https://neovim.io/doc/user/lua.html#lua-require) 135 | 136 | #### Tips 137 | 138 | Several Lua plugins might have identical filenames in their `lua/` folder. This could lead to namespace clashes. 139 | 140 | If two different plugins have a `lua/main.lua` file, then doing `require('main')` is ambiguous: which file do we want to source? 141 | 142 | It might be a good idea to namespace your config or your plugin with a top-level folder, like so: `lua/plugin_name/main.lua` 143 | 144 | ### Runtime files 145 | 146 | Much like Vimscript files, Lua files can be loaded automatically from special folders in your `runtimepath`. Currently, the following folders are supported: 147 | 148 | - `colors/` 149 | - `compiler/` 150 | - `ftplugin/` 151 | - `ftdetect/` 152 | - `indent/` 153 | - `plugin/` 154 | - `syntax/` 155 | 156 | Note: in a runtime directory, all `*.vim` files are sourced before `*.lua` files. 157 | 158 | See also: 159 | 160 | - [`:help 'runtimepath'`](https://neovim.io/doc/user/options.html#'runtimepath') 161 | - [`:help load-plugins`](https://neovim.io/doc/user/starting.html#load-plugins) 162 | 163 | #### Tips 164 | 165 | Since runtime files aren't based on the Lua module system, two plugins can have a `plugin/main.lua` file without it being an issue. 166 | 167 | ## Using Lua from Vimscript 168 | 169 | ### :lua 170 | 171 | This command executes a chunk of Lua code. 172 | 173 | ```vim 174 | :lua require('myluamodule') 175 | ``` 176 | 177 | Multi-line scripts are possible using heredoc syntax: 178 | 179 | ```vim 180 | echo "Here's a bigger chunk of Lua code" 181 | 182 | lua << EOF 183 | local mod = require('mymodule') 184 | local tbl = {1, 2, 3} 185 | 186 | for k, v in ipairs(tbl) do 187 | mod.method(v) 188 | end 189 | 190 | print(tbl) 191 | EOF 192 | ``` 193 | 194 | Note: each `:lua` command has its own scope and variables declared with the `local` keyword are not accessible outside of the command. This won't work: 195 | 196 | ```vim 197 | :lua local foo = 1 198 | :lua print(foo) 199 | " prints 'nil' instead of '1' 200 | ``` 201 | 202 | Note 2: the `print()` function in Lua behaves similarly to the `:echomsg` command. Its output is saved in the message-history and can be suppressed by the `:silent` command. 203 | 204 | See also: 205 | 206 | - [`:help :lua`](https://neovim.io/doc/user/lua.html#Lua) 207 | - [`:help :lua-heredoc`](https://neovim.io/doc/user/lua.html#:lua-heredoc) 208 | 209 | ### :luado 210 | 211 | This command executes a chunk of Lua code that acts on a range of lines in the current buffer. If no range is specified, the whole buffer is used instead. Whatever string is `return`ed from the chunk is used to determine what each line should be replaced with. 212 | 213 | The following command would replace every line in the current buffer with the text `hello world`: 214 | 215 | ```vim 216 | :luado return 'hello world' 217 | ``` 218 | 219 | Two implicit `line` and `linenr` variables are also provided. `line` is the text of the line being iterated upon whereas `linenr` is its number. The following command would make every line whose number is divisible by 2 uppercase: 220 | 221 | ```vim 222 | :luado if linenr % 2 == 0 then return line:upper() end 223 | ``` 224 | 225 | See also: 226 | 227 | - [`:help :luado`](https://neovim.io/doc/user/lua.html#:luado) 228 | 229 | ### Sourcing Lua files 230 | 231 | Neovim provides 3 Ex commands to source Lua files 232 | 233 | - `:luafile` 234 | - `:source` 235 | - `:runtime` 236 | 237 | `:luafile` and `:source` are very similar: 238 | 239 | ```vim 240 | :luafile ~/foo/bar/baz/myluafile.lua 241 | :luafile % 242 | :source ~/foo/bar/baz/myluafile.lua 243 | :source % 244 | ``` 245 | 246 | `:source` also supports ranges, which can be useful to only execute part of a script: 247 | 248 | ```vim 249 | :1,10source 250 | ``` 251 | 252 | `:runtime` is a little different: it uses the `'runtimepath'` option to determine which files to source. See [`:help :runtime`](https://neovim.io/doc/user/repeat.html#:runtime) for more details. 253 | 254 | See also: 255 | 256 | - [`:help :luafile`](https://neovim.io/doc/user/lua.html#:luafile) 257 | - [`:help :source`](https://neovim.io/doc/user/repeat.html#:source) 258 | - [`:help :runtime`](https://neovim.io/doc/user/repeat.html#:runtime) 259 | 260 | #### Sourcing a lua file vs calling require(): 261 | 262 | You might be wondering what the difference between calling the `require()` function and sourcing a Lua file is and whether you should prefer one way over the other. They have different use cases: 263 | 264 | - `require()`: 265 | - is a built-in Lua function. It allows you to take advantage of Lua's module system 266 | - searches for modules in `lua/` folders in your `'runtimepath'` 267 | - keeps track of what modules have been loaded and prevents a script from being parsed and executed a second time. If you change the file containing the code for a module and try to `require()` it a second time while Neovim is running, the module will not actually update 268 | - `:luafile`, `:source` and `:runtime`: 269 | - are Ex commands. They do not support modules 270 | - execute the contents of a script regardless of whether it has been executed before 271 | - `:luafile` and `:source` take a path that is either absolute or relative to the working directory of the current window 272 | - `:runtime` uses the `'runtimepath'` option to find files 273 | 274 | Files sourced via `:source`, `:runtime` or automatically from runtime directories will also show up in `:scriptnames` and `--startuptime` 275 | 276 | ### luaeval() 277 | 278 | This built-in Vimscript function evaluates a Lua expression string and returns its value. Lua data types are automatically converted to Vimscript types (and vice versa). 279 | 280 | ```vim 281 | " You can store the result in a variable 282 | let variable = luaeval('1 + 1') 283 | echo variable 284 | " 2 285 | let concat = luaeval('"Lua".." is ".."awesome"') 286 | echo concat 287 | " 'Lua is awesome' 288 | 289 | " List-like tables are converted to Vim lists 290 | let list = luaeval('{1, 2, 3, 4}') 291 | echo list[0] 292 | " 1 293 | echo list[1] 294 | " 2 295 | " Note that unlike Lua tables, Vim lists are 0-indexed 296 | 297 | " Dict-like tables are converted to Vim dictionaries 298 | let dict = luaeval('{foo = "bar", baz = "qux"}') 299 | echo dict.foo 300 | " 'bar' 301 | 302 | " Same thing for booleans and nil 303 | echo luaeval('true') 304 | " v:true 305 | echo luaeval('nil') 306 | " v:null 307 | 308 | " You can create Vimscript aliases for Lua functions 309 | let LuaMathPow = luaeval('math.pow') 310 | echo LuaMathPow(2, 2) 311 | " 4 312 | let LuaModuleFunction = luaeval('require("mymodule").myfunction') 313 | call LuaModuleFunction() 314 | 315 | " It is also possible to pass Lua functions as values to Vim functions 316 | lua X = function(k, v) return string.format("%s:%s", k, v) end 317 | echo map([1, 2, 3], luaeval("X")) 318 | ``` 319 | 320 | `luaeval()` takes an optional second argument that allows you to pass data to the expression. You can then access that data from Lua using the magic global `_A`: 321 | 322 | ```vim 323 | echo luaeval('_A[1] + _A[2]', [1, 1]) 324 | " 2 325 | 326 | echo luaeval('string.format("Lua is %s", _A)', 'awesome') 327 | " 'Lua is awesome' 328 | ``` 329 | 330 | See also: 331 | 332 | - [`:help luaeval()`]() 333 | 334 | ### v:lua 335 | 336 | This global Vim variable allows you to call Lua functions in the global namespace ([`_G`](https://www.lua.org/manual/5.1/manual.html#pdf-_G)) directly from Vimscript. Again, Vim data types are converted to Lua types and vice versa. 337 | 338 | ```vim 339 | call v:lua.print('Hello from Lua!') 340 | " 'Hello from Lua!' 341 | 342 | let scream = v:lua.string.rep('A', 10) 343 | echo scream 344 | " 'AAAAAAAAAA' 345 | 346 | " How about a nice statusline? 347 | lua << EOF 348 | function _G.statusline() 349 | local filepath = '%f' 350 | local align_section = '%=' 351 | local percentage_through_file = '%p%%' 352 | return string.format( 353 | '%s%s%s', 354 | filepath, 355 | align_section, 356 | percentage_through_file 357 | ) 358 | end 359 | EOF 360 | 361 | set statusline=%!v:lua.statusline() 362 | 363 | " Also works in expression mappings 364 | lua << EOF 365 | function _G.check_back_space() 366 | local col = vim.api.nvim_win_get_cursor(0)[2] 367 | return (col == 0 or vim.api.nvim_get_current_line():sub(col, col):match('%s')) and true 368 | end 369 | EOF 370 | 371 | inoremap 372 | \ pumvisible() ? "\" : 373 | \ v:lua.check_back_space() ? "\" : 374 | \ completion#trigger_completion() 375 | 376 | " Call a function from a Lua module by using single quotes and omitting parentheses: 377 | call v:lua.require'module'.foo() 378 | ``` 379 | 380 | See also: 381 | 382 | - [`:help v:lua`](https://neovim.io/doc/user/eval.html#v:lua) 383 | - [`:help v:lua-call`](https://neovim.io/doc/user/lua.html#v:lua-call) 384 | 385 | #### Caveats 386 | 387 | This variable can only be used to call functions. The following will always throw an error: 388 | 389 | ```vim 390 | " Aliasing functions doesn't work 391 | let LuaPrint = v:lua.print 392 | 393 | " Accessing dictionaries doesn't work 394 | echo v:lua.some_global_dict['key'] 395 | 396 | " Using a function as a value doesn't work 397 | echo map([1, 2, 3], v:lua.global_callback) 398 | ``` 399 | 400 | ### Tips 401 | 402 | You can get Lua syntax highlighting inside .vim files by putting `let g:vimsyn_embed = 'l'` in your configuration file. See [`:help g:vimsyn_embed`](https://neovim.io/doc/user/syntax.html#g:vimsyn_embed) for more on this option. 403 | 404 | ## The vim namespace 405 | 406 | Neovim exposes a global `vim` variable which serves as an entry point to interact with its APIs from Lua. It provides users with an extended "standard library" of functions as well as various sub-modules. 407 | 408 | Some notable functions and modules include: 409 | 410 | - `vim.inspect`: transform Lua objects into human-readable strings (useful for inspecting tables) 411 | - `vim.regex`: use Vim regexes from Lua 412 | - `vim.api`: module that exposes API functions (the same API used by remote plugins) 413 | - `vim.ui`: overridable UI functions that can be leveraged by plugins 414 | - `vim.loop`: module that exposes the functionality of Neovim's event-loop (using LibUV) 415 | - `vim.lsp`: module that controls the built-in LSP client 416 | - `vim.treesitter`: module that exposes the functionality of the tree-sitter library 417 | 418 | This list is by no means comprehensive. If you wish to know more about what's made available by the `vim` variable, [`:help lua-stdlib`](https://neovim.io/doc/user/lua.html#lua-stdlib) and [`:help lua-vim`](https://neovim.io/doc/user/lua.html#lua-vim) are the way to go. Alternatively, you can do `:lua print(vim.inspect(vim))` to get a list of every module. API functions are documented under [`:help api-global`](https://neovim.io/doc/user/api.html#api-global). 419 | 420 | #### Tips 421 | 422 | Writing `print(vim.inspect(x))` every time you want to inspect the contents of an object can get pretty tedious. It might be worthwhile to have a global wrapper function somewhere in your configuration (in Neovim 0.7.0+, this function is built-in, see [`:help vim.pretty_print()`]()): 423 | 424 | ```lua 425 | function _G.put(...) 426 | local objects = {} 427 | for i = 1, select('#', ...) do 428 | local v = select(i, ...) 429 | table.insert(objects, vim.inspect(v)) 430 | end 431 | 432 | print(table.concat(objects, '\n')) 433 | return ... 434 | end 435 | ``` 436 | 437 | You can then inspect the contents of an object very quickly in your code or from the command-line: 438 | 439 | ```lua 440 | put({1, 2, 3}) 441 | ``` 442 | 443 | ```vim 444 | :lua put(vim.loop) 445 | ``` 446 | 447 | Alternatively, you can use the `:lua` command to pretty-print a Lua expression by prefixing it with `=` (Neovim 0.7+ only): 448 | 449 | ```vim 450 | :lua =vim.loop 451 | ``` 452 | 453 | Additionally, you may find that built-in Lua functions are sometimes lacking compared to what you would find in other languages (for example `os.clock()` only returns a value in seconds, not milliseconds). Be sure to look at the Neovim stdlib (and `vim.fn`, more on that later), it probably has what you're looking for. 454 | 455 | ## Using Vimscript from Lua 456 | 457 | ### vim.api.nvim_eval() 458 | 459 | This function evaluates a Vimscript expression string and returns its value. Vimscript data types are automatically converted to Lua types (and vice versa). 460 | 461 | It is the Lua equivalent of the `luaeval()` function in Vimscript 462 | 463 | ```lua 464 | -- Data types are converted correctly 465 | print(vim.api.nvim_eval('1 + 1')) -- 2 466 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 467 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" } 468 | print(vim.api.nvim_eval('v:true')) -- true 469 | print(vim.api.nvim_eval('v:null')) -- nil 470 | ``` 471 | 472 | #### Caveats 473 | 474 | Unlike `luaeval()`, `vim.api.nvim_eval()` does not provide an implicit `_A` variable to pass data to the expression. 475 | 476 | ### vim.api.nvim_exec() 477 | 478 | This function evaluates a chunk of Vimscript code. It takes in a string containing the source code to execute and a boolean to determine whether the output of the code should be returned by the function (you can then store the output in a variable, for example). 479 | 480 | ```lua 481 | local result = vim.api.nvim_exec( 482 | [[ 483 | let s:mytext = 'hello world' 484 | 485 | function! s:MyFunction(text) 486 | echo a:text 487 | endfunction 488 | 489 | call s:MyFunction(s:mytext) 490 | ]], 491 | true) 492 | 493 | print(result) -- 'hello world' 494 | ``` 495 | 496 | #### Caveats 497 | 498 | `nvim_exec` does not support script-local variables (`s:`) prior to Neovim 0.6.0 499 | 500 | ### vim.api.nvim_command() 501 | 502 | This function executes an ex command. It takes in a string containing the command to execute. 503 | 504 | ```lua 505 | vim.api.nvim_command('new') 506 | vim.api.nvim_command('wincmd H') 507 | vim.api.nvim_command('set nonumber') 508 | vim.api.nvim_command('%s/foo/bar/g') 509 | ``` 510 | 511 | ### vim.cmd() 512 | 513 | Alias for `vim.api.nvim_exec()`. Only the command argument is needed, `output` is always set to `false`. 514 | 515 | ```lua 516 | vim.cmd('buffers') 517 | vim.cmd([[ 518 | let g:multiline_list = [ 519 | \ 1, 520 | \ 2, 521 | \ 3, 522 | \ ] 523 | 524 | echo g:multiline_list 525 | ]]) 526 | ``` 527 | 528 | #### Tips 529 | 530 | Since you have to pass strings to these functions, you often end up having to escape backslashes: 531 | 532 | ```lua 533 | vim.cmd('%s/\\Vfoo/bar/g') 534 | ``` 535 | 536 | Double bracketed strings are easier to use as they do not require escaping characters: 537 | 538 | ```lua 539 | vim.cmd([[%s/\Vfoo/bar/g]]) 540 | ``` 541 | 542 | ### vim.api.nvim_replace_termcodes() 543 | 544 | This API function allows you to escape terminal codes and Vim keycodes. 545 | 546 | You may have come across mappings like this one: 547 | 548 | ```vim 549 | inoremap pumvisible() ? "\" : "\" 550 | ``` 551 | 552 | Trying to do the same in Lua can prove to be a challenge. You might be tempted to do it like this: 553 | 554 | ```lua 555 | function _G.smart_tab() 556 | return vim.fn.pumvisible() == 1 and [[\]] or [[\]] 557 | end 558 | 559 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 560 | ``` 561 | 562 | only to find out that the mapping inserts `\` and `\` literally... 563 | 564 | Being able to escape keycodes is actually a Vimscript feature. Aside from the usual escape sequences like `\r`, `\42` or `\x10` that are common to many programming languages, Vimscript `expr-quotes` (strings surrounded with double quotes) allow you to escape the human-readable representation of Vim keycodes. 565 | 566 | Lua doesn't have such a feature built-in. Fortunately, Neovim has an API function for escaping terminal codes and keycodes: `nvim_replace_termcodes()` 567 | 568 | ```lua 569 | print(vim.api.nvim_replace_termcodes('', true, true, true)) 570 | ``` 571 | 572 | This is a little verbose. Making a reusable wrapper can help: 573 | 574 | ```lua 575 | -- The function is called `t` for `termcodes`. 576 | -- You don't have to call it that, but I find the terseness convenient 577 | local function t(str) 578 | -- Adjust boolean arguments as needed 579 | return vim.api.nvim_replace_termcodes(str, true, true, true) 580 | end 581 | 582 | print(t'') 583 | ``` 584 | 585 | Coming back to our earlier example, this should now work as expected: 586 | 587 | ```lua 588 | local function t(str) 589 | return vim.api.nvim_replace_termcodes(str, true, true, true) 590 | end 591 | 592 | function _G.smart_tab() 593 | return vim.fn.pumvisible() == 1 and t'' or t'' 594 | end 595 | 596 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 597 | ``` 598 | 599 | This is not necessary with `vim.keymap.set()` as it automatically transforms vim keycodes returned by Lua functions in `expr` mappings by default: 600 | 601 | ```lua 602 | vim.keymap.set('i', '', function() 603 | return vim.fn.pumvisible() == 1 and '' or '' 604 | end, {expr = true}) 605 | ``` 606 | 607 | See also: 608 | 609 | - [`:help keycodes`](https://neovim.io/doc/user/intro.html#keycodes) 610 | - [`:help expr-quote`](https://neovim.io/doc/user/eval.html#expr-quote) 611 | - [`:help nvim_replace_termcodes()`]() 612 | 613 | ## Managing vim options 614 | 615 | ### Using api functions 616 | 617 | Neovim provides a set of API functions to either set an option or get its current value: 618 | 619 | - Global options: 620 | - [`vim.api.nvim_set_option()`]() 621 | - [`vim.api.nvim_get_option()`]() 622 | - Buffer-local options: 623 | - [`vim.api.nvim_buf_set_option()`]() 624 | - [`vim.api.nvim_buf_get_option()`]() 625 | - Window-local options: 626 | - [`vim.api.nvim_win_set_option()`]() 627 | - [`vim.api.nvim_win_get_option()`]() 628 | 629 | They take a string containing the name of the option to set/get as well as the value you want to set it to. 630 | 631 | Boolean options (like `(no)number`) have to be set to either `true` or `false`: 632 | 633 | ```lua 634 | vim.api.nvim_set_option('smarttab', false) 635 | print(vim.api.nvim_get_option('smarttab')) -- false 636 | ``` 637 | 638 | Unsurprisingly, string options have to be set to a string: 639 | 640 | ```lua 641 | vim.api.nvim_set_option('selection', 'exclusive') 642 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 643 | ``` 644 | 645 | Number options accept a number: 646 | 647 | ```lua 648 | vim.api.nvim_set_option('updatetime', 3000) 649 | print(vim.api.nvim_get_option('updatetime')) -- 3000 650 | ``` 651 | 652 | Buffer-local and window-local options also need a buffer number or a window number (using `0` will set/get the option for the current buffer/window): 653 | 654 | ```lua 655 | vim.api.nvim_win_set_option(0, 'number', true) 656 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 657 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 658 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 659 | ``` 660 | 661 | ### Using meta-accessors 662 | 663 | A few meta-accessors are available if you want to set options in a more "idiomatic" way. They essentially wrap the above API functions and allow you to manipulate options as if they were variables: 664 | 665 | - [`vim.o`](https://neovim.io/doc/user/lua.html#vim.o): behaves like `:let &{option-name}` 666 | - [`vim.go`](https://neovim.io/doc/user/lua.html#vim.go): behaves like `:let &g:{option-name}` 667 | - [`vim.bo`](https://neovim.io/doc/user/lua.html#vim.bo): behaves like `:let &l:{option-name}` for buffer-local options 668 | - [`vim.wo`](https://neovim.io/doc/user/lua.html#vim.wo): behaves like `:let &l:{option-name}` for window-local options 669 | 670 | ```lua 671 | vim.o.smarttab = false -- let &smarttab = v:false 672 | print(vim.o.smarttab) -- false 673 | vim.o.isfname = vim.o.isfname .. ',@-@' -- on Linux: let &isfname = &isfname .. ',@-@' 674 | print(vim.o.isfname) -- '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@' 675 | 676 | vim.bo.shiftwidth = 4 677 | print(vim.bo.shiftwidth) -- 4 678 | ``` 679 | 680 | You can specify a number for buffer-local and window-local options. If no number is given, the current buffer/window is used: 681 | 682 | ```lua 683 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 'expandtab', true) 684 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 'number', true) 685 | ``` 686 | 687 | These wrappers also have more sophisticated `vim.opt*` variants that provide convenient mechanisms for setting options in Lua. They're similar to what you might be used to in your `init.vim`: 688 | 689 | - `vim.opt`: behaves like `:set` 690 | - `vim.opt_global`: behaves like `:setglobal` 691 | - `vim.opt_local`: behaves like `:setlocal` 692 | 693 | ```lua 694 | vim.opt.smarttab = false 695 | print(vim.opt.smarttab:get()) -- false 696 | ``` 697 | 698 | Some options can be set using Lua tables: 699 | 700 | ```lua 701 | vim.opt.completeopt = {'menuone', 'noselect'} 702 | print(vim.inspect(vim.opt.completeopt:get())) -- { "menuone", "noselect" } 703 | ``` 704 | 705 | Wrappers for list-like, map-like and set-like options also come with methods and metamethods that work similarly to their `:set+=`, `:set^=` and `:set-=` counterparts in Vimscript. 706 | 707 | ```lua 708 | vim.opt.shortmess:append({ I = true }) 709 | -- alternative form: 710 | vim.opt.shortmess = vim.opt.shortmess + { I = true } 711 | 712 | vim.opt.whichwrap:remove({ 'b', 's' }) 713 | -- alternative form: 714 | vim.opt.whichwrap = vim.opt.whichwrap - { 'b', 's' } 715 | ``` 716 | 717 | Be sure to look at [`:help vim.opt`](https://neovim.io/doc/user/lua.html#vim.opt) for more information. 718 | 719 | See also: 720 | 721 | - [`:help lua-vim-options`](https://neovim.io/doc/user/lua.html#lua-vim-options) 722 | 723 | ## Managing vim internal variables 724 | 725 | ### Using api functions 726 | 727 | Much like options, internal variables have their own set of API functions: 728 | 729 | - Global variables (`g:`): 730 | - [`vim.api.nvim_set_var()`]() 731 | - [`vim.api.nvim_get_var()`]() 732 | - [`vim.api.nvim_del_var()`]() 733 | - Buffer variables (`b:`): 734 | - [`vim.api.nvim_buf_set_var()`]() 735 | - [`vim.api.nvim_buf_get_var()`]() 736 | - [`vim.api.nvim_buf_del_var()`]() 737 | - Window variables (`w:`): 738 | - [`vim.api.nvim_win_set_var()`]() 739 | - [`vim.api.nvim_win_get_var()`]() 740 | - [`vim.api.nvim_win_del_var()`]() 741 | - Tabpage variables (`t:`): 742 | - [`vim.api.nvim_tabpage_set_var()`]() 743 | - [`vim.api.nvim_tabpage_get_var()`]() 744 | - [`vim.api.nvim_tabpage_del_var()`]() 745 | - Predefined Vim variables (`v:`): 746 | - [`vim.api.nvim_set_vvar()`]() 747 | - [`vim.api.nvim_get_vvar()`]() 748 | 749 | With the exception of predefined Vim variables, they can also be deleted (the `:unlet` command is the equivalent in Vimscript). Local variables (`l:`), script variables (`s:`) and function arguments (`a:`) cannot be manipulated as they only make sense in the context of a Vim script, Lua has its own scoping rules. 750 | 751 | If you are unfamiliar with what these variables do, [`:help internal-variables`](https://neovim.io/doc/user/eval.html#internal-variables) describes them in detail. 752 | 753 | These functions take a string containing the name of the variable to set/get/delete as well as the value you want to set it to. 754 | 755 | ```lua 756 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 300 }) 757 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- { key1 = "value", key2 = 300 } 758 | vim.api.nvim_del_var('some_global_variable') 759 | ``` 760 | 761 | Variables that are scoped to a buffer, a window or a tabpage also receive a number (using `0` will set/get/delete the variable for the current buffer/window/tabpage): 762 | 763 | ```lua 764 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 765 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 766 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 767 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 'hello world' 768 | vim.api.nvim_win_del_var(0, 'some_window_variable') 769 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 770 | ``` 771 | 772 | ### Using meta-accessors 773 | 774 | Internal variables can be manipulated more intuitively using these meta-accessors: 775 | 776 | - [`vim.g`](https://neovim.io/doc/user/lua.html#vim.g): global variables 777 | - [`vim.b`](https://neovim.io/doc/user/lua.html#vim.b): buffer variables 778 | - [`vim.w`](https://neovim.io/doc/user/lua.html#vim.w): window variables 779 | - [`vim.t`](https://neovim.io/doc/user/lua.html#vim.t): tabpage variables 780 | - [`vim.v`](https://neovim.io/doc/user/lua.html#vim.v): predefined Vim variables 781 | - [`vim.env`](https://neovim.io/doc/user/lua.html#vim.env): environment variables 782 | 783 | ```lua 784 | vim.g.some_global_variable = { 785 | key1 = 'value', 786 | key2 = 300 787 | } 788 | 789 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", key2 = 300 } 790 | 791 | -- target a specific buffer/window/tabpage (Neovim 0.6+) 792 | vim.b[2].myvar = 1 793 | ``` 794 | 795 | Some variable names may contain characters that cannot be used for identifiers in Lua. You can still manipulate these variables by using this syntax: `vim.g['my#variable']`. 796 | 797 | To delete one of these variables, simply assign `nil` to it: 798 | 799 | ```lua 800 | vim.g.some_global_variable = nil 801 | ``` 802 | 803 | See also: 804 | 805 | - [`:help lua-vim-variables`](https://neovim.io/doc/user/lua.html#lua-vim-variables) 806 | 807 | #### Caveats 808 | 809 | You cannot add/update/delete keys from a dictionary stored in one of these variables. For example, this snippet of Vimscript code does not work as expected: 810 | 811 | ```vim 812 | let g:variable = {} 813 | lua vim.g.variable.key = 'a' 814 | echo g:variable 815 | " {} 816 | ``` 817 | 818 | You can use a temporary variable as a workaround: 819 | 820 | ```vim 821 | let g:variable = {} 822 | lua << EOF 823 | local tmp = vim.g.variable 824 | tmp.key = 'a' 825 | vim.g.variable = tmp 826 | EOF 827 | echo g:variable 828 | " {'key': 'a'} 829 | ``` 830 | 831 | This is a known issue: 832 | 833 | - [Issue #12544](https://github.com/neovim/neovim/issues/12544) 834 | 835 | ## Calling Vimscript functions 836 | 837 | ### vim.fn.{function}() 838 | 839 | `vim.fn` can be used to call a Vimscript function. Data types are converted back and forth from Lua to Vimscript. 840 | 841 | ```lua 842 | print(vim.fn.printf('Hello from %s', 'Lua')) 843 | 844 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 845 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 846 | 847 | local function print_stdout(chan_id, data, name) 848 | print(data[1]) 849 | end 850 | 851 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 852 | ``` 853 | 854 | Hashes (`#`) are not valid characters for identifiers in Lua, so autoload functions have to be called with this syntax: 855 | 856 | ```lua 857 | vim.fn['my#autoload#function']() 858 | ``` 859 | 860 | The functionality of `vim.fn` is identical to `vim.call`, but allows a more Lua-like syntax. 861 | 862 | It is distinct from `vim.api.nvim_call_function` in that converting Vim/Lua objects is automatic: `vim.api.nvim_call_function` returns a table for floating point numbers and does not accept Lua closures while `vim.fn` handles these types transparently. 863 | 864 | See also: 865 | 866 | - [`:help vim.fn`](https://neovim.io/doc/user/lua.html#vim.fn) 867 | 868 | #### Tips 869 | 870 | Neovim has an extensive library of powerful built-in functions that are very useful for plugins. See [`:help vim-function`](https://neovim.io/doc/user/eval.html#vim-function) for an alphabetical list and [`:help function-list`](https://neovim.io/doc/user/usr_41.html#function-list) for a list of functions grouped by topic. 871 | 872 | Neovim API functions can be used directly through `vim.api.{..}`. See [`:help api`](https://neovim.io/doc/user/api.html#API) for information. 873 | 874 | #### Caveats 875 | 876 | Some Vim functions that should return a boolean return `1` or `0` instead. This isn't a problem in Vimscript as `1` is truthy and `0` falsy, enabling constructs like these: 877 | 878 | ```vim 879 | if has('nvim') 880 | " do something... 881 | endif 882 | ``` 883 | 884 | In Lua however, only `false` and `nil` are considered falsy, numbers always evaluate to `true` no matter their value. You have to explicitly check for `1` or `0`: 885 | 886 | ```lua 887 | if vim.fn.has('nvim') == 1 then 888 | -- do something... 889 | end 890 | ``` 891 | 892 | ## Defining mappings 893 | 894 | ### API functions 895 | 896 | Neovim provides a list of API functions to set, get and delete mappings: 897 | 898 | - Global mappings: 899 | - [`vim.api.nvim_set_keymap()`]() 900 | - [`vim.api.nvim_get_keymap()`]() 901 | - [`vim.api.nvim_del_keymap()`]() 902 | - Buffer-local mappings: 903 | - [`vim.api.nvim_buf_set_keymap()`]() 904 | - [`vim.api.nvim_buf_get_keymap()`]() 905 | - [`vim.api.nvim_buf_del_keymap()`]() 906 | 907 | Let's start with `vim.api.nvim_set_keymap()` and `vim.api.nvim_buf_set_keymap()` 908 | 909 | The first argument passed to the function is a string containing the name of the mode for which the mapping will take effect: 910 | 911 | | String value | Help page | Affected modes | Vimscript equivalent | 912 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 913 | | `''` (an empty string) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 914 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 915 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 916 | | `'s'` | `mapmode-s` | Select | `:smap` | 917 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 918 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 919 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 920 | | `'i'` | `mapmode-i` | Insert | `:imap` | 921 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 922 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 923 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 924 | 925 | The second argument is a string containing the left-hand side of the mapping (the key or set of keys that trigger the command defined in the mapping). An empty string is equivalent to ``, which disables a key. 926 | 927 | The third argument is a string containing the right-hand side of the mapping (the command to execute). 928 | 929 | The final argument is a table containing boolean options for the mapping as defined in [`:help :map-arguments`](https://neovim.io/doc/user/map.html#:map-arguments) (including `noremap` and excluding `buffer`). Since Neovim 0.7.0, you can also pass a `callback` option to invoke a Lua function instead of the right-hand side when executing the mapping. 930 | 931 | Buffer-local mappings also take a buffer number as their first argument (`0` sets the mapping for the current buffer). 932 | 933 | ```lua 934 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', { noremap = true, silent = true }) 935 | -- :nnoremap :set hlsearch 936 | vim.api.nvim_set_keymap('n', 'tegf', [[lua require('telescope.builtin').git_files()]], { noremap = true, silent = true }) 937 | -- :nnoremap tegf lua require('telescope.builtin').git_files() 938 | 939 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : "ggcc"', { noremap = true, expr = true }) 940 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 941 | 942 | vim.api.nvim_set_keymap('n', 'ex', '', { 943 | noremap = true, 944 | callback = function() 945 | print('My example') 946 | end, 947 | -- Since Lua function don't have a useful string representation, you can use the "desc" option to document your mapping 948 | desc = 'Prints "My example" in the message area', 949 | }) 950 | ``` 951 | 952 | `vim.api.nvim_get_keymap()` takes a string containing the shortname of the mode for which you want the list of mappings (see table above). The return value is a table containing all global mappings for the mode. 953 | 954 | ```lua 955 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 956 | -- :verbose nmap 957 | ``` 958 | 959 | `vim.api.nvim_buf_get_keymap()` takes an additional buffer number as its first argument (`0` will get mapppings for the current bufffer) 960 | 961 | ```lua 962 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 963 | -- :verbose imap 964 | ``` 965 | 966 | `vim.api.nvim_del_keymap()` takes a mode and the left-hand side of a mapping. 967 | 968 | ```lua 969 | vim.api.nvim_del_keymap('n', '') 970 | -- :nunmap 971 | ``` 972 | 973 | Again, `vim.api.nvim_buf_del_keymap()`, takes a buffer number as its first argument, with `0` representing the current buffer. 974 | 975 | ```lua 976 | vim.api.nvim_buf_del_keymap(0, 'i', '') 977 | -- :iunmap 978 | ``` 979 | 980 | ### vim.keymap 981 | 982 | :warning: The functions discussed in this section are only available in Neovim 0.7.0+ 983 | 984 | Neovim provides two functions to set/del mappings: 985 | 986 | - [`vim.keymap.set()`]() 987 | - [`vim.keymap.del()`]() 988 | 989 | These are similar to the above API functions with added syntactic sugar. 990 | 991 | `vim.keymap.set()` takes a string as its first argument. It can also be a table of strings to define mappings for multiple modes at once: 992 | 993 | ```lua 994 | vim.keymap.set('n', 'ex1', 'lua vim.notify("Example 1")') 995 | vim.keymap.set({'n', 'c'}, 'ex2', 'lua vim.notify("Example 2")') 996 | ``` 997 | 998 | The second argument is the left-hand side of the mapping. 999 | 1000 | The third argument is the right-hand side of the mapping, which can either be a string or a Lua function: 1001 | 1002 | ```lua 1003 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"') 1004 | vim.keymap.set('n', 'ex2', function() print("Example 2") end) 1005 | vim.keymap.set('n', 'pl1', require('plugin').plugin_action) 1006 | -- To avoid the startup cost of requiring the module, you can wrap it in a function to require it lazily when invoking the mapping: 1007 | vim.keymap.set('n', 'pl2', function() require('plugin').plugin_action() end) 1008 | ``` 1009 | 1010 | The fourth (optional) argument is a table of options that correspond to the options passed to `vim.api.nvim_set_keymap()`, with a few additions (see [`:help vim.keymap.set()`]() for the full list). 1011 | 1012 | ```lua 1013 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"', {buffer = true}) 1014 | vim.keymap.set('n', 'ex2', function() print('Example 2') end, {desc = 'Prints "Example 2" to the message area'}) 1015 | ``` 1016 | 1017 | Defining keymaps with a Lua function is different from using a string. The usual way to show information about a keymap like `:nmap ex1` will not output useful information (the string itself), but instead only show `Lua function`. It is recommended to add a `desc` key to describe the behavior of your keymap. This is especially important for documenting plugin mappings so users can understand the usage of the keymap more easily. 1018 | 1019 | An interesting feature of this API is that it irons out some historical quirks of Vim mappings: 1020 | 1021 | - Mappings are `noremap` by default, except when the `rhs` is a `` mapping. This means you rarely have to think about whether a mapping should be recursive or not: 1022 | 1023 | ```lua 1024 | vim.keymap.set('n', 'test1', 'echo "test"') 1025 | -- :nnoremap test echo "test" 1026 | 1027 | -- If you DO want the mapping to be recursive, set the "remap" option to "true" 1028 | vim.keymap.set('n', '>', ']', {remap = true}) 1029 | -- :nmap > ] 1030 | 1031 | -- mappings don't work unless they're recursive, vim.keymap.set() handles that for you automatically 1032 | vim.keymap.set('n', 'plug', '(plugin)') 1033 | -- :nmap plug (plugin) 1034 | ``` 1035 | 1036 | - In `expr` mappings, `nvim_replace_termcodes()` is automatically applied to strings returned from Lua functions: 1037 | ```lua 1038 | vim.keymap.set('i', '', function() 1039 | return vim.fn.pumvisible == 1 and '' or '' 1040 | end, {expr = true}) 1041 | ``` 1042 | 1043 | See also: 1044 | 1045 | - [`:help recursive_mapping`](https://neovim.io/doc/user/map.html#recursive_mapping) 1046 | 1047 | `vim.keymap.del()` works the same way but deletes mappings instead: 1048 | 1049 | ```lua 1050 | vim.keymap.del('n', 'ex1') 1051 | vim.keymap.del({'n', 'c'}, 'ex2', {buffer = true}) 1052 | ``` 1053 | 1054 | ## Defining user commands 1055 | 1056 | :warning: The API functions discussed in this section are only available in Neovim 0.7.0+ 1057 | 1058 | Neovim provides API functions for user-defined commands: 1059 | 1060 | - Global user commands: 1061 | - [`vim.api.nvim_create_user_command()`]() 1062 | - [`vim.api.nvim_del_user_command()`]() 1063 | - Buffer-local user commands: 1064 | - [`vim.api.nvim_buf_create_user_command()`]() 1065 | - [`vim.api.nvim_buf_del_user_command()`]() 1066 | 1067 | Let's start with `vim.api.nvim_create_user_command()` 1068 | 1069 | The first argument passed to this function is the name of the command (which must start with an uppercase letter). 1070 | 1071 | The second argument is the code to execute when invoking said command. It can either be: 1072 | 1073 | A string (in which case it will be executed as Vimscript). You can use escape sequences like ``, ``, etc. like you would with `:command` 1074 | 1075 | ```lua 1076 | vim.api.nvim_create_user_command('Upper', 'echo toupper()', { nargs = 1 }) 1077 | -- :command! -nargs=1 Upper echo toupper() 1078 | 1079 | vim.cmd('Upper hello world') -- prints "HELLO WORLD" 1080 | ``` 1081 | 1082 | Or a Lua function. It receives a dictionary-like table that contains the data normally provided by escape sequences (see [`:help nvim_create_user_command()`]() for a list of available keys) 1083 | 1084 | ```lua 1085 | vim.api.nvim_create_user_command( 1086 | 'Upper', 1087 | function(opts) 1088 | print(string.upper(opts.args)) 1089 | end, 1090 | { nargs = 1 } 1091 | ) 1092 | ``` 1093 | 1094 | The third argument lets you pass command attributes as a table (see [`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes)). Since you can already define buffer-local user commands with `vim.api.nvim_buf_create_user_command()`, `-buffer` is not a valid attribute. 1095 | 1096 | Two additional attributes are available: 1097 | 1098 | - `desc` allows you to control what gets displayed when you run `:command {cmd}` on a command defined as a Lua callback. Similarly to keymaps, it is recommended to add a `desc` key to commands defined as Lua functions. 1099 | - `force` is equivalent to calling `:command!` and replaces a command if one with the same name already exists. It is true by default, unlike its Vimscript equivalent. 1100 | 1101 | The `-complete` attribute can take a Lua function in addition to the attributes listed in [`:help :command-complete`](https://neovim.io/doc/user/map.html#:command-complete). 1102 | 1103 | ```lua 1104 | vim.api.nvim_create_user_command('Upper', function() end, { 1105 | nargs = 1, 1106 | complete = function(ArgLead, CmdLine, CursorPos) 1107 | -- return completion candidates as a list-like table 1108 | return { 'foo', 'bar', 'baz' } 1109 | end, 1110 | }) 1111 | ``` 1112 | 1113 | Buffer-local user commands also take a buffer number as their first argument. This is an advantage over `-buffer` which can only define a command for the current buffer. 1114 | 1115 | ```lua 1116 | vim.api.nvim_buf_create_user_command(4, 'Upper', function() end, {}) 1117 | ``` 1118 | 1119 | `vim.api.nvim_del_user_command()` takes a command name. 1120 | 1121 | ```lua 1122 | vim.api.nvim_del_user_command('Upper') 1123 | -- :delcommand Upper 1124 | ``` 1125 | 1126 | Again, `vim.api.nvim_buf_del_user_command()`, takes a buffer number as its first argument, with `0` representing the current buffer. 1127 | 1128 | ```lua 1129 | vim.api.nvim_buf_del_user_command(4, 'Upper') 1130 | ``` 1131 | 1132 | See also: 1133 | 1134 | - [`:help nvim_create_user_command()`]() 1135 | - [`:help 40.2`](https://neovim.io/doc/user/usr_40.html#40.2) 1136 | - [`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes) 1137 | 1138 | ### Caveats 1139 | 1140 | The `-complete=custom` attribute automatically filters completion candidates and has built-in wildcard ([`:help wildcard`](https://neovim.io/doc/user/editing.html#wildcard)) support: 1141 | 1142 | ```vim 1143 | function! s:completion_function(ArgLead, CmdLine, CursorPos) abort 1144 | return join([ 1145 | \ 'strawberry', 1146 | \ 'star', 1147 | \ 'stellar', 1148 | \ ], "\n") 1149 | endfunction 1150 | 1151 | command! -nargs=1 -complete=custom,s:completion_function Test echo 1152 | " Typing `:Test st[ae]` returns "star" and "stellar" 1153 | ``` 1154 | 1155 | Passing a Lua function to `complete` makes it behave like `customlist` which leaves filtering up to the user: 1156 | 1157 | ```lua 1158 | vim.api.nvim_create_user_command('Test', function() end, { 1159 | nargs = 1, 1160 | complete = function(ArgLead, CmdLine, CursorPos) 1161 | return { 1162 | 'strawberry', 1163 | 'star', 1164 | 'stellar', 1165 | } 1166 | end, 1167 | }) 1168 | 1169 | -- Typing `:Test z` returns all the completion results because the list was not filtered 1170 | ``` 1171 | 1172 | ## Defining autocommands 1173 | 1174 | (this section is a work in progress) 1175 | 1176 | Neovim 0.7.0 has API functions for autocommands. See `:help api-autocmd` for details 1177 | 1178 | - [Pull request #14661](https://github.com/neovim/neovim/pull/14661) (lua: autocmds take 2) 1179 | 1180 | ## Defining highlights 1181 | 1182 | (this section is a work in progress) 1183 | 1184 | Neovim 0.7.0 has API functions for highlight groups. See also: 1185 | 1186 | - [`:help nvim_set_hl()`]() 1187 | - [`:help nvim_get_hl_by_id()`]() 1188 | - [`:help nvim_get_hl_by_name()`]() 1189 | 1190 | ## General tips and recommendations 1191 | 1192 | ### Reloading cached modules 1193 | 1194 | In Lua, the `require()` function caches modules. This is a good thing for performance, but it can make working on plugins a bit cumbersome because modules are not updated on subsequent `require()` calls. 1195 | 1196 | If you'd like to refresh the cache for a particular module, you have to modify the `package.loaded` global table: 1197 | 1198 | ```lua 1199 | package.loaded['modname'] = nil 1200 | require('modname') -- loads an updated version of module 'modname' 1201 | ``` 1202 | 1203 | The [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) plugin has a [custom function](https://github.com/nvim-lua/plenary.nvim/blob/master/lua/plenary/reload.lua) that does this for you. 1204 | 1205 | ### Don't pad Lua strings! 1206 | 1207 | When using double bracketed strings, resist the temptation to pad them! While it is fine to do in contexts where spaces are ignored, it can cause hard to debug issues when whitespace is significant: 1208 | 1209 | ```lua 1210 | vim.api.nvim_set_keymap('n', 'f', [[ call foo() ]], {noremap = true}) 1211 | ``` 1212 | 1213 | In the above example, `f` is mapped to `call foo()` instead of `call foo()`. 1214 | 1215 | ### Notes about Vimscript <-> Lua type conversion 1216 | 1217 | #### Converting a variable creates a copy: 1218 | 1219 | You can't directly interact with the reference to a Vim object from Lua or a Lua object from Vimscript. 1220 | For example, the `map()` function in Vimscript modifies a variable in place: 1221 | 1222 | ```vim 1223 | let s:list = [1, 2, 3] 1224 | let s:newlist = map(s:list, {_, v -> v * 2}) 1225 | 1226 | echo s:list 1227 | " [2, 4, 6] 1228 | echo s:newlist 1229 | " [2, 4, 6] 1230 | echo s:list is# s:newlist 1231 | " 1 1232 | ``` 1233 | 1234 | Using this function from Lua creates a copy instead: 1235 | 1236 | ```lua 1237 | local tbl = {1, 2, 3} 1238 | local newtbl = vim.fn.map(tbl, function(_, v) return v * 2 end) 1239 | 1240 | print(vim.inspect(tbl)) -- { 1, 2, 3 } 1241 | print(vim.inspect(newtbl)) -- { 2, 4, 6 } 1242 | print(tbl == newtbl) -- false 1243 | ``` 1244 | 1245 | #### Conversion is not always possible 1246 | 1247 | This mostly affects functions and tables: 1248 | 1249 | Lua tables that are a mix between a List and a Dictionary can't be converted: 1250 | 1251 | ```lua 1252 | print(vim.fn.count({1, 1, number = 1}, 1)) 1253 | -- E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys 1254 | ``` 1255 | 1256 | While you can call Vim functions in Lua with `vim.fn`, you can't hold references to them. This can cause surprising behaviors: 1257 | 1258 | ```lua 1259 | local FugitiveHead = vim.fn.funcref('FugitiveHead') 1260 | print(FugitiveHead) -- vim.NIL 1261 | 1262 | vim.cmd("let g:test_dict = {'test_lambda': {-> 1}}") 1263 | print(vim.g.test_dict.test_lambda) -- nil 1264 | print(vim.inspect(vim.g.test_dict)) -- {} 1265 | ``` 1266 | 1267 | Passing Lua functions to Vim functions is OK, storing them in Vim variables is not (fixed in Neovim 0.7.0+): 1268 | 1269 | ```lua 1270 | -- This works: 1271 | vim.fn.jobstart({'ls'}, { 1272 | on_stdout = function(chan_id, data, name) 1273 | print(vim.inspect(data)) 1274 | end 1275 | }) 1276 | 1277 | -- This doesn't: 1278 | vim.g.test_dict = {test_lambda = function() return 1 end} -- Error: Cannot convert given lua type 1279 | ``` 1280 | 1281 | Note however that doing the same from Vimscript with `luaeval()` **does** work: 1282 | 1283 | ```vim 1284 | let g:test_dict = {'test_lambda': luaeval('function() return 1 end')} 1285 | echo g:test_dict 1286 | " {'test_lambda': function('4714')} 1287 | ``` 1288 | 1289 | #### Vim booleans 1290 | 1291 | A common pattern in Vim scripts is to use `1` or `0` instead of proper booleans. Indeed, Vim did not have a separate boolean type until version 7.4.1154. 1292 | 1293 | Lua booleans are converted to actual booleans in Vimscript, not numbers: 1294 | 1295 | ```vim 1296 | lua vim.g.lua_true = true 1297 | echo g:lua_true 1298 | " v:true 1299 | lua vim.g.lua_false = false 1300 | echo g:lua_false 1301 | " v:false 1302 | ``` 1303 | 1304 | ### Setting up linters/language servers 1305 | 1306 | If you're using linters and/or language servers to get diagnostics and autocompletion for Lua projects, you may have to configure Neovim-specific settings for them. Here are a few recommended settings for popular tools: 1307 | 1308 | #### luacheck 1309 | 1310 | You can get [luacheck](https://github.com/mpeterv/luacheck/) to recognize the `vim` global by putting this configuration in `~/.luacheckrc` (or `$XDG_CONFIG_HOME/luacheck/.luacheckrc`): 1311 | 1312 | ```lua 1313 | globals = { 1314 | "vim", 1315 | } 1316 | ``` 1317 | 1318 | The [Alloyed/lua-lsp](https://github.com/Alloyed/lua-lsp/) language server uses `luacheck` to provide linting and reads the same file. 1319 | 1320 | For more information on how to configure `luacheck`, please refer to its [documentation](https://luacheck.readthedocs.io/en/stable/config.html) 1321 | 1322 | #### sumneko/lua-language-server 1323 | 1324 | The [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) repository contains [instructions to configure sumneko/lua-language-server](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#sumneko_lua) (the example uses the built-in LSP client but the configuration should be identical for other LSP client implementations). 1325 | 1326 | For more information on how to configure [sumneko/lua-language-server](https://github.com/sumneko/lua-language-server/) see ["Setting"](https://github.com/sumneko/lua-language-server/wiki/Setting) 1327 | 1328 | #### coc.nvim 1329 | 1330 | The [rafcamlet/coc-nvim-lua](https://github.com/rafcamlet/coc-nvim-lua/) completion source for [coc.nvim](https://github.com/neoclide/coc.nvim/) provides completion items for the Neovim stdlib. 1331 | 1332 | ### Debugging Lua code 1333 | 1334 | You can debug Lua code running in a separate Neovim instance with [jbyuki/one-small-step-for-vimkind](https://github.com/jbyuki/one-small-step-for-vimkind) 1335 | 1336 | The plugin uses the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/). Connecting to a debug adapter requires a DAP client like [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap/) or [puremourning/vimspector](https://github.com/puremourning/vimspector/). 1337 | 1338 | ### Debugging Lua mappings/commands/autocommands 1339 | 1340 | The `:verbose` command allows you to see where a mapping/command/autocommand was defined: 1341 | 1342 | ```vim 1343 | :verbose map m 1344 | ``` 1345 | 1346 | ```text 1347 | n m_ * echo 'example' 1348 | Last set from ~/.config/nvim/init.vim line 26 1349 | ``` 1350 | 1351 | By default, this feature is disabled in Lua for performance reasons. You can enable it by starting Neovim with a verbose level greater than 0: 1352 | 1353 | ```sh 1354 | nvim -V1 1355 | ``` 1356 | 1357 | See also: 1358 | 1359 | - [`:help 'verbose'`](https://neovim.io/doc/user/options.html#'verbose') 1360 | - [`:help -V`](https://neovim.io/doc/user/starting.html#-V) 1361 | - [neovim/neovim#15079](https://github.com/neovim/neovim/pull/15079) 1362 | 1363 | ### Testing Lua code 1364 | 1365 | - [plenary.nvim: test harness](https://github.com/nvim-lua/plenary.nvim/#plenarytest_harness) 1366 | - [notomo/vusted](https://github.com/notomo/vusted) 1367 | 1368 | ### Using Luarocks packages 1369 | 1370 | [wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim) supports Luarocks packages. Instructions for how to set this up are available in the [README](https://github.com/wbthomason/packer.nvim/#luarocks-support) 1371 | 1372 | ## Miscellaneous 1373 | 1374 | ### vim.loop 1375 | 1376 | `vim.loop` is the module that exposes the LibUV API. Some resources: 1377 | 1378 | - [Official documentation for LibUV](https://docs.libuv.org/en/v1.x/) 1379 | - [Luv documentation](https://github.com/luvit/luv/blob/master/docs.md) 1380 | - [teukka.tech - Using LibUV in Neovim](https://teukka.tech/posts/2020-01-07-vimloop/) 1381 | 1382 | See also: 1383 | 1384 | - [`:help vim.loop`](https://neovim.io/doc/user/lua.html#vim.loop) 1385 | 1386 | ### vim.lsp 1387 | 1388 | `vim.lsp` is the module that controls the built-in LSP client. The [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) repository contains default configurations for popular language servers. 1389 | 1390 | The behavior of the client can be configured using "lsp-handlers". For more information: 1391 | 1392 | - [`:help lsp-handler`](https://neovim.io/doc/user/lsp.html#lsp-handler) 1393 | - [neovim/neovim#12655](https://github.com/neovim/neovim/pull/12655) 1394 | - [How to migrate from diagnostic-nvim](https://github.com/nvim-lua/diagnostic-nvim/issues/73#issue-737897078) 1395 | 1396 | You may also want to take a look at [plugins built around the LSP client](https://github.com/rockerBOO/awesome-neovim#lsp) 1397 | 1398 | See also: 1399 | 1400 | - [`:help lsp`](https://neovim.io/doc/user/lsp.html#LSP) 1401 | 1402 | ### vim.treesitter 1403 | 1404 | `vim.treesitter` is the module that controls the integration of the [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) library in Neovim. If you want to know more about Tree-sitter, you may be interested in this [presentation (38:37)](https://www.youtube.com/watch?v=Jes3bD6P0To). 1405 | 1406 | The [nvim-treesitter](https://github.com/nvim-treesitter/) organisation hosts various plugins taking advantage of the library. 1407 | 1408 | See also: 1409 | 1410 | - [`:help lua-treesitter`](https://neovim.io/doc/user/treesitter.html#lua-treesitter) 1411 | 1412 | ### Transpilers 1413 | 1414 | One advantage of using Lua is that you don't actually have to write Lua code! There is a multitude of transpilers available for the language. 1415 | 1416 | - [Moonscript](https://moonscript.org/) 1417 | 1418 | Probably one of the most well-known transpilers for Lua. Adds a lots of convenient features like classes, list comprehensions or function literals. The [svermeulen/nvim-moonmaker](https://github.com/svermeulen/nvim-moonmaker) plugin allows you to write Neovim plugins and configuration directly in Moonscript. 1419 | 1420 | - [Fennel](https://fennel-lang.org/) 1421 | 1422 | A lisp that compiles to Lua. You can write configuration and plugins for Neovim in Fennel with the [Olical/aniseed](https://github.com/Olical/aniseed) or the [Hotpot](https://github.com/rktjmp/hotpot.nvim) plugin. Additionally, the [Olical/conjure](https://github.com/Olical/conjure) plugin provides an interactive development environment that supports Fennel (among other languages). 1423 | 1424 | - [Teal](https://github.com/teal-language/tl) 1425 | 1426 | The name Teal comes from pronouncing TL (typed lua). This is exactly what it tries to do - add strong typing to lua while otherwise remaining close to standard lua syntax. The [nvim-teal-maker](https://github.com/svermeulen/nvim-teal-maker) plugin can be used to write Neovim plugins or configuration files directly in Teal 1427 | 1428 | Other interesting projects: 1429 | 1430 | - [TypeScriptToLua/TypeScriptToLua](https://github.com/TypeScriptToLua/TypeScriptToLua) 1431 | - [Haxe](https://haxe.org/) 1432 | - [SwadicalRag/wasm2lua](https://github.com/SwadicalRag/wasm2lua) 1433 | - [hengestone/lua-languages](https://github.com/hengestone/lua-languages) 1434 | -------------------------------------------------------------------------------- /README.pt-br.md: -------------------------------------------------------------------------------- 1 | # Primeiros passos usando Lua no Neovim 2 | 3 | ## Introdução 4 | 5 | A integração do Lua como uma linguagem de primeira classe dentro do Neovim está se configurando para ser uma de suas características matadoras. No entanto, a quantidade de material didático para aprender a escrever plug-ins em Lua não é tão grande quanto você encontraria para escrevê-los em Vimscript. Esta é uma tentativa de fornecer algumas informações básicas para ajudar e incentivar quem está começando agora. 6 | 7 | Este guia assume que você está usando o [build noturno](https://github.com/neovim/neovim/releases/tag/nightly) mais recente do Neovim. Como a versão 0.5 do Neovim é uma versão em desenvolvimento, tenha em mente que algumas APIs nas quais estão sendo trabalhadas ativamente não são muito estáveis e podem mudar antes do lançamento. 8 | 9 | ### Aprendendo Lua 10 | 11 | Se você ainda não está familiarizado com a linguagem, existem muitos recursos para começar: 12 | 13 | - A página [Aprenda X em Y minutos sobre Lua](https://learnxinyminutes.com/docs/lua/) deve fornecer uma visão geral rápida dos fundamentos 14 | - Se os vídeos são mais do seu agrado, Derek Banas tem um [tutorial de 1 hora sobre a linguagem](https://www.youtube.com/watch?v=iMacxZQMPXs) 15 | - O [wiki de usuários do lua](http://lua-users.org/wiki/LuaDirectory) está cheio de informações úteis sobre todos os tipos de tópicos relacionados ao Lua 16 | - O [manual oficial de referência para o Lua](https://www.lua.org/manual/5.1/) deve fornecer uma visão mais completo da linguagem 17 | 18 | Deve-se notar também que o Lua é uma linguagem muito limpa e simples. É fácil de aprender, especialmente se você tiver experiência com linguagens de script semelhantes, como JavaScript. Você já deve conhecer mais o Lua do que imagina! 19 | 20 | Nota: a versão do Lua que o Neovim embute é LuaJIT 2.1.0, que mantém a compatibilidade com Lua 5.1 (com algumas extensões 5.2) 21 | 22 | ### Tutoriais existentes para escrever códigos Lua para o Neovim 23 | 24 | Alguns tutoriais já foram criados para ajudar as pessoas a escrever plug-ins em Lua. Alguns deles ajudaram bastante na redação deste guia. Muito obrigado aos seus autores. 25 | 26 | - [teukka.tech - Do init.vim para init.lua](https://teukka.tech/luanvim.html) 27 | - [2n.pl - Como escrever plug-ins neovim em Lua](https://www.2n.pl/blog/how-to-write-neovim-plugins-in-lua.md) 28 | - [2n.pl - Como fazer interface do usuário para plug-ins neovim em Lua](https://www.2n.pl/blog/how-to-make-ui-for-neovim-plugins-in-lua) 29 | - [ms-jpq - Tutorial Neovim Async](https://ms-jpq.github.io/neovim-async-tutorial/) 30 | 31 | ### Plugins complementares 32 | 33 | - [Vimpeccable](https://github.com/svermeulen/vimpeccable) - Plugin para ajudar a escrever seu .vimrc em Lua 34 | - [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - Todas as funções lua que não quero escrever duas vezes 35 | - [popup.nvim](https://github.com/nvim-lua/popup.nvim) - Uma implementação da API Popup do vim no Neovim 36 | - [nvim_utils](https://github.com/norcalli/nvim_utils) 37 | - [nvim-luadev](https://github.com/bfredl/nvim-luadev) - console REPL / debug para plug-ins nvim lua 38 | - [nvim-luapad](https://github.com/rafcamlet/nvim-luapad) - Bloco de rascunho neovim interativo em tempo real para mecanismo lua integrado 39 | - [nlua.nvim](https://github.com/tjdevries/nlua.nvim) - Desenvolvimento Lua para Neovim 40 | - [BetterLua.vim](https://github.com/euclidianAce/BetterLua.vim) - Melhor destaque da sintaxe Lua no Vim / NeoVim 41 | 42 | ## Onde colocar os arquivos Lua 43 | 44 | Os arquivos Lua são normalmente encontrados dentro de uma pasta `lua/` em seu `runtimepath` (para a maioria dos usuários, isso significará `~/.config/nvim/lua` em sistemas *nix e `~/AppData/Local/nvim/lua` no Windows). Os globais `package.path` e `package.cpath` são ajustados automaticamente para incluir arquivos Lua nesta pasta. Isso significa que você pode `require()` esses arquivos como módulos Lua. 45 | 46 | Vamos pegar a seguinte estrutura de pastas como exemplo: 47 | 48 | ```texto 49 | 📂 ~/.config/nvim 50 | ├── 📁 after 51 | ├── 📁 ftplugin 52 | ├── 📂 lua 53 | │ ├── 🌑 myluamodule.lua 54 | │ └── 📂 other_modules 55 | │ ├── 🌑 anothermodule.lua 56 | │ └── 🌑 init.lua 57 | ├── 📁 pack 58 | ├── 📁 plugin 59 | ├── 📁 syntax 60 | └── 🇻 init.vim 61 | ``` 62 | 63 | O seguinte código Lua carregará `myluamodule.lua`: 64 | 65 | ```lua 66 | require('myluamodule') 67 | ``` 68 | 69 | Observe a ausência de uma extensão `.lua`. 70 | 71 | Da mesma forma, o carregamento de `other_modules/anothermodule.lua` é feito assim: 72 | 73 | ```lua 74 | require('other_modules.anothermodule') 75 | - ou 76 | require('other_modules/anothermodule') 77 | ``` 78 | 79 | Os separadores de caminho são indicados por um ponto `.` ou por uma barra `/`. 80 | 81 | Uma pasta contendo um arquivo `init.lua` pode ser solicitada diretamente, sem ter que especificar o nome do arquivo. 82 | 83 | ```lua 84 | require('other_modules') -- loads other_modules/init.lua 85 | ``` 86 | 87 | Para mais informações: `:help lua-require` 88 | 89 | #### Ressalvas 90 | 91 | Ao contrário dos arquivos .vim, os arquivos .lua não são originados automaticamente de diretórios em seu `runtimepath`. Em vez disso, você deve obtê-los/solicitá-los do Vimscript. Existem planos para adicionar a opção de carregar um arquivo `init.lua` como uma alternativa para` init.vim`: 92 | 93 | - [Problema nº 7895](https://github.com/neovim/neovim/issues/7895) 94 | - [solicitação pull correspondente](https://github.com/neovim/neovim/pull/12235) 95 | 96 | #### Dicas 97 | 98 | Vários plug-ins Lua podem ter nomes de arquivo idênticos em sua pasta `lua/`. Isso pode levar a conflitos de espaço de nomes. 99 | 100 | Se dois plug-ins diferentes têm um arquivo `lua/main.lua`, então fazer `require('main')` é ambíguo: qual arquivo fonte nós queremos? 101 | 102 | Pode ser uma boa ideia atribuir um namespace à sua configuração ou ao seu plugin com uma pasta de nível superior, como: `lua/plugin_name/main.lua` 103 | 104 | ## Usando Lua a partir de Vimscript 105 | 106 | ### :lua 107 | 108 | Esse comando executa um trecho do código Lua. 109 | 110 | ```vim 111 | :lua require('myluamodule') 112 | ``` 113 | 114 | Scripts multilinhas são possíveis usando a sintaxe heredoc: 115 | 116 | ```vim 117 | echo "Aqui está um pedaço maior do código Lua" 118 | 119 | lua << EOF 120 | local mod = require('mymodule') 121 | local tbl = {1, 2, 3} 122 | 123 | for k, v in ipairs(tbl) do 124 | mod.method(v) 125 | end 126 | 127 | print(tbl) 128 | EOF 129 | ``` 130 | 131 | 132 | Veja também: 133 | 134 | - `:help :lua` 135 | - `:help :lua-heredoc` 136 | 137 | #### Ressalvas 138 | 139 | Você não obtém o realce de sintaxe correto ao escrever Lua em um arquivo .vim. Pode ser mais conveniente usar o comando `:lua` como um ponto de entrada para solicitar arquivos Lua externos. 140 | 141 | ### :luado 142 | 143 | Este comando executa um pedaço de código Lua que atua em um intervalo de linhas no buffer atual. Se nenhum intervalo for especificado, todo o buffer será usado. Qualquer string que seja retornada (`return`) do pedaço de código é usada para determinar com o que cada linha deve ser substituída. 144 | 145 | O seguinte comando substituiria todas as linhas no buffer atual com o texto `hello world`: 146 | 147 | ```vim 148 | :luado return 'hello world' 149 | ``` 150 | 151 | Duas variáveis implícitas `line` e `linenr` também são fornecidas. `line` é o texto da linha sendo iterada, enquanto `linenr` é o seu número. O comando a seguir tornaria cada linha cujo número é divisível por 2 maiúsculas: 152 | 153 | ```vim 154 | :luado if linenr % 2 == 0 then return line:upper() end 155 | ``` 156 | 157 | Veja também: 158 | 159 | - `:help :luado` 160 | 161 | ### :luafile 162 | 163 | Este comando fornece um arquivo Lua. 164 | 165 | ```vim 166 | :luafile ~/foo/bar/baz/myluafile.lua 167 | ``` 168 | 169 | É análogo ao comando `:source` para arquivos .vim ou à função incorporada `dofile()` em Lua. 170 | 171 | Veja também: 172 | 173 | - `:help :luafile` 174 | 175 | #### luafile vs require(): 176 | 177 | Você pode estar se perguntando qual é a diferença entre `lua require()` e `luafile` e se você deve usar um em vez do outro. Eles têm diferentes casos de uso: 178 | 179 | - `require()`: 180 | - é uma função Lua embutida. Ele permite que você aproveite as vantagens do sistema de módulos de Lua 181 | - busca por módulos usando a variável `package.path` (como observado anteriormente, você pode `require()` scripts Lua localizados dentro da pasta `lua/` em seu `runtimepath`) 182 | - mantém registro de quais módulos foram carregados e evita que um script seja analisado e executado uma segunda vez. Se você alterar o arquivo que contém o código de um módulo e tentar `require()` uma segunda vez enquanto o Neovim está em execução, o módulo não será atualizado 183 | - `:luafile`: 184 | - é um Ex command. Não suporta módulos 185 | - pega um caminho que é absoluto ou relativo ao diretório de trabalho da janela atual 186 | - executa o conteúdo de um script independentemente de ele ter sido executado antes 187 | 188 | `:luafile` também pode ser útil se você deseja executar um arquivo Lua no qual está trabalhando: 189 | 190 | ```vim 191 | :luafile % 192 | ``` 193 | 194 | ### luaeval() 195 | 196 | Essa função Vimscript embutida avalia uma string de expressão matemática Lua e retorna seu valor. Os tipos de dados Lua são convertidos automaticamente em tipos Vimscript (e vice-versa). 197 | 198 | ```vim 199 | " Você pode armazenar o resultado em uma variável 200 | let variable = luaeval('1 + 1') 201 | echo variable 202 | " 2 203 | let concat = luaeval('"Lua".." eh ".."incrivel"') 204 | echo concat 205 | " 'Lua eh incrivel' 206 | 207 | " Tabelas semelhantes a listas são convertidas para listas Vim 208 | let list = luaeval('{1, 2, 3, 4}') 209 | echo list[0] 210 | " 1 211 | echo list[1] 212 | " 2 213 | " Observe que, ao contrário das tabelas Lua, as listas do Vim são indexadas em 0 214 | 215 | " Tabelas semelhantes a Dict são convertidas em dicionários Vim 216 | let dict = luaeval('{foo = "bar", baz = "qux"}') 217 | echo dict.foo 218 | " 'bar' 219 | 220 | " O mesmo vale para booleanas e nulidade 221 | echo luaeval('true') 222 | " v:true 223 | echo luaeval('nil') 224 | " v:null 225 | 226 | " Você pode criar pseudônimos Vimscript para funções Lua 227 | let LuaMathPow = luaeval('math.pow') 228 | echo LuaMathPow(2, 2) 229 | " 4 230 | let LuaModuleFunction = luaeval('require("mymodule").myfunction') 231 | call LuaModuleFunction() 232 | 233 | " Também é possível passar funções Lua como valores para funções Vim 234 | lua X = function(k, v) return string.format("%s:%s", k, v) end 235 | echo map([1, 2, 3], luaeval("X")) 236 | ``` 237 | 238 | `luaeval()` recebe um segundo argumento opcional que permite que você passe dados para uma expressão matemática. Você pode então acessar esses dados de Lua usando o mágico `_A` global: 239 | 240 | ```vim 241 | echo luaeval('_A[1] + _A[2]', [1, 1]) 242 | " 2 243 | 244 | echo luaeval('string.format("Lua eh %s", _A)', 'incrivel') 245 | " 'Lua eh incrivel' 246 | ``` 247 | 248 | Veja também: 249 | - `:help luaeval()` 250 | 251 | ### v:lua 252 | 253 | Essa variável global do Vim permite chamar funções Lua globais diretamente do Vimscript. Novamente, os tipos de dados do Vim são convertidos em tipos Lua e vice-versa. 254 | 255 | ```vim 256 | call v:lua.print('Ola da Lua!') 257 | " 'Ola da Lua!' 258 | 259 | let scream = v:lua.string.rep('A', 10) 260 | echo scream 261 | " 'AAAAAAAAAA' 262 | 263 | " Podemos requerir módulos 264 | call v:lua.require('mymodule').myfunction() 265 | 266 | " Que tal um bom statusline? 267 | lua << EOF 268 | function _G.statusline() 269 | local filepath = '%f' 270 | local align_section = '%=' 271 | local percentage_through_file = '%p%%' 272 | return string.format( 273 | '%s%s%s', 274 | filepath, 275 | align_section, 276 | percentage_through_file 277 | ) 278 | end 279 | EOF 280 | 281 | set statusline=%!v:lua.statusline() 282 | 283 | " Também funciona em mapeamentos de expressões 284 | lua << EOF 285 | function _G.check_back_space() 286 | local col = vim.fn.col('.') - 1 287 | if col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then 288 | return true 289 | else 290 | return false 291 | end 292 | end 293 | EOF 294 | 295 | inoremap 296 | \ pumvisible() ? '\' : 297 | \ v:lua.check_back_space() ? '\' : 298 | \ completion#trigger_completion() 299 | ``` 300 | 301 | Veja também: 302 | - `:help v:lua` 303 | - `:help v:lua-call` 304 | 305 | 306 | #### Ressalvas 307 | 308 | Esta variável só pode ser usada para chamar funções. O seguinte sempre gerará um erro: 309 | 310 | ```vim 311 | " As funções de pseudônimo não funcionam 312 | let LuaPrint = v:lua.print 313 | 314 | " Acessar dicionários não funciona 315 | echo v:lua.some_global_dict['key'] 316 | 317 | " Usar uma função como valor não funciona 318 | echo map([1, 2, 3], v:lua.global_callback) 319 | ``` 320 | 321 | ## O namespace do vim 322 | 323 | Neovim expõe uma variável global `vim` que serve como um ponto de entrada para interagir com suas APIs de Lua. Ele fornece aos usuários uma "biblioteca padrão" estendida de funções, bem como vários submódulos. 324 | 325 | Algumas funções e módulos notáveis incluem: 326 | 327 | - `vim.inspect`: objetos Lua de impressão bonita (útil para inspecionar tabelas) 328 | - `vim.regex`: use regexes do Vim através do Lua 329 | - `vim.api`: módulo que expõe funções da API (a mesma API usada por plug-ins remotos) 330 | - `vim.loop`: módulo que expõe a funcionalidade do loop de evento do Neovim (usando LibUV) 331 | - `vim.lsp`: módulo que controla o cliente LSP integrado 332 | - `vim.treesitter`: módulo que expõe a funcionalidade da biblioteca tree-sitter 333 | 334 | Esta lista não é abrangente. Se você deseja saber mais sobre o que é disponibilizado pela variável `vim`, utilize `:help lua-stdlib` e `:help lua-vim`. Alternativamente, você pode fazer `:lua print(vim.inspect(vim))` para obter uma lista de cada módulo. 335 | 336 | #### Dicas 337 | 338 | Escrever `print(vim.inspect(x))` toda vez que você deseja inspecionar o conteúdo de um objeto pode ser muito tedioso. Pode valer a pena ter uma função de wrapper global em algum lugar da sua configuração: 339 | 340 | ```lua 341 | function _G.dump(...) 342 | local objects = vim.tbl_map(vim.inspect, {...}) 343 | print(unpack(objects)) 344 | end 345 | ``` 346 | 347 | Você pode então inspecionar o conteúdo de um objeto muito rapidamente em seu código ou na linha de comando: 348 | 349 | ```lua 350 | dump({1, 2, 3}) 351 | ``` 352 | 353 | ```vim 354 | :lua dump(vim.loop) 355 | ``` 356 | 357 | 358 | Além disso, você pode descobrir que às vezes faltam funções nativas do Lua em comparação com o que você encontraria em outras linguagens (por exemplo, `os.clock()` retorna apenas um valor em segundos, não milissegundos). Certifique-se de verificar o stdlib do Neovim (e `vim.fn`, falaremos mais sobre isso depois), ele provavelmente tem o que você está procurando. 359 | 360 | ## Usando Vimscript através do Lua 361 | 362 | ### vim.api.nvim_eval() 363 | 364 | Esta função avalia uma string de expressão Vimscript e retorna seu valor. Os tipos de dados Vimscript são convertidos automaticamente em tipos Lua (e vice-versa). 365 | 366 | É o equivalente em Lua da função `luaeval()` em Vimscript 367 | 368 | ```lua 369 | -- Os tipos de dados são convertidos corretamente 370 | print(vim.api.nvim_eval('1 + 1')) -- 2 371 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 372 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" } 373 | print(vim.api.nvim_eval('v:true')) -- true 374 | print(vim.api.nvim_eval('v:null')) -- nil 375 | ``` 376 | 377 | **A FAZER**: é possível que `vim.api.nvim_eval ()` retorne um `funcref`? 378 | 379 | #### Ressalvas 380 | 381 | Ao contrário de `luaeval()`, a utilização de `vim.api.nvim_eval()` não fornece uma variável `_A` implícita para passar dados para a expressão. 382 | 383 | ### vim.api.nvim_exec() 384 | 385 | Esta função avalia um pedaço do código Vimscript. Leva em uma string contendo o código-fonte para ser executado e um booleano para determinar se a saída do código deve ser retornada pela função (você pode então armazenar a saída em uma variável, por exemplo). 386 | 387 | ```lua 388 | local result = vim.api.nvim_exec( 389 | [[ 390 | let mytext = 'hello world' 391 | 392 | function! MyFunction(text) 393 | echo a:text 394 | endfunction 395 | 396 | call MyFunction(mytext) 397 | ]], 398 | true) 399 | 400 | print(result) -- 'hello world' 401 | ``` 402 | 403 | **A FAZER**: A documentação diz que o escopo do script (`s:`) é suportado, mas executar este trecho com uma variável com escopo do script gera um erro. Por quê? 404 | 405 | ### vim.api.nvim_command() 406 | 407 | Esta função executa um comando ex. Ele recebe uma string contendo o comando a ser executado. 408 | 409 | ```lua 410 | vim.api.nvim_command('new') 411 | vim.api.nvim_command('wincmd H') 412 | vim.api.nvim_command('set nonumber') 413 | vim.api.nvim_command('%s/foo/bar/g') 414 | ``` 415 | 416 | Nota: `vim.cmd` é um pseudônimo mais curto para esta função 417 | 418 | ```lua 419 | vim.cmd('buffers') 420 | ``` 421 | 422 | #### Dicas 423 | 424 | Como você precisa passar strings para essas funções, muitas vezes acaba tendo que escapar das barras invertidas: 425 | 426 | ```lua 427 | vim.cmd('%s/\\Vfoo/bar/g') 428 | ``` 429 | 430 | Strings literais são mais fáceis de usar, pois não requerem caracteres de escape: 431 | 432 | ```lua 433 | vim.cmd([[%s/\Vfoo/bar/g]]) 434 | ``` 435 | 436 | ## Gerenciando opções do vim 437 | 438 | ### Usando funções API 439 | 440 | Neovim fornece um conjunto de funções de API para definir (set) uma opção ou obter (get) seu valor atual: 441 | 442 | - Opções globais: 443 | - `vim.api.nvim_set_option()` 444 | - `vim.api.nvim_get_option()` 445 | - Opções locais de buffer: 446 | - `vim.api.nvim_buf_set_option()` 447 | - `vim.api.nvim_buf_get_option()` 448 | - Opções locais da janela: 449 | - `vim.api.nvim_win_set_option()` 450 | - `vim.api.nvim_win_get_option()` 451 | 452 | Eles recebem uma string contendo o nome da opção para definir/obter, bem como o valor que você deseja definir. 453 | 454 | As opções booleanas (como `(no)number`) devem ser definidas como `true` (verdadeiro) ou `false` (falso): 455 | 456 | ```lua 457 | vim.api.nvim_set_option('smarttab', false) 458 | print(vim.api.nvim_get_option('smarttab')) -- false 459 | ``` 460 | 461 | Não deve ser surpresa que as opções de string devam ser definidas como uma string: 462 | 463 | ```lua 464 | vim.api.nvim_set_option('selection', 'exclusive') 465 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 466 | ``` 467 | 468 | As opções de número aceitam um número: 469 | 470 | ```lua 471 | vim.api.nvim_set_option('updatetime', 3000) 472 | print(vim.api.nvim_get_option('updatetime')) -- 3000 473 | ``` 474 | 475 | As opções de buffer local e janela local também precisam de um número de buffer ou de janela (usando `0` irá definir/obter a opção para o buffer/janela atual): 476 | 477 | ```lua 478 | vim.api.nvim_win_set_option(0, 'number', true) 479 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 480 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 481 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 482 | ``` 483 | 484 | ### Usando meta-acessores 485 | 486 | Alguns meta-acessores estão disponíveis se você quiser definir opções de uma maneira mais "idiomática". Eles basicamente cobrem as funções de API acima e permitem que você manipule opções como se fossem variáveis: 487 | 488 | - `vim.o.{option}`: opções globais 489 | - `vim.bo.{opção}`: opções locais do buffer 490 | - `vim.wo.{opção}`: opções locais da janela 491 | 492 | ```lua 493 | vim.o.smarttab = false 494 | print(vim.o.smarttab) -- false 495 | 496 | vim.bo.shiftwidth = 4 497 | print(vim.bo.shiftwidth) -- 4 498 | ``` 499 | 500 | Você pode especificar um número para opções locais de buffer e locais de janela. Se nenhum número for fornecido, o buffer/janela atual é usado: 501 | 502 | ```lua 503 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 'expandtab', true) 504 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 'number', true) 505 | ``` 506 | 507 | Veja também: 508 | - `:help lua-vim-internal-options` 509 | 510 | #### Ressalvas 511 | 512 | **AVISO**: a seção a seguir é baseada em alguns experimentos que fiz. Os documentos não parecem mencionar esse comportamento e eu não verifiquei o código-fonte para verificar minhas afirmações. 513 | **A FAZER**: Alguém pode confirmar isso? 514 | 515 | Se você sempre lidou com opções usando o comando `:set`, o comportamento de algumas opções pode surpreendê-lo. 516 | 517 | Essencialmente, as opções podem ser globais, locais para um buffer/janela ou ter um valor global **e** local. 518 | 519 | O comando `:setglobal` define o valor global de uma opção. 520 | O comando `:setlocal` define o valor local de uma opção. 521 | O comando `:set` define o valor global **e** local de uma opção. 522 | 523 | Aqui está uma tabela útil de `:help :setglobal`: 524 | 525 | 526 | | Comando | valor global | valor local | 527 | | ----------------------: | :----------: | :---------: | 528 | | :set option=value | set | set | 529 | | :setlocal option=value | - | set | 530 | | :setglobal option=value | set | - | 531 | 532 | Não há equivalente ao comando `:set` em Lua, você define uma opção global ou localmente. 533 | 534 | Você pode esperar que a opção `number` seja global, mas a documentação a descreve como sendo "local para a janela". Essas opções são, na verdade, "fixas": seu valor é copiado da janela atual quando você abre uma nova. 535 | 536 | Portanto, se você definisse a opção em `init.lua`, faria da seguinte forma: 537 | 538 | ```lua 539 | vim.wo.number = true 540 | ``` 541 | 542 | Opções que são "locais para buffer" como `shiftwidth`, `expandtab` ou `undofile` são ainda mais confusas. Digamos que seu `init.lua` contém o seguinte código: 543 | 544 | ```lua 545 | vim.bo.expandtab = true 546 | ``` 547 | 548 | Quando você inicia o Neovim e começa a editar, está tudo bem: pressionar `` insere espaços em vez de um caractere de tabulação. Abra outro buffer e você de repente está de volta às guias... 549 | 550 | Configurá-lo globalmente tem o problema oposto: 551 | 552 | ```lua 553 | vim.o.expandtab = true 554 | ``` 555 | 556 | Desta vez, você insere guias ao iniciar o Neovim pela primeira vez. Abra outro buffer e o pressionar do `` fará o que você espera. 557 | 558 | Em suma, as opções que são "locais para buffer" devem ser definidas da seguinte maneira se você quiser o comportamento correto: 559 | 560 | ```lua 561 | vim.bo.expandtab = true 562 | vim.o.expandtab = true 563 | ``` 564 | 565 | Veja também: 566 | - `:help :setglobal` 567 | - `:help global-local` 568 | 569 | **A FAZER**: Por que isso acontece? Todas as opções locais de buffer se comportam dessa maneira? Pode estar relacionado a [neovim/neovim#7658](https://github.com/neovim/neovim/issues/7658) e a [vim/vim#2390](https://github.com/vim/vim/issues/2390). Também para opções de janela local: [neovim/neovim#11525](https://github.com/neovim/neovim/issues/11525) e [vim/vim#4945](https://github.com/vim/vim/issues/4945) 570 | 571 | ## Gerenciando variáveis internas do vim 572 | 573 | ### Usando funções API 574 | 575 | Assim como as opções, as variáveis internas têm seu próprio conjunto de funções de API: 576 | 577 | - Variáveis globais (`g:`): 578 | - `vim.api.nvim_set_var()` 579 | - `vim.api.nvim_get_var()` 580 | - `vim.api.nvim_del_var()` 581 | - Variáveis de buffer (`b:`): 582 | - `vim.api.nvim_buf_set_var()` 583 | - `vim.api.nvim_buf_get_var()` 584 | - `vim.api.nvim_buf_del_var()` 585 | - Variáveis de janela (`w:`): 586 | - `vim.api.nvim_win_set_var()` 587 | - `vim.api.nvim_win_get_var()` 588 | - `vim.api.nvim_win_del_var()` 589 | - Variáveis da página de tabulação (`t:`): 590 | - `vim.api.nvim_tabpage_set_var()` 591 | - `vim.api.nvim_tabpage_get_var()` 592 | - `vim.api.nvim_tabpage_del_var()` 593 | - Variáveis Vim predefinidas (`v:`): 594 | - `vim.api.nvim_set_vvar()` 595 | - `vim.api.nvim_get_vvar()` 596 | 597 | Com exceção das variáveis Vim predefinidas, elas também podem ser excluídas (o comando `:unlet` é o equivalente no Vimscript). Variáveis locais (`l:`), variáveis de script (`s:`) e argumentos de função (`a:`) não podem ser manipulados, pois só fazem sentido no contexto de um script Vim, Lua tem suas próprias regras de escopo. 598 | 599 | Se você não está familiarizado com o que essas variáveis fazem, `:help internal-variables` as descreve em detalhes. 600 | 601 | Essas funções recebem uma string contendo o nome da variável para definir/obter/excluir, bem como o valor para o qual você deseja defini-la. 602 | 603 | ```lua 604 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 300 }) 605 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- { key1 = "value", key2 = 300 } 606 | vim.api.nvim_del_var('some_global_variable') 607 | ``` 608 | 609 | Variáveis que têm como escopo um buffer, uma janela ou uma página de tabulação também recebem um número (usando `0` irá definir/obter/excluir a variável para o buffer/janela/página de tabulação atual): 610 | 611 | ```lua 612 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 613 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 614 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 615 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 'hello world' 616 | vim.api.nvim_win_del_var(0, 'some_window_variable') 617 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 618 | ``` 619 | 620 | ### Usando meta-acessores 621 | 622 | Variáveis internas podem ser manipuladas de forma mais intuitiva usando estes meta-acessores: 623 | 624 | - `vim.g.{name}`: variáveis globais 625 | - `vim.b.{name}`: variáveis de buffer 626 | - `vim.w.{name}`: variáveis de janela 627 | - `vim.t.{name}`: variáveis da página de tabulação 628 | - `vim.v.{name}`: variáveis Vim predefinidas 629 | 630 | ```lua 631 | vim.g.some_global_variable = { 632 | key1 = 'value', 633 | key2 = 300 634 | } 635 | 636 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", key2 = 300 } 637 | ``` 638 | 639 | Para excluir uma dessas variáveis, simplesmente atribua `nil` a ela: 640 | 641 | ```lua 642 | vim.g.some_global_variable = nil 643 | ``` 644 | 645 | #### Ressalvas 646 | 647 | Ao contrário dos meta-acessores de opções, você não pode especificar um número para variáveis com escopo de buffer/janela/página de tabulação. 648 | 649 | Além disso, você não pode adicionar/atualizar/excluir chaves de um dicionário armazenado em uma dessas variáveis. Por exemplo, este snippet de código Vimscript não funciona conforme o esperado: 650 | 651 | ```vim 652 | let g:variable = {} 653 | lua vim.g.variable.key = 'a' 654 | echo g:variable 655 | " {} 656 | ``` 657 | 658 | Este é um problema conhecido: 659 | 660 | - [Issue #12544](https://github.com/neovim/neovim/issues/12544) 661 | 662 | ## Chamando funções Vimscript 663 | 664 | ### vim.call() 665 | 666 | `vim.call()` chama uma função Vimscript. Pode ser uma função integrada do Vim ou uma função do usuário. Novamente, os tipos de dados são convertidos entre Lua e Vimscript. 667 | 668 | Leva o nome da função seguido pelos argumentos que você deseja passar para essa função: 669 | 670 | ```lua 671 | print(vim.call('printf', 'Hello from %s', 'Lua')) 672 | 673 | local reversed_list = vim.call('reverse', { 'a', 'b', 'c' }) 674 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 675 | 676 | local function print_stdout(chan_id, data, name) 677 | print(data[1]) 678 | end 679 | 680 | vim.call('jobstart', 'ls', { on_stdout = print_stdout }) 681 | 682 | vim.call('my#autoload#function') 683 | ``` 684 | 685 | Veja também: 686 | - `:help vim.call()` 687 | 688 | ### vim.fn.{function}() 689 | 690 | `vim.fn` faz exatamente a mesma coisa que `vim.call()`, mas se parece mais com uma chamada de função nativa do Lua: 691 | 692 | ```lua 693 | print(vim.fn.printf('Hello from %s', 'Lua')) 694 | 695 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 696 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 697 | 698 | local function print_stdout(chan_id, data, name) 699 | print(data[1]) 700 | end 701 | 702 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 703 | ``` 704 | Hashtags `#` não são caracteres válidos para identificadores em Lua, então funções de carregamento automático devem ser chamadas com esta sintaxe: 705 | 706 | ```lua 707 | vim.fn['my#autoload#function']() 708 | ``` 709 | 710 | Veja também: 711 | - `:help vim.fn` 712 | 713 | #### Dicas 714 | 715 | O Neovim possui uma extensa biblioteca de poderosas funções integradas que são muito úteis para plug-ins. Veja `:help vim-function` para uma lista alfabética e `:help function-list` para uma lista de funções agrupadas por tópico. 716 | 717 | #### Ressalvas 718 | 719 | Algumas funções do Vim que deveriam retornar uma booleana, retornam `1` ou` 0`. Isso não é um problema no Vimscript, já que `1` é verdadeiro e `0` falso, permitindo construções como estas: 720 | 721 | ```vim 722 | if has('nvim') 723 | " do something... 724 | endif 725 | ``` 726 | 727 | Em Lua, no entanto, apenas `false` e` nil` são considerados falsos, os números sempre avaliam como `true` independentemente de seu valor. Você deve verificar explicitamente se há `1` ou` 0`: 728 | 729 | ```lua 730 | if vim.fn.has('nvim') == 1 then 731 | -- do something... 732 | end 733 | ``` 734 | 735 | ## Definindo mapeamentos 736 | 737 | Neovim fornece uma lista de funções de API para definir, obter e excluir mapeamentos: 738 | 739 | - Mapeamentos globais: 740 | - `vim.api.nvim_set_keymap()` 741 | - `vim.api.nvim_get_keymap()` 742 | - `vim.api.nvim_del_keymap()` 743 | - Mapeamentos de buffer local: 744 | - `vim.api.nvim_buf_set_keymap()` 745 | - `vim.api.nvim_buf_get_keymap()` 746 | - `vim.api.nvim_buf_del_keymap()` 747 | 748 | Vamos começar com `vim.api.nvim_set_keymap()` e `vim.api.nvim_buf_set_keymap()` 749 | 750 | O primeiro argumento passado para a função é uma string contendo o nome do modo para o qual o mapeamento terá efeito: 751 | 752 | 753 | | Valor da string | Página de ajuda | Modos afetados | Equivalente no Vimscript | 754 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 755 | | `''` (string vazia) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 756 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 757 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 758 | | `'s'` | `mapmode-s` | Select | `:smap` | 759 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 760 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 761 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 762 | | `'i'` | `mapmode-i` | Insert | `:imap` | 763 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 764 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 765 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 766 | 767 | O segundo argumento é uma string contendo o lado esquerdo do mapeamento (a chave ou conjunto de chaves que acionam o comando definido no mapeamento). Uma string vazia é equivalente a ``, que desabilita uma tecla. 768 | 769 | O terceiro argumento é uma string contendo o lado direito do mapeamento (o comando a ser executado). 770 | 771 | O argumento final é uma tabela contendo opções booleanas para o mapeamento conforme definido em `:help :map-arguments` (incluindo `noremap` e excluindo `buffer`). 772 | 773 | Os mapeamentos locais do buffer também levam um número do buffer como primeiro argumento (`0` define o mapeamento para o buffer atual). 774 | 775 | ```lua 776 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', { noremap = true, silent = true }) 777 | -- :nnoremap :set hlsearch 778 | 779 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : "ggcc"', { noremap = true, expr = true }) 780 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 781 | ``` 782 | 783 | `vim.api.nvim_get_keymap()` pega uma string contendo o nome curto do modo para o qual você deseja a lista de mapeamentos (veja a tabela acima). O valor de retorno é uma tabela contendo todos os mapeamentos globais para o modo. 784 | 785 | ```lua 786 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 787 | -- :verbose nmap 788 | ``` 789 | 790 | `vim.api.nvim_buf_get_keymap()` recebe um número de buffer adicional como seu primeiro argumento (`0` obterá mapeamentos para o buffer atual) 791 | 792 | ```lua 793 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 794 | -- :verbose imap 795 | ``` 796 | 797 | `vim.api.nvim_del_keymap()` pega um modo e o lado esquerdo de um mapeamento. 798 | 799 | ```lua 800 | vim.api.nvim_del_keymap('n', '') 801 | -- :nunmap 802 | ``` 803 | 804 | Novamente, `vim.api.nvim_buf_del_keymap()`, recebe um número de buffer como seu primeiro argumento, com `0` representando o buffer atual. 805 | 806 | ```lua 807 | vim.api.nvim_buf_del_keymap(0, 'i', '') 808 | -- :iunmap 809 | ``` 810 | 811 | ## Definindo comandos de usuário 812 | 813 | Atualmente não há interface para criar comandos de usuário em Lua. Mas está planejado: 814 | 815 | - [Solicitação pull # 11613](https://github.com/neovim/neovim/pull/11613) 816 | 817 | Por enquanto, é melhor você criar comandos no Vimscript. 818 | 819 | ## Definindo autocommands 820 | 821 | Augroups e autocommands ainda não têm uma interface, mas está sendo trabalhada: 822 | 823 | - [Solicitação pull # 12378](https://github.com/neovim/neovim/pull/12378) 824 | 825 | Enquanto isso, você pode criar comandos automáticos no Vimscript ou usar [este wrapper de norcalli / nvim_utils](https://github.com/norcalli/nvim_utils/blob/master/lua/nvim_utils.lua#L554-L567) 826 | 827 | ## Definindo sintaxe/destaques 828 | 829 | A sintaxe API ainda é um trabalho em andamento. Aqui estão algumas dicas: 830 | 831 | - [Problema nº 9876](https://github.com/neovim/neovim/issues/9876) 832 | - [tjdevries / colorbuddy.vim, uma biblioteca para criar esquemas de cores em Lua](https://github.com/tjdevries/colorbuddy.vim) 833 | - `:help lua-treesitter` 834 | 835 | ## Dicas e recomendações gerais 836 | 837 | **FAÇAM**: 838 | - Hot-reloadings de módulos 839 | - `vim.validate()`? 840 | - Adicionar coisas sobre testes de unidade? Eu sei que o Neovim usa o framework [busted](https://olivinelabs.com/busted/), mas não sei como usá-lo para plug-ins 841 | - Melhores Práticas? Não sou um mago da Lua, então não saberia 842 | - Como usar pacotes LuaRocks ([wbthomason / packer.nvim](https://github.com/wbthomason/packer.nvim)?) 843 | 844 | ## Diversos 845 | 846 | ### vim.loop 847 | 848 | `vim.loop` é o módulo que expõe a API LibUV. Alguns recursos: 849 | 850 | - [Documentação oficial para LibUV](https://docs.libuv.org/en/v1.x/) 851 | - [documentação Luv](https://github.com/luvit/luv/blob/master/docs.md) 852 | - [teukka.tech - Usando LibUV em Neovim](https://teukka.tech/vimloop.html) 853 | 854 | Veja também: 855 | - `:help vim.loop` 856 | 857 | ### vim.lsp 858 | 859 | `vim.lsp` é o módulo que controla o cliente LSP embutido. O repositório [neovim / nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) contém configurações padrão para servidores de idiomas populares. 860 | 861 | Você também pode dar uma olhada nos plug-ins construídos em torno do cliente LSP: 862 | - [nvim-lua / completed-nvim](https://github.com/nvim-lua/completion-nvim) 863 | - [nvim-lua / diagnostic-nvim](https://github.com/nvim-lua/diagnostic-nvim) 864 | 865 | Veja também: 866 | - `:help lsp` 867 | 868 | ### vim.treesitter 869 | 870 | `vim.treesitter` é o módulo que controla a integração da biblioteca [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) no Neovim. Se você quiser saber mais sobre o Tree-sitter, pode se interessar por esta [apresentação (38:37)](https://www.youtube.com/watch?v=Jes3bD6P0To). 871 | 872 | A organização [nvim-treesitter](https://github.com/nvim-treesitter/) hospeda vários plug-ins aproveitando a biblioteca. 873 | 874 | Veja também: 875 | - `:help lua-treesitter` 876 | 877 | 878 | ### Transpilers 879 | 880 | Uma vantagem de usar Lua é que você não precisa realmente escrever código Lua! Há uma grande variedade de transpiladores disponíveis para o idioma. 881 | 882 | - [Moonscript](https://moonscript.org/) 883 | 884 | Provavelmente um dos transpiladores mais conhecidos para Lua. Adiciona muitos recursos convenientes, como classes, compreensões de lista ou literais de função. O plugin [svermeulen / nvim-moonmaker](https://github.com/svermeulen/nvim-moonmaker) permite que você escreva plugins Neovim e configuração diretamente no Moonscript. 885 | 886 | - [Fennel](https://fennel-lang.org/) 887 | 888 | Um lisp que compila para Lua. Você pode escrever configuração e plug-ins para Neovim no Fennel com o plug-in [Olical / aniseed](https://github.com/Olical/aniseed). Adicionalmente, o plugin [Olical/conjure](https://github.com/Olical/conjure) disponibiliza um ambiente interativo de desenvolvimento que da suporte a Fennel (além de outras linguagens). 889 | 890 | Outros projetos interessantes: 891 | - [TypeScriptToLua/TypeScriptToLua](https://github.com/TypeScriptToLua/TypeScriptToLua) 892 | - [teal-language/tl](https://github.com/teal-language/tl) 893 | - [Haxe](https://haxe.org/) 894 | - [SwadicalRag/wasm2lua](https://github.com/SwadicalRag/wasm2lua) 895 | - [hengestone/lua-languages](https://github.com/hengestone/lua-languages) 896 | -------------------------------------------------------------------------------- /doc/nvim-lua-guide.txt: -------------------------------------------------------------------------------- 1 | *nvim-lua-guide.txt* Getting started using Lua in Neovim 2 | 3 | ============================================================================== 4 | INTRODUCTION 5 | *luaguide-introduction* 6 | 7 | The integration of Lua: https://www.youtube.com/watch?v=IP3J56sKtn0 8 | as a first-class language inside Neovim: 9 | https://github.com/neovim/neovim/wiki/FAQ#why-embed-lua-instead-of-x 10 | is shaping up to be one of its killer features. 11 | However, the amount of teaching material for learning how to write 12 | plugins in Lua is not as large as what you would find for writing them 13 | in Vimscript. This is an attempt at providing some basic information to 14 | get people started. 15 | 16 | This guide assumes you are using at least version 0.5 of Neovim. 17 | 18 | Learning Lua~ 19 | 20 | If you are not already familiar with the language, there are plenty of 21 | resources to get started: 22 | 23 | - The Learn X in Y minutes page about Lua: 24 | https://learnxinyminutes.com/docs/lua/ should give you a quick overview 25 | of the basics 26 | - This guide: 27 | https://github.com/medwatt/Notes/blob/main/Lua/Lua_Quick_Guide.ipynb 28 | is also a good resource for getting started quickly 29 | - If videos are more to your liking, Derek Banas has a 1-hour tutorial 30 | on the language: https://www.youtube.com/watch?v=iMacxZQMPXs 31 | - Want something a little more interactive with runnable examples? Try 32 | the LuaScript tutorial: https://www.luascript.dev/learn 33 | - The lua-users wiki: http://lua-users.org/wiki/LuaDirectory is full 34 | of useful information on all kinds of Lua-related topics 35 | - The official reference manual for Lua: https://www.lua.org/manual/5.1/ 36 | should give you the most comprehensive tour of the language exists as 37 | a Vimdoc plugin if you want to read it from the comfort of your editor: 38 | milisims/nvim-luaref: https://github.com/milisims/nvim-luaref 39 | 40 | It should also be noted that Lua is a very clean and simple language. It 41 | is easy to learn, especially if you have experience with similar scripting 42 | languages like JavaScript. You may already know more Lua than you realise! 43 | 44 | Note: the version of Lua that Neovim embeds is LuaJIT: 45 | https://staff.fnwi.uva.nl/h.vandermeer/docs/lua/luajit/luajit_intro.html 46 | 2.1.0, which maintains compatibility with Lua 5.1. 47 | 48 | Existing tutorials for writing Lua in Neovim~ 49 | 50 | A few tutorials have already been written to help people write plugins 51 | in Lua. Some of them helped quite a bit when writing this guide. Many 52 | thanks to their authors. 53 | 54 | - teukka.tech - From init.vim to init.lua: 55 | https://teukka.tech/luanvim.html 56 | - dev.to - How to write neovim plugins in Lua: 57 | https://dev.to/2nit/how-to-write-neovim-plugins-in-lua-5cca 58 | - dev.to - How to make UI for neovim plugins in Lua: 59 | https://dev.to/2nit/how-to-make-ui-for-neovim-plugins-in-lua-3b6e 60 | - ms-jpq - Neovim Async Tutorial: 61 | https://github.com/ms-jpq/neovim-async-tutorial 62 | - oroques.dev - Neovim 0.5 features and the switch to init.lua: 63 | https://oroques.dev/notes/neovim-init/ 64 | - Building A Vim Statusline from Scratch - jdhao's blog: 65 | https://jdhao.github.io/2019/11/03/vim_custom_statusline/ 66 | - Configuring Neovim using Lua: https://icyphox.sh/blog/nvim-lua/ 67 | - Devlog | Everything you need to know to configure neovim using lua: 68 | https://vonheikemen.github.io/devlog/tools/configuring-neovim-using-lua/ 69 | 70 | Companion plugins~ 71 | 72 | - Vimpeccable: https://github.com/svermeulen/vimpeccable - Plugin to 73 | help write your .vimrc in Lua 74 | - plenary.nvim: https://github.com/nvim-lua/plenary.nvim - All the 75 | lua functions I don't want to write twice 76 | - popup.nvim: https://github.com/nvim-lua/popup.nvim - An implementation 77 | of the Popup API from vim in Neovim 78 | - nvim_utils: https://github.com/norcalli/nvim_utils 79 | - nvim-luadev: https://github.com/bfredl/nvim-luadev - REPL/debug 80 | console for nvim lua plugins 81 | - nvim-luapad: https://github.com/rafcamlet/nvim-luapad - Interactive 82 | real time neovim scratchpad for embedded lua engine 83 | - nlua.nvim: https://github.com/tjdevries/nlua.nvim - Lua Development 84 | for Neovim 85 | - BetterLua.vim: https://github.com/euclidianAce/BetterLua.vim - 86 | Better Lua syntax highlighting in Vim/NeoVim 87 | 88 | ============================================================================== 89 | WHERE TO PUT LUA FILES 90 | *luaguide-where-to-put-lua-files* 91 | 92 | init.lua~ 93 | 94 | Neovim supports loading an `init.lua` file for configuration instead of 95 | the usual `init.vim`. 96 | 97 | Note: `init.lua` is of course _completely_ optional. Support 98 | for `init.vim` is not going away and is still a valid option for 99 | configuration. Do keep in mind that some features are not 100% exposed 100 | to Lua yet. 101 | 102 | See also: 103 | - |config| 104 | 105 | Modules~ 106 | 107 | Lua modules are found inside a `lua/` folder in your `'runtimepath'` 108 | (for most users, this will mean `~/.config/nvim/lua` on \*nix systems 109 | and `~/AppData/Local/nvim/lua` on Windows). You can `require()` files 110 | in this folder as Lua modules. 111 | 112 | Let's take the following folder structure as an example: 113 | 114 | > 115 | 📂 ~/.config/nvim 116 | ├── 📁 after 117 | ├── 📁 ftplugin 118 | ├── 📂 lua 119 | │ ├── 🌑 myluamodule.lua 120 | │ └── 📂 other_modules 121 | │ ├── 🌑 anothermodule.lua 122 | │ └── 🌑 init.lua 123 | ├── 📁 pack 124 | ├── 📁 plugin 125 | ├── 📁 syntax 126 | └── 🇻 init.vim 127 | < 128 | 129 | The following Lua code will load `myluamodule.lua`: 130 | 131 | > 132 | require('myluamodule') 133 | < 134 | 135 | Notice the absence of a `.lua` extension. 136 | 137 | Similarly, loading `other_modules/anothermodule.lua` is done like so: 138 | 139 | > 140 | require('other_modules.anothermodule') 141 | -- or 142 | require('other_modules/anothermodule') 143 | < 144 | 145 | Path separators are denoted by either a dot `.` or a slash `/`. 146 | 147 | A folder containing an `init.lua` file can be required directly, without 148 | having to specify the name of the file. 149 | 150 | > 151 | require('other_modules') -- loads other_modules/init.lua 152 | < 153 | 154 | Requiring a nonexistent module or a module which contains syntax errors 155 | aborts the currently executing script. 156 | `pcall()` may be used to prevent errors. 157 | 158 | > 159 | local ok, _ = pcall(require, 'module_with_error') 160 | if not ok then 161 | -- not loaded 162 | end 163 | < 164 | 165 | See also: 166 | - |lua-require| 167 | 168 | Tips~ 169 | 170 | Several Lua plugins might have identical filenames in their `lua/` 171 | folder. This could lead to namespace clashes. 172 | 173 | If two different plugins have a `lua/main.lua` file, then doing 174 | `require('main')` is ambiguous: which file do we want to source? 175 | 176 | It might be a good idea to namespace your config or your plugin with a 177 | top-level folder, like so: `lua/plugin_name/main.lua` 178 | 179 | Runtime files~ 180 | 181 | Much like Vimscript files, Lua files can be loaded automatically from 182 | special folders in your `runtimepath`. Currently, the following folders 183 | are supported: 184 | 185 | - `colors/` 186 | - `compiler/` 187 | - `ftplugin/` 188 | - `ftdetect/` 189 | - `indent/` 190 | - `plugin/` 191 | - `syntax/` 192 | 193 | Note: in a runtime directory, all `*.vim` files are sourced before 194 | `*.lua` files. 195 | 196 | See also: 197 | - |'runtimepath'| 198 | - |load-plugins| 199 | 200 | Tips~ 201 | 202 | Since runtime files aren't based on the Lua module system, two plugins 203 | can have a `plugin/main.lua` file without it being an issue. 204 | 205 | ============================================================================== 206 | USING LUA FROM VIMSCRIPT 207 | *luaguide-using-lua-from-vimscript* 208 | 209 | :lua~ 210 | 211 | This command executes a chunk of Lua code. 212 | 213 | > 214 | :lua require('myluamodule') 215 | < 216 | 217 | Multi-line scripts are possible using heredoc syntax: 218 | 219 | > 220 | echo "Here's a bigger chunk of Lua code" 221 | 222 | lua << EOF 223 | local mod = require('mymodule') 224 | local tbl = {1, 2, 3} 225 | 226 | for k, v in ipairs(tbl) do 227 | mod.method(v) 228 | end 229 | 230 | print(tbl) 231 | EOF 232 | < 233 | 234 | Note: each `:lua` command has its own scope and variables declared with 235 | the `local` keyword are not accessible outside of the command. This 236 | won't work: 237 | 238 | > 239 | :lua local foo = 1 240 | :lua print(foo) 241 | " prints 'nil' instead of '1' 242 | < 243 | 244 | Note 2: the `print()` function in Lua behaves similarly to the `:echomsg` 245 | command. Its output is saved in the message-history and can be suppressed 246 | by the `:silent` command. 247 | 248 | See also: 249 | 250 | - |:lua| 251 | - |:lua-heredoc| 252 | 253 | :luado~ 254 | 255 | This command executes a chunk of Lua code that acts on a range of lines 256 | in the current buffer. If no range is specified, the whole buffer is 257 | used instead. Whatever string is `return`ed from the chunk is used to 258 | determine what each line should be replaced with. 259 | 260 | The following command would replace every line in the current buffer 261 | with the text `hello world`: 262 | 263 | > 264 | :luado return 'hello world' 265 | < 266 | 267 | Two implicit `line` and `linenr` variables are also provided. `line` 268 | is the text of the line being iterated upon whereas `linenr` is its 269 | number. The following command would make every line whose number is 270 | divisible by 2 uppercase: 271 | 272 | > 273 | :luado if linenr % 2 == 0 then return line:upper() end 274 | < 275 | 276 | See also: 277 | 278 | - |:luado| 279 | 280 | Sourcing Lua files~ 281 | 282 | Neovim provides 3 Ex commands to source Lua files 283 | 284 | - `:luafile` 285 | - `:source` 286 | - `:runtime` 287 | 288 | `:luafile` and `:source` are very similar: 289 | 290 | > 291 | :luafile ~/foo/bar/baz/myluafile.lua 292 | :luafile % 293 | :source ~/foo/bar/baz/myluafile.lua 294 | :source % 295 | < 296 | 297 | `:source` also supports ranges, which can be useful to only execute part 298 | of a script: 299 | 300 | > 301 | :1,10source 302 | < 303 | 304 | `:runtime` is a little different: it uses the `'runtimepath'` option to 305 | determine which files to source. See |:runtime| for more details. 306 | 307 | See also: 308 | 309 | - |:luafile| 310 | - |:source| 311 | - |:runtime| 312 | 313 | Sourcing a lua file vs calling require():~ 314 | 315 | You might be wondering what the difference between calling the `require()` 316 | function and sourcing a Lua file is and whether you should prefer one 317 | way over the other. They have different use cases: 318 | 319 | - `require()`: 320 | - is a built-in Lua function. It allows you to take advantage of 321 | Lua's module system 322 | - searches for modules in `lua/` folders in your `'runtimepath'` 323 | - keeps track of what modules have been loaded and prevents a script 324 | from being parsed and executed a second time. If you change the file 325 | containing the code for a module and try to `require()` it a second 326 | time while Neovim is running, the module will not actually update 327 | - `:luafile`, `:source` and `:runtime`: 328 | - are Ex commands. They do not support modules 329 | - execute the contents of a script regardless of whether it has been 330 | executed before 331 | - `:luafile` and `:source` take a path that is either absolute or 332 | relative to the working directory of the current window 333 | - `:runtime` uses the `'runtimepath'` option to find files 334 | 335 | Files sourced via `:source`, `:runtime` or automatically from runtime 336 | directories will also show up in `:scriptnames` and `--startuptime` 337 | 338 | luaeval()~ 339 | 340 | This built-in Vimscript function evaluates a Lua expression string 341 | and returns its value. Lua data types are automatically converted to 342 | Vimscript types (and vice versa). 343 | 344 | > 345 | " You can store the result in a variable 346 | let variable = luaeval('1 + 1') 347 | echo variable 348 | " 2 349 | let concat = luaeval('"Lua".." is ".."awesome"') 350 | echo concat 351 | " 'Lua is awesome' 352 | 353 | " List-like tables are converted to Vim lists 354 | let list = luaeval('{1, 2, 3, 4}') 355 | echo list[0] 356 | " 1 357 | echo list[1] 358 | " 2 359 | " Note that unlike Lua tables, Vim lists are 0-indexed 360 | 361 | " Dict-like tables are converted to Vim dictionaries 362 | let dict = luaeval('{foo = "bar", baz = "qux"}') 363 | echo dict.foo 364 | " 'bar' 365 | 366 | " Same thing for booleans and nil 367 | echo luaeval('true') 368 | " v:true 369 | echo luaeval('nil') 370 | " v:null 371 | 372 | " You can create Vimscript aliases for Lua functions 373 | let LuaMathPow = luaeval('math.pow') 374 | echo LuaMathPow(2, 2) 375 | " 4 376 | let LuaModuleFunction = luaeval('require("mymodule").myfunction') 377 | call LuaModuleFunction() 378 | 379 | " It is also possible to pass Lua functions as values to Vim functions 380 | lua X = function(k, v) return string.format("%s:%s", k, v) end 381 | echo map([1, 2, 3], luaeval("X")) 382 | < 383 | 384 | `luaeval()` takes an optional second argument that allows you to pass 385 | data to the expression. You can then access that data from Lua using 386 | the magic global `_A`: 387 | 388 | > 389 | echo luaeval('_A[1] + _A[2]', [1, 1]) 390 | " 2 391 | 392 | echo luaeval('string.format("Lua is %s", _A)', 'awesome') 393 | " 'Lua is awesome' 394 | < 395 | 396 | See also: 397 | - |luaeval()| 398 | 399 | v:lua~ 400 | 401 | This global Vim variable allows you to call Lua functions in the global 402 | namespace `_G`: https://www.lua.org/manual/5.1/manual.html#pdf-_G 403 | directly from Vimscript. Again, Vim data types are converted to Lua 404 | types and vice versa. 405 | 406 | > 407 | call v:lua.print('Hello from Lua!') 408 | " 'Hello from Lua!' 409 | 410 | let scream = v:lua.string.rep('A', 10) 411 | echo scream 412 | " 'AAAAAAAAAA' 413 | 414 | " How about a nice statusline? 415 | lua << EOF 416 | function _G.statusline() 417 | local filepath = '%f' 418 | local align_section = '%=' 419 | local percentage_through_file = '%p%%' 420 | return string.format( 421 | '%s%s%s', 422 | filepath, 423 | align_section, 424 | percentage_through_file 425 | ) 426 | end 427 | EOF 428 | 429 | set statusline=%!v:lua.statusline() 430 | 431 | " Also works in expression mappings 432 | lua << EOF 433 | function _G.check_back_space() 434 | local col = vim.api.nvim_win_get_cursor(0)[2] 435 | return (col == 0 or vim.api.nvim_get_current_line():sub(col, 436 | col):match('%s')) and true 437 | end 438 | EOF 439 | 440 | inoremap 441 | \ pumvisible() ? "\" : 442 | \ v:lua.check_back_space() ? "\" : 443 | \ completion#trigger_completion() 444 | 445 | " Call a function from a Lua module by using single quotes and 446 | omitting parentheses: 447 | call v:lua.require'module'.foo() 448 | < 449 | 450 | See also: 451 | - |v:lua| 452 | - |v:lua-call| 453 | 454 | Caveats~ 455 | 456 | This variable can only be used to call functions. The following will 457 | always throw an error: 458 | 459 | > 460 | " Aliasing functions doesn't work 461 | let LuaPrint = v:lua.print 462 | 463 | " Accessing dictionaries doesn't work 464 | echo v:lua.some_global_dict['key'] 465 | 466 | " Using a function as a value doesn't work 467 | echo map([1, 2, 3], v:lua.global_callback) 468 | < 469 | 470 | Tips~ 471 | 472 | You can get Lua syntax highlighting inside .vim files by putting `let 473 | g:vimsyn_embed = 'l'` in your configuration file. See |g:vimsyn_embed| 474 | for more on this option. 475 | 476 | ============================================================================== 477 | THE VIM NAMESPACE 478 | *luaguide-the-vim-namespace* 479 | 480 | Neovim exposes a global `vim` variable which serves as an entry point 481 | to interact with its APIs from Lua. It provides users with an extended 482 | "standard library" of functions as well as various sub-modules. 483 | 484 | Some notable functions and modules include: 485 | 486 | - `vim.inspect`: transform Lua objects into human-readable strings 487 | (useful for inspecting tables) 488 | - `vim.regex`: use Vim regexes from Lua 489 | - `vim.api`: module that exposes API functions (the same API used by 490 | remote plugins) 491 | - `vim.ui`: overridable UI functions that can be leveraged by plugins 492 | - `vim.loop`: module that exposes the functionality of Neovim's event-loop 493 | (using LibUV) 494 | - `vim.lsp`: module that controls the built-in LSP client 495 | - `vim.treesitter`: module that exposes the functionality of the 496 | tree-sitter library 497 | 498 | This list is by no means comprehensive. If you wish to know more about what's 499 | made available by the `vim` variable, |lua-stdlib| and |lua-vim| are the way 500 | to go. Alternatively, you can do `:lua print(vim.inspect(vim))` to get a list 501 | of every module. API functions are documented under |api-global|. 502 | 503 | Tips~ 504 | 505 | Writing `print(vim.inspect(x))` every time you want to inspect the 506 | contents of an object can get pretty tedious. It might be worthwhile 507 | to have a global wrapper function somewhere in your configuration (in 508 | Neovim 0.7.0+, this function is built-in, see |vim.pretty_print()|: 509 | 510 | > 511 | function _G.put(...) 512 | local objects = {} 513 | for i = 1, select('#', ...) do 514 | local v = select(i, ...) 515 | table.insert(objects, vim.inspect(v)) 516 | end 517 | 518 | print(table.concat(objects, '\n')) 519 | return ... 520 | end 521 | < 522 | 523 | You can then inspect the contents of an object very quickly in your code 524 | or from the command-line: 525 | 526 | > 527 | put({1, 2, 3}) 528 | < 529 | 530 | > 531 | :lua put(vim.loop) 532 | < 533 | 534 | Alternatively, you can use the `:lua` command to pretty-print a Lua 535 | expression by prefixing it with `=` (Neovim 0.7+ only): 536 | > 537 | :lua =vim.loop 538 | < 539 | 540 | Additionally, you may find that built-in Lua functions are sometimes 541 | lacking compared to what you would find in other languages (for example 542 | `os.clock()` only returns a value in seconds, not milliseconds). Be 543 | sure to look at the Neovim stdlib (and `vim.fn`, more on that later), 544 | it probably has what you're looking for. 545 | 546 | ============================================================================== 547 | USING VIMSCRIPT FROM LUA 548 | *luaguide-using-vimscript-from-lua* 549 | 550 | vim.api.nvim_eval()~ 551 | 552 | This function evaluates a Vimscript expression string and returns its 553 | value. Vimscript data types are automatically converted to Lua types 554 | (and vice versa). 555 | 556 | It is the Lua equivalent of the `luaeval()` function in Vimscript 557 | 558 | > 559 | -- Data types are converted correctly 560 | print(vim.api.nvim_eval('1 + 1')) -- 2 561 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 562 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) 563 | -- { baz = "qux", foo = "bar" } 564 | print(vim.api.nvim_eval('v:true')) -- true 565 | print(vim.api.nvim_eval('v:null')) -- nil 566 | < 567 | 568 | Caveats~ 569 | 570 | Unlike `luaeval()`, `vim.api.nvim_eval()` does not provide an implicit 571 | `_A` variable to pass data to the expression. 572 | 573 | vim.api.nvim_exec()~ 574 | 575 | This function evaluates a chunk of Vimscript code. It takes in a string 576 | containing the source code to execute and a boolean to determine whether 577 | the output of the code should be returned by the function (you can then 578 | store the output in a variable, for example). 579 | 580 | > 581 | local result = vim.api.nvim_exec( 582 | [[ 583 | let s:mytext = 'hello world' 584 | 585 | function! s:MyFunction(text) 586 | echo a:text 587 | endfunction 588 | 589 | call s:MyFunction(s:mytext) 590 | ]], 591 | true) 592 | 593 | print(result) -- 'hello world' 594 | < 595 | 596 | Caveats~ 597 | 598 | `nvim_exec` does not support script-local variables (`s:`) prior to 599 | Neovim 0.6.0 600 | 601 | vim.api.nvim_command()~ 602 | 603 | This function executes an ex command. It takes in a string containing 604 | the command to execute. 605 | 606 | > 607 | vim.api.nvim_command('new') 608 | vim.api.nvim_command('wincmd H') 609 | vim.api.nvim_command('set nonumber') 610 | vim.api.nvim_command('%s/foo/bar/g') 611 | < 612 | 613 | vim.cmd()~ 614 | 615 | Alias for `vim.api.nvim_exec()`. Only the command argument is needed, 616 | `output` is always set to `false`. 617 | 618 | > 619 | vim.cmd('buffers') 620 | vim.cmd([[ 621 | let g:multiline_list = [ 622 | \ 1, 623 | \ 2, 624 | \ 3, 625 | \ ] 626 | 627 | echo g:multiline_list 628 | ]]) 629 | < 630 | 631 | Tips~ 632 | 633 | Since you have to pass strings to these functions, you often end up 634 | having to escape backslashes: 635 | 636 | > 637 | vim.cmd('%s/\\Vfoo/bar/g') 638 | < 639 | 640 | Double bracketed strings are easier to use as they do not require 641 | escaping characters: 642 | 643 | > 644 | vim.cmd([[%s/\Vfoo/bar/g]]) 645 | < 646 | 647 | vim.api.nvim_replace_termcodes()~ 648 | 649 | This API function allows you to escape terminal codes and Vim keycodes. 650 | 651 | You may have come across mappings like this one: 652 | 653 | > 654 | inoremap pumvisible() ? "\" : "\" 655 | < 656 | 657 | Trying to do the same in Lua can prove to be a challenge. You might be 658 | tempted to do it like this: 659 | 660 | > 661 | function _G.smart_tab() 662 | return vim.fn.pumvisible() == 1 and [[\]] or [[\]] 663 | end 664 | 665 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = 666 | true, noremap = true}) 667 | < 668 | 669 | only to find out that the mapping inserts `\` and `\` 670 | literally... 671 | 672 | Being able to escape keycodes is actually a Vimscript feature. Aside 673 | from the usual escape sequences like `\r`, `\42` or `\x10` that are 674 | common to many programming languages, Vimscript `expr-quotes` (strings 675 | surrounded with double quotes) allow you to escape the human-readable 676 | representation of Vim keycodes. 677 | 678 | Lua doesn't have such a feature built-in. Fortunately, Neovim 679 | has an API function for escaping terminal codes and keycodes: 680 | `nvim_replace_termcodes()` 681 | 682 | > 683 | print(vim.api.nvim_replace_termcodes('', true, true, true)) 684 | < 685 | 686 | This is a little verbose. Making a reusable wrapper can help: 687 | 688 | > 689 | -- The function is called `t` for `termcodes`. 690 | -- You don't have to call it that, but I find the terseness convenient 691 | local function t(str) 692 | -- Adjust boolean arguments as needed 693 | return vim.api.nvim_replace_termcodes(str, true, true, true) 694 | end 695 | 696 | print(t'') 697 | < 698 | 699 | Coming back to our earlier example, this should now work as expected: 700 | 701 | > 702 | local function t(str) 703 | return vim.api.nvim_replace_termcodes(str, true, true, true) 704 | end 705 | 706 | function _G.smart_tab() 707 | return vim.fn.pumvisible() == 1 and t'' or t'' 708 | end 709 | 710 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = 711 | true, noremap = true}) 712 | < 713 | 714 | This is not necessary with `vim.keymap.set()` as it automatically 715 | transforms vim keycodes returned by Lua functions in `expr` mappings 716 | by default: 717 | 718 | > 719 | vim.keymap.set('i', '', function() 720 | return vim.fn.pumvisible() == 1 and '' or '' 721 | end, {expr = true}) 722 | < 723 | 724 | See also: 725 | 726 | - |keycodes| 727 | - |expr-quote| 728 | - |nvim_replace_termcodes()| 729 | 730 | ============================================================================== 731 | MANAGING VIM OPTIONS 732 | *luaguide-managing-vim-options* 733 | 734 | Using api functions~ 735 | 736 | Neovim provides a set of API functions to either set an option or get 737 | its current value: 738 | 739 | - Global options: 740 | - |nvim_set_option()| 741 | - |nvim_get_option()| 742 | - Buffer-local options: 743 | - |nvim_buf_set_option()| 744 | - |nvim_buf_get_option()| 745 | - Window-local options: 746 | - |nvim_win_set_option()| 747 | - |nvim_win_get_option()| 748 | 749 | They take a string containing the name of the option to set/get as well 750 | as the value you want to set it to. 751 | 752 | Boolean options (like `(no)number`) have to be set to either `true` or 753 | `false`: 754 | 755 | > 756 | vim.api.nvim_set_option('smarttab', false) 757 | print(vim.api.nvim_get_option('smarttab')) -- false 758 | < 759 | 760 | Unsurprisingly, string options have to be set to a string: 761 | 762 | > 763 | vim.api.nvim_set_option('selection', 'exclusive') 764 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 765 | < 766 | 767 | Number options accept a number: 768 | 769 | > 770 | vim.api.nvim_set_option('updatetime', 3000) 771 | print(vim.api.nvim_get_option('updatetime')) -- 3000 772 | < 773 | 774 | Buffer-local and window-local options also need a buffer number or 775 | a window number (using `0` will set/get the option for the current 776 | buffer/window): 777 | 778 | > 779 | vim.api.nvim_win_set_option(0, 'number', true) 780 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 781 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 782 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 783 | < 784 | 785 | Using meta-accessors~ 786 | 787 | A few meta-accessors are available if you want to set options in a more 788 | "idiomatic" way. They essentially wrap the above API functions and allow 789 | you to manipulate options as if they were variables: 790 | 791 | - |vim.o|: behaves like `:let &{option-name}` 792 | - |vim.go|: behaves like `:let &g:{option-name}` 793 | - |vim.bo|: behaves like `:let &l:{option-name}` for buffer-local options 794 | - |vim.wo|: behaves like `:let &l:{option-name}` for window-local options 795 | 796 | > 797 | vim.o.smarttab = false -- let &smarttab = v:false 798 | print(vim.o.smarttab) -- false 799 | vim.o.isfname = vim.o.isfname .. ',@-@' -- on Linux: let &isfname = 800 | &isfname .. ',@-@' 801 | print(vim.o.isfname) -- '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@' 802 | 803 | vim.bo.shiftwidth = 4 804 | print(vim.bo.shiftwidth) -- 4 805 | < 806 | 807 | You can specify a number for buffer-local and window-local options. If 808 | no number is given, the current buffer/window is used: 809 | 810 | > 811 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 812 | 'expandtab', true) 813 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 814 | 'number', true) 815 | < 816 | 817 | These wrappers also have more sophisticated `vim.opt*` variants that 818 | provide convenient mechanisms for setting options in Lua. They're similar 819 | to what you might be used to in your `init.vim`: 820 | 821 | - `vim.opt`: behaves like `:set` 822 | - `vim.opt_global`: behaves like `:setglobal` 823 | - `vim.opt_local`: behaves like `:setlocal` 824 | 825 | > 826 | vim.opt.smarttab = false 827 | print(vim.opt.smarttab:get()) -- false 828 | < 829 | 830 | Some options can be set using Lua tables: 831 | 832 | > 833 | vim.opt.completeopt = {'menuone', 'noselect'} 834 | print(vim.inspect(vim.opt.completeopt:get())) -- { "menuone", 835 | "noselect" } 836 | < 837 | 838 | Wrappers for list-like, map-like and set-like options also come with 839 | methods and metamethods that work similarly to their `:set+=`, `:set^=` 840 | and `:set-=` counterparts in Vimscript. 841 | 842 | > 843 | vim.opt.shortmess:append({ I = true }) 844 | -- alternative form: 845 | vim.opt.shortmess = vim.opt.shortmess + { I = true } 846 | 847 | vim.opt.whichwrap:remove({ 'b', 's' }) 848 | -- alternative form: 849 | vim.opt.whichwrap = vim.opt.whichwrap - { 'b', 's' } 850 | < 851 | 852 | Be sure to look at |vim.opt| for more information. 853 | 854 | See also: 855 | - |lua-vim-options| 856 | 857 | ============================================================================== 858 | MANAGING VIM INTERNAL VARIABLES 859 | *luaguide-managing-vim-internal-variables* 860 | 861 | Using api functions~ 862 | 863 | Much like options, internal variables have their own set of API functions: 864 | 865 | - Global variables (`g:`): 866 | - |nvim_set_var()| 867 | - |nvim_get_var()| 868 | - |nvim_del_var()| 869 | - Buffer variables (`b:`): 870 | - |nvim_buf_set_var()| 871 | - |nvim_buf_get_var()| 872 | - |nvim_buf_del_var()| 873 | - Window variables (`w:`): 874 | - |nvim_win_set_var()| 875 | - |nvim_win_get_var()| 876 | - |nvim_win_del_var()| 877 | - Tabpage variables (`t:`): 878 | - |nvim_tabpage_set_var()| 879 | - |nvim_tabpage_get_var()| 880 | - |nvim_tabpage_del_var()| 881 | - Predefined Vim variables (`v:`): 882 | - |nvim_set_vvar()| 883 | - |nvim_get_vvar()| 884 | 885 | With the exception of predefined Vim variables, they can also be deleted 886 | (the `:unlet` command is the equivalent in Vimscript). Local variables 887 | (`l:`), script variables (`s:`) and function arguments (`a:`) cannot 888 | be manipulated as they only make sense in the context of a Vim script, 889 | Lua has its own scoping rules. 890 | 891 | If you are unfamiliar with what these variables do, |internal-variables| 892 | describes them in detail. 893 | 894 | These functions take a string containing the name of the variable to 895 | set/get/delete as well as the value you want to set it to. 896 | 897 | > 898 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 899 | 300 }) 900 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- 901 | { key1 = "value", key2 = 300 } 902 | vim.api.nvim_del_var('some_global_variable') 903 | < 904 | 905 | Variables that are scoped to a buffer, a window or a tabpage also 906 | receive a number (using `0` will set/get/delete the variable for the 907 | current buffer/window/tabpage): 908 | 909 | > 910 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 911 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 912 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 913 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 914 | 'hello world' 915 | vim.api.nvim_win_del_var(0, 'some_window_variable') 916 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 917 | < 918 | 919 | Using meta-accessors~ 920 | 921 | Internal variables can be manipulated more intuitively using these 922 | meta-accessors: 923 | 924 | - |vim.g|: global variables 925 | - |vim.b|: buffer variables 926 | - |vim.w|: window variables 927 | - |vim.t|: tabpage variables 928 | - |vim.v|: predefined Vim variables 929 | - |vim.env|: environment variables 930 | 931 | > 932 | vim.g.some_global_variable = { 933 | key1 = 'value', 934 | key2 = 300 935 | } 936 | 937 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", 938 | key2 = 300 } 939 | 940 | -- target a specific buffer/window/tabpage (Neovim 0.6+) 941 | vim.b[2].myvar = 1 942 | < 943 | 944 | Some variable names may contain characters that cannot be used for 945 | identifiers in Lua. You can still manipulate these variables by using 946 | this syntax: `vim.g['my#variable']`. 947 | 948 | To delete one of these variables, simply assign `nil` to it: 949 | 950 | > 951 | vim.g.some_global_variable = nil 952 | < 953 | 954 | See also: 955 | - |lua-vim-variables| 956 | 957 | Caveats~ 958 | 959 | You cannot add/update/delete keys from a dictionary stored in one of 960 | these variables. For example, this snippet of Vimscript code does not 961 | work as expected: 962 | 963 | > 964 | let g:variable = {} 965 | lua vim.g.variable.key = 'a' 966 | echo g:variable 967 | " {} 968 | < 969 | 970 | You can use a temporary variable as a workaround: 971 | 972 | > 973 | let g:variable = {} 974 | lua << EOF 975 | local tmp = vim.g.variable 976 | tmp.key = 'a' 977 | vim.g.variable = tmp 978 | EOF 979 | echo g:variable 980 | " {'key': 'a'} 981 | < 982 | 983 | This is a known issue: 984 | 985 | - Issue #12544: https://github.com/neovim/neovim/issues/12544 986 | 987 | ============================================================================== 988 | CALLING VIMSCRIPT FUNCTIONS 989 | *luaguide-calling-vimscript-functions* 990 | 991 | vim.fn.{function}()~ 992 | 993 | `vim.fn` can be used to call a Vimscript function. Data types are 994 | converted back and forth from Lua to Vimscript. 995 | 996 | > 997 | print(vim.fn.printf('Hello from %s', 'Lua')) 998 | 999 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 1000 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 1001 | 1002 | local function print_stdout(chan_id, data, name) 1003 | print(data[1]) 1004 | end 1005 | 1006 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 1007 | < 1008 | 1009 | Hashes (`#`) are not valid characters for identifiers in Lua, so autoload 1010 | functions have to be called with this syntax: 1011 | 1012 | > 1013 | vim.fn['my#autoload#function']() 1014 | < 1015 | 1016 | The functionality of `vim.fn` is identical to `vim.call`, but allows a 1017 | more Lua-like syntax. 1018 | 1019 | It is distinct from `vim.api.nvim_call_function` in that converting 1020 | Vim/Lua objects is automatic: `vim.api.nvim_call_function` returns a 1021 | table for floating point numbers and does not accept Lua closures while 1022 | `vim.fn` handles these types transparently. 1023 | 1024 | See also: 1025 | - |vim.fn| 1026 | 1027 | Tips~ 1028 | 1029 | Neovim has an extensive library of powerful built-in functions that are very 1030 | useful for plugins. See |vim-function| for an alphabetical list and 1031 | |function-list| for a list of functions grouped by topic. 1032 | 1033 | Neovim API functions can be used directly through `vim.api.{..}`. See 1034 | |api| for information. 1035 | 1036 | Caveats~ 1037 | 1038 | Some Vim functions that should return a boolean return `1` or `0` 1039 | instead. This isn't a problem in Vimscript as `1` is truthy and `0` 1040 | falsy, enabling constructs like these: 1041 | 1042 | > 1043 | if has('nvim') 1044 | " do something... 1045 | endif 1046 | < 1047 | 1048 | In Lua however, only `false` and `nil` are considered falsy, numbers 1049 | always evaluate to `true` no matter their value. You have to explicitly 1050 | check for `1` or `0`: 1051 | 1052 | > 1053 | if vim.fn.has('nvim') == 1 then 1054 | -- do something... 1055 | end 1056 | < 1057 | 1058 | ============================================================================== 1059 | DEFINING MAPPINGS 1060 | *luaguide-defining-mappings* 1061 | 1062 | API functions~ 1063 | 1064 | Neovim provides a list of API functions to set, get and delete mappings: 1065 | 1066 | - Global mappings: 1067 | - |nvim_set_keymap()| 1068 | - |nvim_get_keymap()| 1069 | - |nvim_del_keymap()| 1070 | - Buffer-local mappings: 1071 | - |nvim_buf_set_keymap()| 1072 | - |nvim_buf_get_keymap()| 1073 | - |nvim_buf_del_keymap()| 1074 | 1075 | Let's start with `vim.api.nvim_set_keymap()` and 1076 | `vim.api.nvim_buf_set_keymap()` 1077 | 1078 | The first argument passed to the function is a string containing the 1079 | name of the mode for which the mapping will take effect: 1080 | 1081 | | String value | Help page | Affected modes | Vimscript equivalent | 1082 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 1083 | | `''` (an empty string) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 1084 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 1085 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 1086 | | `'s'` | `mapmode-s` | Select | `:smap` | 1087 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 1088 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 1089 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 1090 | | `'i'` | `mapmode-i` | Insert | `:imap` | 1091 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 1092 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 1093 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 1094 | 1095 | The second argument is a string containing the left-hand side of the 1096 | mapping (the key or set of keys that trigger the command defined in the 1097 | mapping). An empty string is equivalent to ``, which disables a key. 1098 | 1099 | The third argument is a string containing the right-hand side of the 1100 | mapping (the command to execute). 1101 | 1102 | The final argument is a table containing boolean options for the mapping 1103 | as defined in |:map-arguments|. Since Neovim 0.7.0, you can also pass a 1104 | `callback` option to invoke a Lua function instead of the right-hand 1105 | side when executing the mapping. 1106 | 1107 | Buffer-local mappings also take a buffer number as their first argument 1108 | (`0` sets the mapping for the current buffer). 1109 | 1110 | > 1111 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', 1112 | { noremap = true, silent = true }) 1113 | -- :nnoremap :set hlsearch 1114 | vim.api.nvim_set_keymap('n', 'tegf', [[lua 1115 | require('telescope.builtin').git_files()]], { noremap = true, 1116 | silent = true }) 1117 | -- :nnoremap tegf lua 1118 | require('telescope.builtin').git_files() 1119 | 1120 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : 1121 | "ggcc"', { noremap = true, expr = true }) 1122 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 1123 | 1124 | vim.api.nvim_set_keymap('n', 'ex', '', { 1125 | noremap = true, 1126 | callback = function() 1127 | print('My example') 1128 | end, 1129 | -- Since Lua function don't have a useful string representation, 1130 | you can use the "desc" option to document your mapping 1131 | desc = 'Prints "My example" in the message area', 1132 | }) 1133 | < 1134 | 1135 | `vim.api.nvim_get_keymap()` takes a string containing the shortname of 1136 | the mode for which you want the list of mappings (see table above). The 1137 | return value is a table containing all global mappings for the mode. 1138 | 1139 | > 1140 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 1141 | -- :verbose nmap 1142 | < 1143 | 1144 | `vim.api.nvim_buf_get_keymap()` takes an additional buffer number as 1145 | its first argument (`0` will get mapppings for the current bufffer) 1146 | 1147 | > 1148 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 1149 | -- :verbose imap 1150 | < 1151 | 1152 | `vim.api.nvim_del_keymap()` takes a mode and the left-hand side of 1153 | a mapping. 1154 | 1155 | > 1156 | vim.api.nvim_del_keymap('n', '') 1157 | -- :nunmap 1158 | < 1159 | 1160 | Again, `vim.api.nvim_buf_del_keymap()`, takes a buffer number as its 1161 | first argument, with `0` representing the current buffer. 1162 | 1163 | > 1164 | vim.api.nvim_buf_del_keymap(0, 'i', '') 1165 | -- :iunmap 1166 | < 1167 | 1168 | vim.keymap~ 1169 | 1170 | WARNING: The functions discussed in this section are only available in 1171 | Neovim 0.7.0+ 1172 | 1173 | Neovim provides two functions to set/del mappings: 1174 | - |vim.keymap.set()| 1175 | - |vim.keymap.del()| 1176 | 1177 | These are similar to the above API functions with added syntactic sugar. 1178 | 1179 | `vim.keymap.set()` takes a string as its first argument. It can also be 1180 | a table of strings to define mappings for multiple modes at once: 1181 | 1182 | > 1183 | vim.keymap.set('n', 'ex1', 'lua vim.notify("Example 1184 | 1")') 1185 | vim.keymap.set({'n', 'c'}, 'ex2', 'lua 1186 | vim.notify("Example 2")') 1187 | < 1188 | 1189 | The second argument is the left-hand side of the mapping. 1190 | 1191 | The third argument is the right-hand side of the mapping, which can 1192 | either be a string or a Lua function: 1193 | 1194 | > 1195 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"') 1196 | vim.keymap.set('n', 'ex2', function() print("Example 2") end) 1197 | vim.keymap.set('n', 'pl1', require('plugin').plugin_action) 1198 | -- To avoid the startup cost of requiring the module, you can wrap 1199 | it in a function to require it lazily when invoking the mapping: 1200 | vim.keymap.set('n', 'pl2', function() 1201 | require('plugin').plugin_action() end) 1202 | < 1203 | 1204 | The fourth (optional) argument is a table of options that correspond to 1205 | the options passed to `vim.api.nvim_set_keymap()`, with a few additions 1206 | (see |vim.keymap.set()|. 1207 | 1208 | > 1209 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"', 1210 | {buffer = true}) 1211 | vim.keymap.set('n', 'ex2', function() print('Example 2') 1212 | end, {desc = 'Prints "Example 2" to the message area'}) 1213 | < 1214 | 1215 | Defining keymaps with a Lua function is different from using a string. The 1216 | usual way to show information about a keymap like `:nmap ex1` 1217 | will not output useful information (the string itself), but instead 1218 | only show `Lua function`. It is recommended to add a `desc` key to 1219 | describe the behavior of your keymap. This is especially important for 1220 | documenting plugin mappings so users can understand the usage of the 1221 | keymap more easily. 1222 | 1223 | An interesting feature of this API is that it irons out some historical 1224 | quirks of Vim mappings: 1225 | - Mappings are `noremap` by default, except when the `rhs` is a `` 1226 | mapping. This means you rarely have to think about whether a mapping 1227 | should be recursive or not: 1228 | ```lua 1229 | vim.keymap.set('n', 'test1', 'echo "test"') 1230 | -- :nnoremap test echo "test" 1231 | 1232 | -- If you DO want the mapping to be recursive, set the "remap" 1233 | option to "true" 1234 | vim.keymap.set('n', '>', ']', {remap = true}) 1235 | -- :nmap > ] 1236 | 1237 | -- mappings don't work unless they're recursive, 1238 | vim.keymap.set() handles that for you automatically 1239 | vim.keymap.set('n', 'plug', '(plugin)') 1240 | -- :nmap plug (plugin) 1241 | ``` 1242 | - In `expr` mappings, `nvim_replace_termcodes()` is automatically applied 1243 | to strings returned from Lua functions: 1244 | ```lua 1245 | vim.keymap.set('i', '', function() 1246 | return vim.fn.pumvisible == 1 and '' or '' 1247 | end, {expr = true}) 1248 | ``` 1249 | 1250 | See also: 1251 | - |recursive_mapping| 1252 | 1253 | `vim.keymap.del()` works the same way but deletes mappings instead: 1254 | 1255 | > 1256 | vim.keymap.del('n', 'ex1') 1257 | vim.keymap.del({'n', 'c'}, 'ex2', {buffer = true}) 1258 | < 1259 | 1260 | ============================================================================== 1261 | DEFINING USER COMMANDS 1262 | *luaguide-defining-user-commands* 1263 | 1264 | WARNING: The API functions discussed in this section are only available 1265 | in Neovim 0.7.0+ 1266 | 1267 | Neovim provides API functions for user-defined commands: 1268 | 1269 | - Global user commands: 1270 | - |nvim_create_user_command()| 1271 | - |nvim_del_user_command()| 1272 | - Buffer-local user commands: 1273 | - |nvim_buf_create_user_command()| 1274 | - |nvim_buf_del_user_command()| 1275 | 1276 | Let's start with `vim.api.nvim_create_user_command()` 1277 | 1278 | The first argument passed to this function is the name of the command 1279 | (which must start with an uppercase letter). 1280 | 1281 | The second argument is the code to execute when invoking said command. It 1282 | can either be: 1283 | 1284 | A string (in which case it will be executed as Vimscript). You can use 1285 | escape sequences like ``, ``, etc. like you would with 1286 | `:command` 1287 | > 1288 | vim.api.nvim_create_user_command('Upper', 'echo toupper()', 1289 | { nargs = 1 }) 1290 | -- :command! -nargs=1 Upper echo toupper() 1291 | 1292 | vim.cmd('Upper hello world') -- prints "HELLO WORLD" 1293 | < 1294 | 1295 | Or a Lua function. It receives a dictionary-like table that 1296 | contains the data normally provided by escape sequences (see 1297 | |nvim_create_user_command()| 1298 | > 1299 | vim.api.nvim_create_user_command( 1300 | 'Upper', 1301 | function(opts) 1302 | print(string.upper(opts.args)) 1303 | end, 1304 | { nargs = 1 } 1305 | ) 1306 | < 1307 | 1308 | The third argument lets you pass command attributes as a table (see 1309 | |command-attributes|`. Since you can already define buffer-local user commands 1310 | with |nvim_buf_create_user_command()|, `-buffer` is not a valid attribute. 1311 | 1312 | Two additional attributes are available: 1313 | - `desc` allows you to control what gets displayed when you run `:command 1314 | {cmd}` on a command defined as a Lua callback. Similarly to keymaps, it 1315 | is recommended to add a `desc` key to commands defined as Lua functions. 1316 | - `force` is equivalent to calling `:command!` and replaces a command 1317 | if one with the same name already exists. It is true by default, unlike 1318 | its Vimscript equivalent. 1319 | 1320 | The `-complete` attribute can take a Lua function in addition to the 1321 | attributes listed in |:command-complete|. 1322 | 1323 | > 1324 | vim.api.nvim_create_user_command('Upper', function() end, { 1325 | nargs = 1, 1326 | complete = function(ArgLead, CmdLine, CursorPos) 1327 | -- return completion candidates as a list-like table 1328 | return { 'foo', 'bar', 'baz' } 1329 | end, 1330 | }) 1331 | < 1332 | 1333 | Buffer-local user commands also take a buffer number as their first 1334 | argument. This is an advantage over `-buffer` which can only define a 1335 | command for the current buffer. 1336 | 1337 | > 1338 | vim.api.nvim_buf_create_user_command(4, 'Upper', function() end, {}) 1339 | < 1340 | 1341 | `vim.api.nvim_del_user_command()` takes a command name. 1342 | 1343 | > 1344 | vim.api.nvim_del_user_command('Upper') 1345 | -- :delcommand Upper 1346 | < 1347 | 1348 | Again, `vim.api.nvim_buf_del_user_command()`, takes a buffer number as 1349 | its first argument, with `0` representing the current buffer. 1350 | 1351 | > 1352 | vim.api.nvim_buf_del_user_command(4, 'Upper') 1353 | < 1354 | 1355 | See also: 1356 | - |nvim_create_user_command()| 1357 | - |40.2| 1358 | - |command-attributes| 1359 | 1360 | Caveats~ 1361 | 1362 | The `-complete=custom` attribute automatically filters completion 1363 | candidates and has built-in wildcard (|wildcard| support: 1364 | 1365 | > 1366 | function! s:completion_function(ArgLead, CmdLine, CursorPos) abort 1367 | return join([ 1368 | \ 'strawberry', 1369 | \ 'star', 1370 | \ 'stellar', 1371 | \ ], "\n") 1372 | endfunction 1373 | 1374 | command! -nargs=1 -complete=custom,s:completion_function Test echo 1375 | 1376 | " Typing `:Test st[ae]` returns "star" and "stellar" 1377 | < 1378 | 1379 | Passing a Lua function to `complete` makes it behave like `customlist` 1380 | which leaves filtering up to the user: 1381 | 1382 | > 1383 | vim.api.nvim_create_user_command('Test', function() end, { 1384 | nargs = 1, 1385 | complete = function(ArgLead, CmdLine, CursorPos) 1386 | return { 1387 | 'strawberry', 1388 | 'star', 1389 | 'stellar', 1390 | } 1391 | end, 1392 | }) 1393 | 1394 | -- Typing `:Test z` returns all the completion results because 1395 | the list was not filtered 1396 | < 1397 | 1398 | ============================================================================== 1399 | DEFINING AUTOCOMMANDS 1400 | *luaguide-defining-autocommands* 1401 | 1402 | (this section is a work in progress) 1403 | 1404 | Neovim 0.7.0 has API functions for autocommands. See `:help api-autocmd` 1405 | for details 1406 | 1407 | - Pull request #14661: https://github.com/neovim/neovim/pull/14661 lua: 1408 | autocmds take 2 1409 | 1410 | ============================================================================== 1411 | DEFINING HIGHLIGHTS 1412 | *luaguide-defining-highlights* 1413 | 1414 | (this section is a work in progress) 1415 | 1416 | Neovim 0.7.0 has API functions for highlight groups. See also: 1417 | 1418 | - |nvim_set_hl()| 1419 | - |nvim_get_hl_by_id()| 1420 | - |nvim_get_hl_by_name()| 1421 | 1422 | ============================================================================== 1423 | GENERAL TIPS AND RECOMMENDATIONS 1424 | *luaguide-general-tips-and-recommendations* 1425 | 1426 | Reloading cached modules~ 1427 | 1428 | In Lua, the `require()` function caches modules. This is a good thing 1429 | for performance, but it can make working on plugins a bit cumbersome 1430 | because modules are not updated on subsequent `require()` calls. 1431 | 1432 | If you'd like to refresh the cache for a particular module, you have to 1433 | modify the `package.loaded` global table: 1434 | 1435 | > 1436 | package.loaded['modname'] = nil 1437 | require('modname') -- loads an updated version of module 'modname' 1438 | < 1439 | 1440 | The nvim-lua/plenary.nvim: 1441 | https://github.com/nvim-lua/plenary.nvim plugin has a custom function: 1442 | https://github.com/nvim-lua/plenary.nvim/blob/master/lua/plenary/reload.lua 1443 | that does this for you. 1444 | 1445 | Don't pad Lua strings!~ 1446 | 1447 | When using double bracketed strings, resist the temptation to pad 1448 | them! While it is fine to do in contexts where spaces are ignored, 1449 | it can cause hard to debug issues when whitespace is significant: 1450 | 1451 | > 1452 | vim.api.nvim_set_keymap('n', 'f', [[ call foo() 1453 | ]], {noremap = true}) 1454 | < 1455 | 1456 | In the above example, `f` is mapped to `call 1457 | foo()` instead of `call foo()`. 1458 | 1459 | Notes about Vimscript <-> Lua type conversion~ 1460 | 1461 | Converting a variable creates a copy:~ 1462 | You can't directly interact with the reference to a Vim object from Lua 1463 | or a Lua object from Vimscript. 1464 | For example, the `map()` function in Vimscript modifies a variable 1465 | in place: 1466 | 1467 | > 1468 | let s:list = [1, 2, 3] 1469 | let s:newlist = map(s:list, {_, v -> v * 2}) 1470 | 1471 | echo s:list 1472 | " [2, 4, 6] 1473 | echo s:newlist 1474 | " [2, 4, 6] 1475 | echo s:list is# s:newlist 1476 | " 1 1477 | < 1478 | 1479 | Using this function from Lua creates a copy instead: 1480 | 1481 | > 1482 | local tbl = {1, 2, 3} 1483 | local newtbl = vim.fn.map(tbl, function(_, v) return v * 2 end) 1484 | 1485 | print(vim.inspect(tbl)) -- { 1, 2, 3 } 1486 | print(vim.inspect(newtbl)) -- { 2, 4, 6 } 1487 | print(tbl == newtbl) -- false 1488 | < 1489 | 1490 | Conversion is not always possible~ 1491 | This mostly affects functions and tables: 1492 | 1493 | Lua tables that are a mix between a List and a Dictionary can't be 1494 | converted: 1495 | 1496 | > 1497 | print(vim.fn.count({1, 1, number = 1}, 1)) 1498 | -- E5100: Cannot convert given lua table: table should either have 1499 | a sequence of positive integer keys or contain only string keys 1500 | < 1501 | 1502 | While you can call Vim functions in Lua with `vim.fn`, you can't hold 1503 | references to them. This can cause surprising behaviors: 1504 | 1505 | > 1506 | local FugitiveHead = vim.fn.funcref('FugitiveHead') 1507 | print(FugitiveHead) -- vim.NIL 1508 | 1509 | vim.cmd("let g:test_dict = {'test_lambda': {-> 1}}") 1510 | print(vim.g.test_dict.test_lambda) -- nil 1511 | print(vim.inspect(vim.g.test_dict)) -- {} 1512 | < 1513 | 1514 | Passing Lua functions to Vim functions is OK, storing them in Vim 1515 | variables is not (fixed in Neovim 0.7.0+): 1516 | 1517 | > 1518 | -- This works: 1519 | vim.fn.jobstart({'ls'}, { 1520 | on_stdout = function(chan_id, data, name) 1521 | print(vim.inspect(data)) 1522 | end 1523 | }) 1524 | 1525 | -- This doesn't: 1526 | vim.g.test_dict = {test_lambda = function() return 1 end} -- Error: 1527 | Cannot convert given lua type 1528 | < 1529 | 1530 | Note however that doing the same from Vimscript with `luaeval()` 1531 | **does** work: 1532 | 1533 | > 1534 | let g:test_dict = {'test_lambda': luaeval('function() return 1 end')} 1535 | echo g:test_dict 1536 | " {'test_lambda': function('4714')} 1537 | < 1538 | 1539 | Vim booleans~ 1540 | A common pattern in Vim scripts is to use `1` or `0` instead of proper 1541 | booleans. Indeed, Vim did not have a separate boolean type until version 1542 | 7.4.1154. 1543 | 1544 | Lua booleans are converted to actual booleans in Vimscript, not numbers: 1545 | 1546 | > 1547 | lua vim.g.lua_true = true 1548 | echo g:lua_true 1549 | " v:true 1550 | lua vim.g.lua_false = false 1551 | echo g:lua_false 1552 | " v:false 1553 | < 1554 | 1555 | Setting up linters/language servers~ 1556 | 1557 | If you're using linters and/or language servers to get diagnostics and 1558 | autocompletion for Lua projects, you may have to configure Neovim-specific 1559 | settings for them. Here are a few recommended settings for popular tools: 1560 | 1561 | luacheck~ 1562 | 1563 | You can get luacheck: https://github.com/mpeterv/luacheck/ to recognize 1564 | the `vim` global by putting this configuration in `~/.luacheckrc` or 1565 | `$XDG_CONFIG_HOME/luacheck/.luacheckrc` : 1566 | 1567 | > 1568 | globals = { 1569 | "vim", 1570 | } 1571 | < 1572 | 1573 | The Alloyed/lua-lsp: https://github.com/Alloyed/lua-lsp/ language 1574 | server uses `luacheck` to provide linting and reads the same file. 1575 | 1576 | For more information on how to configure `luacheck`, please refer to 1577 | its documentation: https://luacheck.readthedocs.io/en/stable/config.html 1578 | 1579 | sumneko/lua-language-server~ 1580 | 1581 | The nvim-lspconfig: https://github.com/neovim/nvim-lspconfig/ repository 1582 | contains instructions to configure sumneko/lua-language-server: 1583 | https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#sumneko_lua 1584 | the example uses the built-in LSP client but the configuration should 1585 | be identical for other LSP client implementations . 1586 | 1587 | For more information on how to configure sumneko/lua-language-server: 1588 | https://github.com/sumneko/lua-language-server/ see "Setting": 1589 | https://github.com/sumneko/lua-language-server/wiki/Setting 1590 | 1591 | coc.nvim~ 1592 | 1593 | The rafcamlet/coc-nvim-lua: https://github.com/rafcamlet/coc-nvim-lua/ 1594 | completion source for coc.nvim: https://github.com/neoclide/coc.nvim/ 1595 | provides completion items for the Neovim stdlib. 1596 | 1597 | Debugging Lua code~ 1598 | 1599 | You can debug Lua code running in a separate Neovim 1600 | instance with jbyuki/one-small-step-for-vimkind: 1601 | https://github.com/jbyuki/one-small-step-for-vimkind 1602 | 1603 | The plugin uses the Debug Adapter Protocol: 1604 | https://microsoft.github.io/debug-adapter-protocol/ . Connecting to 1605 | a debug adapter requires a DAP client like mfussenegger/nvim-dap: 1606 | https://github.com/mfussenegger/nvim-dap/ or puremourning/vimspector: 1607 | https://github.com/puremourning/vimspector/ . 1608 | 1609 | Debugging Lua mappings/commands/autocommands~ 1610 | 1611 | The `:verbose` command allows you to see where a 1612 | mapping/command/autocommand was defined: 1613 | 1614 | > 1615 | :verbose map m 1616 | < 1617 | 1618 | > 1619 | n m_ * echo 'example' 1620 | Last set from ~/.config/nvim/init.vim line 26 1621 | < 1622 | 1623 | By default, this feature is disabled in Lua for performance reasons. You 1624 | can enable it by starting Neovim with a verbose level greater than 0: 1625 | 1626 | > 1627 | nvim -V1 1628 | < 1629 | 1630 | See also: 1631 | - |'verbose'| 1632 | - |-V| 1633 | - neovim/neovim#15079: https://github.com/neovim/neovim/pull/15079 1634 | 1635 | Testing Lua code~ 1636 | 1637 | - plenary.nvim: test harness: 1638 | https://github.com/nvim-lua/plenary.nvim/#plenarytest_harness 1639 | - notomo/vusted: https://github.com/notomo/vusted 1640 | 1641 | Using Luarocks packages~ 1642 | 1643 | wbthomason/packer.nvim: https://github.com/wbthomason/packer.nvim 1644 | supports Luarocks packages. Instructions for 1645 | how to set this up are available in the README: 1646 | https://github.com/wbthomason/packer.nvim/#luarocks-support 1647 | 1648 | ============================================================================== 1649 | MISCELLANEOUS 1650 | *luaguide-miscellaneous* 1651 | 1652 | vim.loop~ 1653 | 1654 | `vim.loop` is the module that exposes the LibUV API. Some resources: 1655 | 1656 | - Official documentation for LibUV: https://docs.libuv.org/en/v1.x/ 1657 | - Luv documentation: https://github.com/luvit/luv/blob/master/docs.md 1658 | - teukka.tech - Using LibUV in Neovim: 1659 | https://teukka.tech/posts/2020-01-07-vimloop/ 1660 | 1661 | See also: 1662 | - |vim.loop| 1663 | 1664 | vim.lsp~ 1665 | 1666 | `vim.lsp` is the module that controls the built-in LSP client. The 1667 | neovim/nvim-lspconfig: https://github.com/neovim/nvim-lspconfig/ 1668 | repository contains default configurations for popular language servers. 1669 | 1670 | The behavior of the client can be configured using "lsp-handlers". For 1671 | more information: 1672 | - |lsp-handler| 1673 | - neovim/neovim#12655: https://github.com/neovim/neovim/pull/12655 1674 | - How to migrate from diagnostic-nvim: 1675 | https://github.com/nvim-lua/diagnostic-nvim/issues/73#issue-737897078 1676 | 1677 | You may also want to take a look at plugins built around the LSP client: 1678 | https://github.com/rockerBOO/awesome-neovim#lsp 1679 | 1680 | See also: 1681 | - |lsp| 1682 | 1683 | vim.treesitter~ 1684 | 1685 | `vim.treesitter` is the module that controls the integration of the 1686 | Tree-sitter: https://tree-sitter.github.io/tree-sitter/ library in 1687 | Neovim. If you want to know more about Tree-sitter, you may be interested 1688 | in this presentation 38:37 : https://www.youtube.com/watch?v=Jes3bD6P0To 1689 | . 1690 | 1691 | The nvim-treesitter: https://github.com/nvim-treesitter/ organisation 1692 | hosts various plugins taking advantage of the library. 1693 | 1694 | See also: 1695 | - |lua-treesitter| 1696 | 1697 | Transpilers~ 1698 | 1699 | One advantage of using Lua is that you don't actually have to write Lua 1700 | code! There is a multitude of transpilers available for the language. 1701 | 1702 | - Moonscript: https://moonscript.org/ 1703 | 1704 | Probably one of the most well-known transpilers for 1705 | Lua. Adds a lots of convenient features like classes, list 1706 | comprehensions or function literals. The svermeulen/nvim-moonmaker: 1707 | https://github.com/svermeulen/nvim-moonmaker plugin allows you to write 1708 | Neovim plugins and configuration directly in Moonscript. 1709 | 1710 | - Fennel: https://fennel-lang.org/ 1711 | 1712 | A lisp that compiles to Lua. You can write configuration 1713 | and plugins for Neovim in Fennel with the Olical/aniseed: 1714 | https://github.com/Olical/aniseed or the Hotpot: 1715 | https://github.com/rktjmp/hotpot.nvim plugin. Additionally, the 1716 | Olical/conjure: https://github.com/Olical/conjure plugin provides an 1717 | interactive development environment that supports Fennel among other 1718 | languages . 1719 | 1720 | - Teal: https://github.com/teal-language/tl 1721 | 1722 | The name Teal comes from pronouncing TL typed lua . This is exactly 1723 | what it tries to do - add strong typing to lua while otherwise 1724 | remaining close to standard lua syntax. The nvim-teal-maker: 1725 | https://github.com/svermeulen/nvim-teal-maker plugin can be used to 1726 | write Neovim plugins or configuration files directly in Teal 1727 | 1728 | Other interesting projects: 1729 | - TypeScriptToLua/TypeScriptToLua: 1730 | https://github.com/TypeScriptToLua/TypeScriptToLua 1731 | - Haxe: https://haxe.org/ 1732 | - SwadicalRag/wasm2lua: https://github.com/SwadicalRag/wasm2lua 1733 | - hengestone/lua-languages: https://github.com/hengestone/lua-languages 1734 | 1735 | vim:tw=78:ts=8:noet:ft=help:norl: 1736 | -------------------------------------------------------------------------------- /scripts/docgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | SCRIPT_ROOT="$(dirname "$0")" 4 | 5 | "$SCRIPT_ROOT"/to_vimdoc.sed "$SCRIPT_ROOT"/../README.md | fmt -s | "$SCRIPT_ROOT"/sections_tags.awk > "$SCRIPT_ROOT"/../doc/nvim-lua-guide.txt 6 | -------------------------------------------------------------------------------- /scripts/sections_tags.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | { 3 | if (lastline ~ /^=+$/) { 4 | tag = tolower($0) 5 | gsub(/[^A-Za-z]/, "-", tag) 6 | print $0 7 | printf("%80s", "*" "luaguide-" tag "*") 8 | print "" 9 | } 10 | else { 11 | print 12 | } 13 | } 14 | 15 | { lastline = $0 } 16 | -------------------------------------------------------------------------------- /scripts/to_vimdoc.sed: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | 3 | # Title 4 | /^# / { 5 | s/# /*nvim-lua-guide.txt* / 6 | } 7 | 8 | # Sections 9 | /^## / { 10 | s/[a-z]/\u&/g 11 | s/## // 12 | i============================================================================== 13 | } 14 | 15 | # Sub-sections, tips and caveats 16 | /^####\? / { 17 | s/####\? // 18 | s/.*/&~/ 19 | } 20 | 21 | # Help links 22 | s/\[`vim\.api\.\(.*\)`\](.*)/|\1|/ 23 | s/\[`:help \(.*\)`\](.*)/|\1|/ 24 | s/\[`\(.*\)`\](.*)/|\1|/ 25 | 26 | # Markdown links 27 | /\[.*\](http.*)/ { 28 | y/[]()/ : / 29 | } 30 | 31 | # Todos 32 | s/\*\*TODO\*\*: /\t*Todo\t/g 33 | 34 | # Warnings 35 | s/\*\*\(WARNING\)\*\*/\1/ 36 | 37 | # Code blocks 38 | /^```.*$/,/^```$/{ 39 | s/.*/ &/ 40 | s/```.\+/>/ 41 | s/\s*```$/