1

I'm trying to understand how can I use Lua to extend Neovim, following a baby steps approach. Something like:

-- ~/.config/nvim/lua/test.lua

local api = vim.api
local firstmodule = {}

function firstmodule.hello_world()
  api.nvim_command('echo "hello world"')
end

return firstmodule

Then in my init.vim I import the module to a command:

command! Greet lua require 'test'.hello_world()

And I get a command :Greet that prints hello world.


So far so good, but how can I get/use a string returned by a lua function, let's say:

function firstmodule.hello_string()
  return 'hello world'
end

I try to call this function in my init.vim:

let g:Myvar = v:lua.test.hello_string()

When I source the file, I get the errors:

E121: Undefined variable: v:lua
E15: Invalid expression: v:lua.test.hello_string()

How can I use that string returned by a lua function, let's say in my statusline?

  • You're getting E121: Undefined variable: v:lua... Are you sure you're using NeoVim and not Vim? It seems v:lua is a NeoVim specific interface not present in Vim... – filbranden May 2 at 15:09
  • Please don't post answers in questions. If an answer solved your problem, mark it accepted (as you did). If you have an answer to share, add it as an answer. – D. Ben Knoble May 2 at 18:28
  • Sorry, wasn't familiar with the procedure. Will do. – Bobby Wan-Kenobi May 2 at 19:30
  • Hmm, so I can accept an answer, and add another one myself(not the accepted one), just to clarify and do a bit of cleanup? – Bobby Wan-Kenobi May 2 at 19:34
  • IMO, if you're clarifying something the better approach is to edit the answer...IF you have the rep to do so. If you don't then asking the answer's author in a comment to add that information is probably a good choice. A new answer should be reserved for a different approach altogether. – B Layer May 3 at 2:15
1

The v:lua interface was only introduced to NeoVim in PR #11338, which has a milestone of 0.5, so it looks like it's not generally available in released versions of NeoVim just yet. (NeoVim 0.5 is still in Beta as of early May 2020.)

You should use the luaeval() Vimscript function to evaluate a Lua expression (such as a function call) and use the returned value back in Vimscript.

In your case, it seems to me this should work:

let g:Myvar = luaeval('require("test").hello_string()')

Inside 'statusline', you can use %{...} to evaluate a Vim expression, which could be a global variable such as g:Myvar or even a luaeval(...) function call. Just keep in mind that 'statusline' is evaluated quite often, so the overhead of using a Lua function call from there might become quite noticeable and produce lag while editing.

A solution that uses some caching should be used to avoid that, either a Vim global variable updated from an autocmd (such as CursorHold, CursorMoved, CursorMovedI, SafeState, etc.) or a Vim function that evaluates whether conditions changed and require a new call to the Lua code or not.

| improve this answer | |
  • I get: E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: attempt to index global 'test' (a nil value) – Bobby Wan-Kenobi May 2 at 14:55
  • 1
    @BobbyWan-Kenobi Updated. My answer is still a bit incomplete... I'm looking at it from the Vim (not NeoVim) point of view... But hopefully this unblocks you? – filbranden May 2 at 14:56
  • 1
    Yes, no errors now. I should be able to reference that variable with set statusline+=\ &Myvar no? – Bobby Wan-Kenobi May 2 at 15:13
  • 1
    @BobbyWan-Kenobi Syntax for statusline is %{...} with a Vim expression inside, so set statusline=%{Myvar}. Or let &statusline = Myvar to set statusline as a string... – filbranden May 2 at 15:22
  • 1
    I guess one thing is you can try :help v:lua to see if your documentation for NeoVim mentions it or not... – filbranden May 2 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.