在trepl或luajit中,如何找到我正在使用的库的源代码? [英] In trepl or luajit, how can I find the source code of a library I'm using?
问题描述
假设我正在使用通过luarocks安装的lua库工作,我想查看该库中函数的定义.在ipython中可以使用
?? function_name
要查看终端中的定义,在matlab中我可以使用
哪个function_name
然后使用我的编辑器查看其中返回的路径.我该怎么做才能找到lua库的函数定义?
??function_name
to see the definition in the terminal, in matlab I could use
which function_name
then use my editor to look at the path returned by which. How could I do something similar to find the function definition for a lua library?
In 'plain' Lua/JIT, you can say debug.getinfo
( func )
and will get a table containing (among others) the fields short_src
, source
and linedefined
.
For Lua functions, short_src
will be the filename or stdin
if it was defined in the REPL. (source
has a slightly different format, filenames are prefixed with an @
, a =
prefix is used for C functions or stuff defined interactively, and for load
ed functions, it will be the actual string that was loaded.)
You can pack that up in a function like
function sourceof( f )
local info = debug.getinfo( f, "S" )
return info.short_src, info.linedefined
end
or maybe even start an editor and point it there, e.g. (for vim)
function viewsource( f )
-- get info & check it's actually from a file
local info = debug.getinfo( f, "S" )
local src, line = info.source, info.linedefined
if src == "=[C]" then return nil, "Is a C function." end
local path = src:match "^@(.*)$"
if path then
-- start vim (or an other editor if you adapt the format string)
return os.execute( ("vim -fR %q +%d"):format( path, line ) )
end
return nil, "Was defined at run time."
end
And just for fun, here's yet another version that returns the code if it can find it somewhere. (This will also work for functions that have been generated at run time, e.g. by calling load
, and where no source file exists. You could also work in the other direction by dumping the load
ed snippet into a temp file and opening that…)
-- helper to extract the source block defining the function
local function funclines( str, line1, lineN, filename )
-- if linedefined / lastlinedefined are 0, this is the main chunk's function
if line1 == 0 and lineN == 0 then
filename = filename and filename.." (main chunk)"
or "(chunk defined at runtime)"
return "-- "..filename.."\n"..str
end
-- add line info to file name or use placeholder
filename = filename and filename..":"..line1 or "(defined at runtime)"
-- get the source block
local phase, skip, grab = 1, line1-1, lineN-(line1-1)
local ostart, oend -- these will be the start/end offsets
if skip == 0 then phase, ostart = 2, 0 end -- starts at first line
for pos in str:gmatch "\n()" do
if phase == 1 then -- find offset of linedefined
skip = skip - 1 ; if skip == 0 then ostart, phase = pos, 2 end
else -- phase == 2, find offset of lastlinedefined+1
grab = grab - 1 ; if grab == 0 then oend = pos-2 ; break end
end
end
return "-- "..filename.."\n"..str:sub( ostart, oend )
end
function dumpsource( f )
-- get info & line numbers
local info = debug.getinfo( f, "S" )
local src, line, lastline = info.source, info.linedefined, info.lastlinedefined
-- can't do anything for a C function
if src == "=[C]" then return nil, "Is a C function." end
if src == "=stdin" then return nil, "Was defined interactively." end
-- for files, fetch the definition
local path = src:match "^@(.*)$"
if path then
local f = io.open( path )
local code = f:read '*a'
f:close( )
return funclines( code, line, lastline, path )
end
-- otherwise `load`ed, so `source`/`src` _is_ the source
return funclines( src, line, lastline )
end
A closing remark: If you paste code into a Lua/JIT REPL, local
s disappear between definitions, because every line (or minimal complete group of lines) is its own chunk. The common fix (that you probably know) is to wrap everything into a block as do
*paste*end
, but an alternative is to load[[
*paste*]]()
(possibly with more =
s like [===[
and ]===]
.) If you paste this way, the above dumpsource
(or any other function using debug.getinfo
) will then be able to get the source of the function(s). This also means that if you defined a nice function but it's gone from the history and the scroll buffer, you can recover it in this way (if you defined it by load
ing and not directly feeding the interpreter). Saving the source in a file will then also be possible without copy-pasting and not require editing out the >>
prompts.
这篇关于在trepl或luajit中,如何找到我正在使用的库的源代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!