Merge branch 'lua-runcommand' of git://github.com/lethosor/dfhack into develop

develop
Alexander Gavrilov 2014-06-17 10:27:50 +04:00
commit 32d8efad54
3 changed files with 95 additions and 1 deletions

@ -4,6 +4,7 @@ DFHack future
- support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua).
- Lua API for listing files in directory. Needed for mod-manager.
- Lua API for creating unit combat reports and writing to gamelog.
- Lua API for running arbitrary DFHack commands
- support for multiple raw/init.d/*.lua init scripts in one save.
- eventful now has a more friendly way of making custom sidebars
- new plugin: building-hacks. Allows to add custom functionality and/or animations to buildings.

@ -2227,6 +2227,64 @@ static int internal_getDir(lua_State *L)
}
return 1;
}
static int internal_runCommand(lua_State *L)
{
buffered_color_ostream out;
command_result res;
if (lua_gettop(L) == 0)
{
lua_pushstring(L, "");
}
int type_1 = lua_type(L, 1);
if (type_1 == LUA_TTABLE)
{
std::string command = "";
std::vector<std::string> args;
lua_pushnil(L); // first key
while (lua_next(L, 1) != 0)
{
if (command == "")
command = lua_tostring(L, -1);
else
args.push_back(lua_tostring(L, -1));
lua_pop(L, 1); // remove value, leave key
}
CoreSuspender suspend;
res = Core::getInstance().runCommand(out, command, args);
}
else if (type_1 == LUA_TSTRING)
{
std::string command = lua_tostring(L, 1);
CoreSuspender suspend;
res = Core::getInstance().runCommand(out, command);
}
else
{
lua_pushnil(L);
lua_pushfstring(L, "Expected table, got %s", lua_typename(L, type_1));
return 2;
}
auto fragments = out.fragments();
lua_newtable(L);
lua_pushinteger(L, (int)res);
lua_setfield(L, -2, "status");
int i = 1;
for (auto iter = fragments.begin(); iter != fragments.end(); iter++, i++)
{
int color = iter->first;
std::string output = iter->second;
lua_createtable(L, 2, 0);
lua_pushinteger(L, color);
lua_rawseti(L, -2, 1);
lua_pushstring(L, output.c_str());
lua_rawseti(L, -2, 2);
lua_rawseti(L, -2, i);
}
lua_pushvalue(L, -1);
return 1;
}
static const luaL_Reg dfhack_internal_funcs[] = {
{ "getAddress", internal_getAddress },
{ "setAddress", internal_setAddress },
@ -2240,6 +2298,7 @@ static const luaL_Reg dfhack_internal_funcs[] = {
{ "memscan", internal_memscan },
{ "diffscan", internal_diffscan },
{ "getDir", internal_getDir },
{ "runCommand", internal_runCommand },
{ NULL, NULL }
};

@ -10,6 +10,14 @@ local dfhack = dfhack
local base_env = dfhack.BASE_G
local _ENV = base_env
CR_LINK_FAILURE = -3
CR_NEEDS_CONSOLE = -2
CR_NOT_IMPLEMENTED = -1
CR_OK = 0
CR_FAILURE = 1
CR_WRONG_USAGE = 2
CR_NOT_FOUND = 3
-- Console color constants
COLOR_RESET = -1
@ -256,7 +264,8 @@ function dfhack.interpreter(prompt,hfile,env)
print("Shortcuts:\n"..
" '= foo' => '_1,_2,... = foo'\n"..
" '! foo' => 'print(foo)'\n"..
"Both save the first result as '_'.")
" '~ foo' => 'printall(foo)'\n"..
"All of these save the first result as '_'.")
print_banner = false
end
@ -357,6 +366,31 @@ function dfhack.run_script(name,...)
return f(...)
end
function dfhack.run_command(...)
args = {...}
if type(args[1]) == 'table' then
command = args[1]
elseif #args > 1 and type(args[2]) == 'table' then
-- {args[1]} + args[2]
command = args[2]
table.insert(command, 1, args[1])
elseif #args == 1 and type(args[1]) == 'string' then
command = args[1]
elseif #args > 1 and type(args[1]) == 'string' then
command = args
else
error('Invalid arguments')
end
result = internal.runCommand(command)
output = ""
for i, f in pairs(result) do
if type(f) == 'table' then
output = output .. f[2]
end
end
return output, result.status
end
-- Per-save init file
function dfhack.getSavePath()