Make dfhack.run_script usable from other scripts, and document it.

develop
Alexander Gavrilov 2012-06-14 12:46:12 +04:00
parent 2781723f7b
commit 7eb4fc19de
4 changed files with 34 additions and 11 deletions

@ -491,6 +491,13 @@ Currently it defines the following features:
Compares to coroutine.resume like dfhack.safecall vs pcall. Compares to coroutine.resume like dfhack.safecall vs pcall.
* ``dfhack.run_script(name[,args...])``
Run a lua script in hack/scripts/, as if it was started from dfhack command-line.
The ``name`` argument should be the name stem, as would be used on the command line.
Note that the script is re-read from the file every time it is called, and errors
are propagated to the caller.
* ``dfhack.with_suspend(f[,args...])`` * ``dfhack.with_suspend(f[,args...])``
Calls ``f`` with arguments after grabbing the DF core suspend lock. Calls ``f`` with arguments after grabbing the DF core suspend lock.
@ -1148,6 +1155,11 @@ Internal API
These functions are intended for the use by dfhack developers, These functions are intended for the use by dfhack developers,
and are only documented here for completeness: and are only documented here for completeness:
* ``dfhack.internal.scripts``
The table used by ``dfhack.run_script()`` to give every script its own
global environment, persistent between calls to the script.
* ``dfhack.internal.getAddress(name)`` * ``dfhack.internal.getAddress(name)``
Returns the global address ``name``, or *nil*. Returns the global address ``name``, or *nil*.

@ -766,6 +766,12 @@ returning. Intended as a convenience function.</p>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.saferesume(coroutine[,args...])</span></tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.saferesume(coroutine[,args...])</span></tt></p>
<p>Compares to coroutine.resume like dfhack.safecall vs pcall.</p> <p>Compares to coroutine.resume like dfhack.safecall vs pcall.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.run_script(name[,args...])</span></tt></p>
<p>Run a lua script in hack/scripts/, as if it was started from dfhack command-line.
The <tt class="docutils literal">name</tt> argument should be the name stem, as would be used on the command line.
Note that the script is re-read from the file every time it is called, and errors
are propagated to the caller.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.with_suspend(f[,args...])</span></tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.with_suspend(f[,args...])</span></tt></p>
<p>Calls <tt class="docutils literal">f</tt> with arguments after grabbing the DF core suspend lock. <p>Calls <tt class="docutils literal">f</tt> with arguments after grabbing the DF core suspend lock.
Suspending is necessary for accessing a consistent state of DF memory.</p> Suspending is necessary for accessing a consistent state of DF memory.</p>
@ -1310,6 +1316,10 @@ Returns <em>true, was_only_planned</em> if removed; or <em>false</em> if none fo
<p>These functions are intended for the use by dfhack developers, <p>These functions are intended for the use by dfhack developers,
and are only documented here for completeness:</p> and are only documented here for completeness:</p>
<ul> <ul>
<li><p class="first"><tt class="docutils literal">dfhack.internal.scripts</tt></p>
<p>The table used by <tt class="docutils literal">dfhack.run_script()</tt> to give every script its own
global environment, persistent between calls to the script.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.getAddress(name)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.internal.getAddress(name)</tt></p>
<p>Returns the global address <tt class="docutils literal">name</tt>, or <em>nil</em>.</p> <p>Returns the global address <tt class="docutils literal">name</tt>, or <em>nil</em>.</p>
</li> </li>

@ -264,16 +264,12 @@ static bool init_run_script(color_ostream &out, lua_State *state, void *info)
return true; return true;
} }
static command_result runLuaScript(color_ostream &out, std::string filename, vector<string> &args) static command_result runLuaScript(color_ostream &out, std::string name, vector<string> &args)
{ {
ScriptArgs data; ScriptArgs data;
data.pcmd = &filename; data.pcmd = &name;
data.pargs = &args; data.pargs = &args;
#ifndef LINUX_BUILD
filename = toLower(filename);
#endif
bool ok = Lua::RunCoreQueryLoop(out, Lua::Core::State, init_run_script, &data); bool ok = Lua::RunCoreQueryLoop(out, Lua::Core::State, init_run_script, &data);
return ok ? CR_OK : CR_FAILURE; return ok ? CR_OK : CR_FAILURE;
@ -619,7 +615,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
{ {
auto filename = getHackPath() + "scripts/" + first + ".lua"; auto filename = getHackPath() + "scripts/" + first + ".lua";
if (fileExists(filename)) if (fileExists(filename))
res = runLuaScript(con, filename, parts); res = runLuaScript(con, first, parts);
else else
con.printerr("%s is not a recognized command.\n", first.c_str()); con.printerr("%s is not a recognized command.\n", first.c_str());
} }

@ -273,19 +273,24 @@ end
-- Command scripts -- Command scripts
dfhack.scripts = dfhack.scripts or {} dfhack.internal.scripts = dfhack.internal.scripts or {}
function dfhack.run_script(file,...) local scripts = dfhack.internal.scripts
local env = dfhack.scripts[file] local hack_path = dfhack.getHackPath()
function dfhack.run_script(name,...)
local key = string.lower(name)
local file = hack_path..'scripts/'..name..'.lua'
local env = scripts[key]
if env == nil then if env == nil then
env = {} env = {}
setmetatable(env, { __index = base_env }) setmetatable(env, { __index = base_env })
dfhack.scripts[file] = env
end end
local f,perr = loadfile(file, 't', env) local f,perr = loadfile(file, 't', env)
if f == nil then if f == nil then
error(perr) error(perr)
end end
scripts[key] = env
return f(...) return f(...)
end end