1

luarocks を使用してインストールした lua ライブラリーを使用していて、そのライブラリーの関数の定義を確認したいとします。ipythonでは使用できます

??関数名

ターミナルで定義を確認するには、matlab で使用できます

どの関数名

次に、エディターを使用して、 which によって返されたパスを確認します。lua ライブラリの関数定義を見つけるのに似たようなことをするにはどうすればよいでしょうか?

4

1 に答える 1

3

「プレーンな」Lua/JIT では、(とりわけ) フィールドとを含むテーブルを取得すると言うことができます。debug.getinfo( func )short_srcsourcelinedefined

Lua 関数の場合short_src、ファイル名になるかstdin、REPL で定義されている場合。(source形式が少し異なります。ファイル名の前に が付きます。プレフィックスは@=C 関数または対話的に定義されたものに使用されますload。ed 関数の場合、ロードされた実際の文字列になります。)

それを次のような関数にまとめることができます

function sourceof( f )
    local info = debug.getinfo( f, "S" )
    return info.short_src, info.linedefined
end

または、エディターを起動してそこにポイントすることもできます(例: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

楽しみのために、どこかでコードが見つかった場合にコードを返す別のバージョンを次に示します。(これは、たとえば を呼び出して実行時に生成された関数loadや、ソース ファイルが存在しない関数に対しても機能します。また、loaded スニペットを一時ファイルにダンプしてそれを開くことで、別の方向で作業することもできます…)

-- 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

結びの言葉: コードを Lua/JIT REPL に貼り付けるlocalと、すべての行 (または行の最小限の完全なグループ) が独自のチャンクであるため、定義の間で s が消えます。一般的な修正 (おそらくご存知でしょう) は、すべてをdo*paste*としてブロックにラップすることですendが、代わりにload[[*paste* ]]()(さらに=like[===[]===].) を使用することもできます。この方法で貼り付けると、上記dumpsource(またはその他のfunction using debug.getinfo) は、関数のソースを取得できます。これはまた、nice 関数を定義したものの、それが履歴とスクロール バッファからなくなった場合、この方法で回復できることも意味します (次のように定義した場合)。load通訳者に直接提供しない)。ソースをファイルに保存することも、コピーして貼り付けることなく可能になり、>>プロンプトを編集する必要がなくなります。

于 2015-04-26T00:35:43.063 に答える