NeoVim - Check if a Vim function exists from Lua - lua

I plan on using vim-plug with NeoVim. So, my init.lua file will have function calls such as
vim.fn['plug#begin'](vim.fn.stdpath('data') .. '/plugged')
vim.fn['plug#']('hoob3rt/lualine.nvim')
However, I don't want to assume vim-plug is definitely installed. I want my init.lua file to degrade gracefully if vim-plug is not installed, rather than throwing an error
E5113: Error while calling lua chunk: Vim:E117: Unknown function: plug#begin
stack traceback:
[C]: in function 'plug#begin'
/Users/andy/.config/nvim/init.lua:8: in main chunk
How can I check if the vim-plug functions exist before attempting to call them?
I tried print(vim.fn['plug#begin']) but that for some reason prints a non-null value: function: 0x0104ba36f0, even though the function doesn't exist.

I tried print(vim.fn['plug#begin']) but that for some reason prints a non-null value: function: 0x0104ba36f0, even though the function doesn't exist.
Presumably it's returning a function that throws the error you are getting. I would thus recommend using pcall:
local success, error = pcall(vim.fn['plug#begin'], vim.fn.stdpath('data') .. '/plugged')
if not success then --[[fail gracefully]] end
caveat: this will catch any error, so you'll probably want to perform some check like if error:find"Unknown function" then ... end to only catch this specific error.

Related

Requiring luasnip to neovim causes errors

I am trying to use luasnip.
The configuration I am using is AstroNvim.
The modifications I made to this configuration are :
require("luasnip.loaders.from_snipmate").lazy_load() at the end of init.lua
Made a directory snippets in the same directory of init.lua, and added some basic snipmate styled snippets inside.
Commands Like :LuaSnipListAvailable works well, and snippets from friendly-snippets works well too.
However the following error message pops up when opening neovim.
Error detected while processing /Users/myusername/.config/nvim/init.lua:
E5113: Error while calling lua chunk: ...m/site/pack/packer/start/packer.nvim/lua/packer/load.lua:171: Vim(echomsg):E121: Undefined variable: Error
stack traceback:
[C]: in function 'cmd'
...m/site/pack/packer/start/packer.nvim/lua/packer/load.lua:171: in function <...m/site/pack/packer/start/packer.nvim/lua/packer/load.lua:16
7>
/Users/myusername/.local/share/nvim/packer_compiled.lua:496: in function </Users/myusername/.local/share/nvim/packer_compiled.lua:485>
[C]: in function 'require'
/Users/myusername/.config/nvim/init.lua:23: in main chunk
I tried other methods of adding snippets, but any sort of require("luasnip") seems to break all.

Loadstring Error: attempted to call a nil value

