Welcome to Vifm Q&A, where you can ask questions about using Vifm. Registration is optional, anonymous posts are moderated. E-mail and GitHub logins are enabled.
0 votes
in vifm by

Thanks for the Lua plugin support. I've experimented a bit and have a couple of questions about the Lua API.

I'm new to Lua, so some questions might be obvious. I've read https://wiki.vifm.info/index.php/Using_Lua_plugins and skimmed over :help vifm-lua.

1) Is the Lua API the only way to add a description to a key binding? As a workaround, I've been creating commands like command! RootEditFile :!sudo $EDITOR %f and then adding a key binding to that command nnoremap <Space>r :RootEditFile<CR>, but description = "edit file as root" is definitely a nicer way.

2) According to the help file: "Builtin print() function puts messages to plugin's log (see |vifm-:plugins| menu)." Where can I view these logs? Running :plugins just shows a list of plugins. I've been using vifm.sb.info('...') instead for logging, but that isn't ideal.

3) Is there something built-in to pretty-print tables? In Neovim you can do :lua print( vim.inspect( tbl ) ).

4) A helper function like the following can pretty-print tables:

local function print_table(tbl, indent)
  indent = indent or 0
  local formatting = string.rep("  ", indent)
  for key, value in pairs(tbl) do
    local keyStr = tostring(key)
    if type(value) == "table" then
      vifm.sb.info(formatting .. keyStr .. " = {")
      print_table(value, indent + 1)
      vifm.sb.info(formatting .. "}")
    else
      vifm.sb.info(formatting .. keyStr .. " = " .. tostring(value))
    end
  end
end

How would one print, for example, vifm.currview(), which is of type Vifmview? I've also encountered the type userdata.

5) I expected there would be something like vim.cmd() in Neovim, but if I understand correctly, it's impossible to call a built-in command like :messages or :normal! j from the Lua API? For the latter, there's an alternative (local c = vifm.currview().cursor; c.pos = c.pos + 1), but for the former, there isn't?

6) There isn't a way to run Lua from the Vifm command-line either, like :lua print('foo') in Neovim?

1 Answer

+1 vote
by
selected by
 
Best answer

1) Is the Lua API the only way to add a description to a key binding?

v0.15 will allow doing this without Lua as:

nnoremap <help><Space>r {edit file as root}:RootEditFile<CR>

Syntax is similar to that of :file[x]type but requires <help> for disambiguation, so ends up somewhat verbose.

2) According to the help file: "Builtin print() function puts messages to plugin's log (see |vifm-:plugins| menu)." Where can I view these logs? Running :plugins just shows a list of plugins. I've been using vifm.sb.info('...') instead for logging, but that isn't ideal.

You need to press e to see the log. Search for Plugins (:plugins) menu in documentation (there is no tag for it, it's below this).

You can simply do print = vifm.sb.info to not have to open the menu while debugging. It turned out to not be convenient, but allows to see messages from different plugins without mixing them up.

3) Is there something built-in to pretty-print tables? In Neovim you can do :lua print( vim.inspect( tbl ) ).

No, I think Lua itself doesn't offer anything for that and Vifm doesn't offer pretty-printing either.

4) A helper function like the following can pretty-print tables:

How would one print, for example, vifm.currview(), which is of type Vifmview? I've also encountered the type userdata.

Vifmview is also user data, but not a lighweight one (that one is reported as userdata). These types are implemented in C, although syntactically they can act similar to tables.

5) I expected there would be something like vim.cmd() in Neovim, but if I understand correctly, it's impossible to call a built-in command like :messages or :normal! j from the Lua API? For the latter, there's an alternative (local c = vifm.currview().cursor; c.pos = c.pos + 1), but for the former, there isn't?

There is intentionally no vifm.cmd(), couple paragraphs on that are here. It's easy to add but there is no way to guarantee proper escaping for arguments because :commands are too irregular in how they treat input. In my experience with Vim plugins partially written in Python, that was a source of never ending issues and I see no solution.

This does mean that an equivalent of each :command needs to be exposed to Lua in its own way and there isn't one for :messages.

6) There isn't a way to run Lua from the Vifm command-line either, like :lua print('foo') in Neovim?

No, for the same reason, although this can be implemented by a plugin:

local function lua(info)
    local code = string.format('return tostring(%s)', info.args)
    local f, err = load(code, ":Lua args")
    if f == nil then
        vifm.sb.error("Failed to compile arguments: "..err)
    else
        vifm.sb.info(f())
    end
end

local function luaS(info)
    local f, err = load(info.args, ":Lua args")
    if f == nil then
        vifm.sb.error("Failed to compile arguments: "..err)
    else
        f()
    end
end

local added = vifm.cmds.add {
    name = "Lua",
    description = "evaluate and print a Lua expression",
    handler = lua,
    minargs = 1,
    maxargs = -1,
}
if not added then
    vifm.sb.error("Failed to register :Lua")
end

local added = vifm.cmds.add {
    name = "LuaS",
    description = "execute a Lua statement",
    handler = luaS,
    minargs = 1,
    maxargs = -1,
}
if not added then
    vifm.sb.error("Failed to register :LuaS")
end

return {}
by

Thank you for these clarifications.

v0.15 will allow doing this without Lua as: nnoremap r {edit file as root}:RootEditFile

That's a very helpful feature, I'm definitely going to use it. It means I will no longer have to create commands to give a key binding a legible description.

You need to press e to see the log. Search for Plugins (:plugins) menu in documentation (there is no tag for it, it's below this).

Thanks, I've figured it out now. I probably missed it before because the "Builtin print() function puts messages to plugin's log (see |vifm-:plugins| menu)." part of the manual doesn't directly link to the "Plugins (:plugins) menu" section.

No, for the same reason, although this can be implemented by a plugin: ...

That snippet could be very handy during plugin development.
For future readers, it can be used like this:

:Lua math.pi
:LuaS if 3 >= 2 then print('greater or equal') else print('less') end
by

I appreciate the key bind hints, looking forward to v0.15 :-)

As always, thank you very much for your detailed answers!

If you would like to make a bug report or feature request consider using GitHub, SourceForge or e-mail. Posting such things here is acceptable, but this is not a perfect place for them.
...