4

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?

5
  • 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, 2020 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, 2020 at 18:28
  • Sorry, wasn't familiar with the procedure. Will do. May 2, 2020 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? May 2, 2020 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, 2020 at 2:15

1 Answer 1

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.

14
  • I get: E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: attempt to index global 'test' (a nil value) May 2, 2020 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, 2020 at 14:56
  • 1
    Yes, no errors now. I should be able to reference that variable with set statusline+=\ &Myvar no? May 2, 2020 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, 2020 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, 2020 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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