loadstring("
\45\45\32\80\117\116\32\115\99\114\105\112\116\32\104\101\114\101\10\112\114\105\110\116\40\34\104\105\34\41\10")()
I keep getting an error stating this:
lua: /tmp/044957038/main.lua:12: attempt to call a nil value (global 'loadstring')
stack traceback:
/tmp/044957038/main.lua:12: in main chunk
[C]: in ?
Can anyone help me? (I’m using glot.io to run my script.)
Based on the comments and some testing in glot, this should work (the print() is just for reference):
print("\45\45\32\80\117\116\32\115\99\114\105\112\116\32\104\101\114\101\10\112\114\105\110\116\40\34\104\105\34\41\10")
load("\45\45\32\80\117\116\32\115\99\114\105\112\116\32\104\101\114\101\10\112\114\105\110\116\40\34\104\105\34\41\10")()
Output
-- Put script here
print("hi")
hi

Error running call reference function

I am having an error whilst trying to run a resource on a game server. I believe this line of code in the console is the issue;
Error running call reference function for resource es_extended:
citizen:/scripting/lua/scheduler.lua:351: server/main.lua:237: attempt to
index a nil value (global 'Async')
I have been to line 351 to find this;
error(err)
I then went to line 237 to find this;
Async.parallel(tasks, function(results)
I cannot see for the life of me anything wrong with either lines of code. So any and all advice is greatly recieved.
The global variable Async is a nil value. Hence indexing it like this:
Async.parallel
is not possible. Therefor Lua throws an error.
To fix it, find out why Async is nil and change that, or do not index it.

Torch 7/Lua cannot require a .so file, but package.loadlib() can

I get a problem when playing Torch 7 code. I have a shared library libhashnn.so file, and I want to load the functions in Torch 7 script, so I use this expression: require 'libhashnn', but the trepl gives an error.
However, if I use package.loadlibfunction, it does work. Here are the results, but I don't know why I can't use require, how can I use require to load lib successfully?
require'libhashnn'
/home/dazhen/torch/install/share/lua/5.1/trepl/init.lua:383: bad argument #1 to '?' (table expected, got string)
stack traceback:
[C]: in function 'error'
/home/dazhen/torch/install/share/lua/5.1/trepl/init.lua:383: in function 'require'
[string "_RESULT={require'libhashnn'}"]:1: in main chunk
[C]: in function 'xpcall'
/home/dazhen/torch/install/share/lua/5.1/trepl/init.lua:650: in function 'repl'
...zhen/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:199: in main chunk
and
f=package.loadlib('libhashnn.so' ,'luaopen_libhashnn')
[0.0195s]
th> f
function: 0x41630f38
Try calling the function that package.loadlib gives you. I bet you will then get the same error that you get when you use require.
To understand why: require does the equivalent of package.loadlib and then calls that function so that the module that you are loading can initialize itself. With just package.loadlib, this initialization is not done and so the error that occurs during initialization does not show up.
I don't know what hashnn is and so I cannot tell you why it is broken, but looking at /home/dazhen/torch/install/share/lua/5.1/trepl/init.lua line 383 might be a good start to figure out what is going on.

Lua: How to call error without stack trace

I'm using Lua to parse scripts written in some language (let's call it L) and create Lua-code that can be run by e.g. LuaJIT. But to simplify debugging for the users, I want to map the run time errors given by Lua/LuaJIT to the correct line in the L-files. I do this by xpcalling the created Lua-code, translating the error message and stacktrace and then calling error with this message. Unfortunately this gives me two stack traces, one created by me and one tracing back to the function that called error. Is it possible to get rid of this stack trace, or is there some better way of doing this?
local status, err = xpcall(loadedCode, debug.traceback)
if not status then
error(createANewErrorMessageWithPrettyTraceback(err),0)
end
Output:
luajit: ./my/file.name:5: Some error message
stack traceback:
my pretty traceback
stack traceback:
[C]: in function 'error'
./my/file/calling/error.lua:44: in function <./my/file/calling/error.lua:26>
./my-main:16: in main chunk
[C]: at 0x00404180
I know that e.g. Moonscript does something similar to this, but as far as I can see they just write the new error message to stderr and then continues as normal, instead of stopping the program which is what I want to do.
There is a possibility of doing this and then calling error with no arguments, which will make the program fail (actually I think it's error that fails), but this feels like quite an ugly solution, so I'll rather keep the stupid second trace than doing that.
PS: I assume what the title asks actually doesn't work (as error only takes two arguments), so what I'm actually asking is more how something like this can be achieved. (Are there other functions that do similar things perhaps, or where I should look to figure out how to write that function myself.)
Edit: Is it perhaps possible to edit the function that error's using to get its traceback, as it is with debug.traceback?
I wanted to do something similar (only from Lua directly) and I ended up overwriting debug.traceback function itself to change the stack trace to suit my needs. My code is below; see if this method works for you as well:
local dtraceback = debug.traceback
debug.traceback = function (...)
if select('#', ...) >= 1 then
local err, lvl = ...
if err and type(err) ~= 'thread' then
local trace = dtraceback(err, (lvl or 2)+1)
if genv.print == iobase.print then -- no remote redirect
return trace
else
genv.print(trace) -- report the error remotely
return -- don't report locally to avoid double reporting
end
end
end
-- direct call to debug.traceback: return the original.
-- debug.traceback(nil, level) doesn't work in Lua 5.1
-- (http://lua-users.org/lists/lua-l/2011-06/msg00574.html), so
-- simply remove first frame from the stack trace
return (dtraceback(...):gsub("(stack traceback:\n)[^\n]*\n", "%1"))
end
You could simply display the modified traceback that you want and exit.
local function errh(err)
print(createANewErrorMessageWithPrettyTraceback(debug.traceback(err, 2)))
os.exit(-1) -- error code
end
local status, result = xpcall(loadedCode, errh)
-- The script will never reach this point if there is an error.
print(result)

Resources