summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--depends/lua/include/luaconf.h18
-rw-r--r--library/CMakeLists.txt6
-rw-r--r--library/Core.cpp10
-rw-r--r--library/LuaTools.cpp364
-rw-r--r--library/LuaWrapper.cpp12
-rw-r--r--library/include/Core.h1
-rw-r--r--library/include/DataDefs.h35
-rw-r--r--library/include/LuaTools.h92
-rw-r--r--library/include/LuaWrapper.h2
-rw-r--r--library/lua/dfhack.lua5
-rw-r--r--plugins/Dfusion/dfusion.cpp104
-rw-r--r--plugins/Dfusion/include/lua_Console.h2
-rw-r--r--plugins/Dfusion/src/lua_Console.cpp73
14 files changed, 501 insertions, 225 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8dde18db..60286c92 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,6 +82,8 @@ SET(DFHACK_DATA_DESTINATION hack)
SET(DFHACK_PLUGIN_DESTINATION hack/plugins)
# dfhack header files go here:
SET(DFHACK_INCLUDES_DESTINATION hack/include)
+# dfhack lua files go here:
+SET(DFHACK_LUA_DESTINATION hack/lua)
# the windows .lib file goes here:
SET(DFHACK_DEVLIB_DESTINATION hack)
diff --git a/depends/lua/include/luaconf.h b/depends/lua/include/luaconf.h
index 7a3a03d3..fca66ce4 100644
--- a/depends/lua/include/luaconf.h
+++ b/depends/lua/include/luaconf.h
@@ -89,25 +89,21 @@
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
-#define LUA_LDIR "!\\lua\\"
+#define LUA_LDIR "!\\hack\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \
- LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua"
+ LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" ".\\?.lua"
#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll"
+ LUA_CDIR"?.dll;" ".\\?.dll"
#else /* }{ */
-#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
-#define LUA_ROOT "/usr/local/"
-#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
-#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
+#define LUA_LDIR "./hack/lua/"
+#define LUA_CDIR "./hack/"
#define LUA_PATH_DEFAULT \
- LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
- LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua"
+ LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" "./?.lua"
#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
+ LUA_CDIR"?.so;" "./?.so"
#endif /* } */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 9de419b9..f8b05a04 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -29,6 +29,7 @@ include/ColorText.h
include/DataDefs.h
include/DataIdentity.h
include/LuaWrapper.h
+include/LuaTools.h
include/Error.h
include/Export.h
include/Hooks.h
@@ -58,6 +59,7 @@ ColorText.cpp
DataDefs.cpp
LuaWrapper.cpp
LuaTypes.cpp
+LuaTools.cpp
DataStatics.cpp
DataStaticsCtor.cpp
DataStaticsFields.cpp
@@ -295,6 +297,10 @@ install(TARGETS dfhack-run dfhack-client
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})
+install(DIRECTORY lua/
+ DESTINATION ${DFHACK_LUA_DESTINATION}
+ FILES_MATCHING PATTERN "*.lua")
+
# Unused for so long that it's not even relevant now...
if(BUILD_DEVEL)
if(WIN32)
diff --git a/library/Core.cpp b/library/Core.cpp
index 4712be0a..8adbf374 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -757,6 +757,16 @@ std::string Core::getHotkeyCmd( void )
return returner;
}
+void Core::print(const char *format, ...)
+{
+ color_ostream_proxy proxy(getInstance().con);
+
+ va_list args;
+ va_start(args,format);
+ proxy.vprint(format,args);
+ va_end(args);
+}
+
void Core::printerr(const char *format, ...)
{
color_ostream_proxy proxy(getInstance().con);
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp
new file mode 100644
index 00000000..b493f761
--- /dev/null
+++ b/library/LuaTools.cpp
@@ -0,0 +1,364 @@
+/*
+https://github.com/peterix/dfhack
+Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "Internal.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "MemAccess.h"
+#include "Core.h"
+#include "VersionInfo.h"
+#include "tinythread.h"
+// must be last due to MS stupidity
+#include "DataDefs.h"
+#include "DataIdentity.h"
+
+#include "LuaWrapper.h"
+#include "LuaTools.h"
+
+#include "MiscUtils.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+using namespace DFHack;
+using namespace DFHack::LuaWrapper;
+
+void DFHack::Lua::PushDFObject(lua_State *state, type_identity *type, void *ptr)
+{
+ push_object_internal(state, type, ptr, false);
+}
+
+void *DFHack::Lua::GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type)
+{
+ return get_object_internal(state, type, val_index, exact_type, false);
+}
+
+static int DFHACK_OSTREAM_TOKEN = 0;
+
+color_ostream *DFHack::Lua::GetOutput(lua_State *L)
+{
+ lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_OSTREAM_TOKEN);
+ auto rv = (color_ostream*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ return rv;
+}
+
+static void set_dfhack_output(lua_State *L, color_ostream *p)
+{
+ lua_pushlightuserdata(L, p);
+ lua_rawsetp(L, LUA_REGISTRYINDEX, &DFHACK_OSTREAM_TOKEN);
+}
+
+static std::string lua_print_fmt(lua_State *L)
+{
+ /* Copied from lua source to fully replicate builtin print */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_getglobal(L, "tostring");
+
+ std::stringstream ss;
+
+ for (int i=1; i<=n; i++) {
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ const char *s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ luaL_error(L, "tostring must return a string to print");
+ if (i>1)
+ ss << '\t';
+ ss << s;
+ lua_pop(L, 1); /* pop result */
+ }
+
+ return ss.str();
+}
+
+static int lua_dfhack_print(lua_State *S)
+{
+ std::string str = lua_print_fmt(S);
+ if (color_ostream *out = Lua::GetOutput(S))
+ *out << str;
+ else
+ Core::print("%s", str.c_str());
+ return 0;
+}
+
+static int lua_dfhack_println(lua_State *S)
+{
+ std::string str = lua_print_fmt(S);
+ if (color_ostream *out = Lua::GetOutput(S))
+ *out << str << std::endl;
+ else
+ Core::print("%s\n", str.c_str());
+ return 0;
+}
+
+static int lua_dfhack_printerr(lua_State *S)
+{
+ std::string str = lua_print_fmt(S);
+ if (color_ostream *out = Lua::GetOutput(S))
+ out->printerr("%s\n", str.c_str());
+ else
+ Core::printerr("%s\n", str.c_str());
+ return 0;
+}
+
+static int traceback (lua_State *L) {
+ const char *msg = lua_tostring(L, 1);
+ if (msg)
+ luaL_traceback(L, L, msg, 1);
+ else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
+ if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
+ lua_pushliteral(L, "(no error message)");
+ }
+ return 1;
+}
+
+static void report_error(color_ostream &out, lua_State *L)
+{
+ const char *msg = lua_tostring(L, -1);
+ if (msg)
+ out.printerr("%s\n", msg);
+ else
+ out.printerr("In Lua::SafeCall: error message is not a string.\n", msg);
+ lua_pop(L, 1);
+}
+
+bool DFHack::Lua::SafeCall(color_ostream &out, lua_State *L, int nargs, int nres, bool perr)
+{
+ int base = lua_gettop(L) - nargs;
+
+ color_ostream *cur_out = Lua::GetOutput(L);
+ set_dfhack_output(L, &out);
+
+ lua_pushcfunction(L, traceback);
+ lua_insert(L, base);
+
+ bool ok = lua_pcall(L, nargs, nres, base) == LUA_OK;
+
+ lua_remove(L, base);
+ set_dfhack_output(L, cur_out);
+
+ if (!ok && perr)
+ report_error(out, L);
+
+ return ok;
+}
+
+bool DFHack::Lua::Require(color_ostream &out, lua_State *state,
+ const std::string &module, bool setglobal)
+{
+ lua_getglobal(state, "require");
+ lua_pushstring(state, module.c_str());
+
+ if (!Lua::SafeCall(out, state, 1, 1))
+ return false;
+
+ if (setglobal)
+ lua_setglobal(state, module.c_str());
+ else
+ lua_pop(state, 1);
+
+ return true;
+}
+
+static bool load_with_env(color_ostream &out, lua_State *state, const std::string &code, int eidx)
+{
+ if (luaL_loadstring(state, code.c_str()) != LUA_OK)
+ {
+ report_error(out, state);
+ return false;
+ }
+
+ // Replace _ENV
+ lua_pushvalue(state, eidx);
+
+ if (!lua_setupvalue(state, -2, 1))
+ {
+ out.printerr("No _ENV upvalue.\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool DFHack::Lua::InterpreterLoop(color_ostream &out, lua_State *state,
+ const char *prompt, int env, const char *hfile)
+{
+ if (!out.is_console())
+ return false;
+ if (!lua_checkstack(state, 20))
+ return false;
+
+ if (!hfile)
+ hfile = "lua.history";
+ if (!prompt)
+ prompt = "lua";
+
+ DFHack::CommandHistory hist;
+ hist.load(hfile);
+
+ out.print("Type quit to exit interactive lua interpreter.\n"
+ "Shortcuts:\n"
+ " '= foo' => '_1,_2,... = foo'\n"
+ " '! foo' => 'print(foo)'\n"
+ "Both assign the first result to '_'\n");
+
+ Console &con = static_cast<Console&>(out);
+
+ // Make a proxy global environment.
+ lua_newtable(state);
+ lua_newtable(state);
+ if (env)
+ lua_pushvalue(state, env);
+ else
+ lua_rawgeti(state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
+ lua_setfield(state, -2, "__index");
+ lua_setmetatable(state, -2);
+
+ // Main interactive loop
+ int base = lua_gettop(state);
+ int vcnt = 1;
+ string curline;
+ string prompt_str = "[" + string(prompt) + "]# ";
+
+ for (;;) {
+ lua_settop(state, base);
+
+ con.lineedit(prompt_str,curline,hist);
+
+ if (curline.empty())
+ continue;
+ if (curline == "quit")
+ break;
+
+ hist.add(curline);
+
+ char pfix = curline[0];
+
+ if (pfix == '=' || pfix == '!')
+ {
+ curline = "return " + curline.substr(1);
+
+ if (!load_with_env(out, state, curline, base))
+ continue;
+ if (!SafeCall(out, state, 0, LUA_MULTRET))
+ continue;
+
+ int numret = lua_gettop(state) - base;
+
+ if (numret >= 1)
+ {
+ lua_pushvalue(state, base+1);
+ lua_setfield(state, base, "_");
+
+ if (pfix == '!')
+ {
+ lua_pushcfunction(state, lua_dfhack_println);
+ lua_insert(state, base+1);
+ SafeCall(out, state, numret, 0);
+ continue;
+ }
+ }
+
+ for (int i = 1; i <= numret; i++)
+ {
+ std::string name = stl_sprintf("_%d", vcnt++);
+ lua_pushvalue(state, base + i);
+ lua_setfield(state, base, name.c_str());
+
+ out.print("%s = ", name.c_str());
+
+ lua_pushcfunction(state, lua_dfhack_println);
+ lua_pushvalue(state, base + i);
+ SafeCall(out, state, 1, 0);
+ }
+ }
+ else
+ {
+ if (!load_with_env(out, state, curline, base))
+ continue;
+ if (!SafeCall(out, state, 0, LUA_MULTRET))
+ continue;
+ }
+ }
+
+ lua_settop(state, base-1);
+
+ hist.save(hfile);
+ return true;
+}
+
+static int lua_dfhack_interpreter(lua_State *state)
+{
+ color_ostream *pstream = Lua::GetOutput(state);
+ if (!pstream)
+ luaL_error(state, "Cannot use dfhack.interpreter() without output.");
+
+ int argc = lua_gettop(state);
+
+ const char *prompt = (argc >= 1 ? lua_tostring(state, 1) : NULL);
+ int env = (argc >= 2 && !lua_isnil(state,2) ? 2 : 0);
+ const char *hfile = (argc >= 3 ? lua_tostring(state, 3) : NULL);
+
+ lua_pushboolean(state, Lua::InterpreterLoop(*pstream, state, prompt, env, hfile));
+ return 1;
+}
+
+static const luaL_Reg dfhack_funcs[] = {
+ { "print", lua_dfhack_print },
+ { "println", lua_dfhack_println },
+ { "printerr", lua_dfhack_printerr },
+ { "traceback", traceback },
+ { "interpreter", lua_dfhack_interpreter },
+ { NULL, NULL }
+};
+
+lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state)
+{
+ if (!state)
+ state = luaL_newstate();
+
+ luaL_openlibs(state);
+ AttachDFGlobals(state);
+
+ // Replace the print function of the standard library
+ lua_pushcfunction(state, lua_dfhack_println);
+ lua_setglobal(state, "print");
+
+ // Create and initialize the dfhack global
+ lua_newtable(state);
+ luaL_setfuncs(state, dfhack_funcs, 0);
+ lua_setglobal(state, "dfhack");
+
+ // load dfhack.lua
+ Require(out, state, "dfhack");
+
+ return state;
+}
+
diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp
index 81712724..b9314f07 100644
--- a/library/LuaWrapper.cpp
+++ b/library/LuaWrapper.cpp
@@ -59,16 +59,6 @@ void LuaWrapper::field_error(lua_State *state, int index, const char *err, const
mode, (cname ? cname : "?"), (fname ? fname : "?"), err);
}
-void DFHack::PushDFObject(lua_State *state, type_identity *type, void *ptr)
-{
- push_object_internal(state, type, ptr, false);
-}
-
-void *DFHack::GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type)
-{
- return get_object_internal(state, type, val_index, exact_type, false);
-}
-
/* */
static int change_error(lua_State *state)
@@ -1320,7 +1310,7 @@ static int DoAttach(lua_State *state)
* Initialize access to DF objects from the interpreter
* context, unless it has already been done.
*/
-void DFHack::AttachDFGlobals(lua_State *state)
+void LuaWrapper::AttachDFGlobals(lua_State *state)
{
if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME))
{
diff --git a/library/include/Core.h b/library/include/Core.h
index 10b95a47..f73ab08e 100644
--- a/library/include/Core.h
+++ b/library/include/Core.h
@@ -135,6 +135,7 @@ namespace DFHack
DFHack::VersionInfo * vinfo;
DFHack::Windows::df_window * screen_window;
+ static void print(const char *format, ...);
static void printerr(const char *format, ...);
private:
diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h
index b2c86ec1..b9b4707d 100644
--- a/library/include/DataDefs.h
+++ b/library/include/DataDefs.h
@@ -360,23 +360,6 @@ namespace DFHack
void InitDataDefGlobals(Core *core);
- // LUA wrapper
-
- /**
- * Make DF objects available to the given interpreter.
- */
- DFHACK_EXPORT void AttachDFGlobals(lua_State *state);
-
- /**
- * Push the pointer onto the stack as a wrapped DF object of the given type.
- */
- DFHACK_EXPORT void PushDFObject(lua_State *state, type_identity *type, void *ptr);
-
- /**
- * Check that the value is a wrapped DF object of the given type, and if so return the pointer.
- */
- DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type = false);
-
template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; }
@@ -683,24 +666,6 @@ namespace DFHack {
flagarray_to_string<T>(&tmp, val);
return join_strings(sep, tmp);
}
-
- // LUA wrapper
-
- /**
- * Push the pointer onto the stack as a wrapped DF object of a specific type.
- */
- template<class T>
- void PushDFObject(lua_State *state, T *ptr) {
- PushDFObject(state, df::identity_traits<T>::get(), ptr);
- }
-
- /**
- * Check that the value is a wrapped DF object of the correct type, and if so return the pointer.
- */
- template<class T>
- T *GetDFObject(lua_State *state, int val_index, bool exact_type = false) {
- return (T*)GetDFObject(state, df::identity_traits<T>::get(), val_index, exact_type);
- }
}
#define ENUM_ATTR(enum,attr,val) (df::enum_traits<df::enum>::attrs(val).attr)
diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h
new file mode 100644
index 00000000..32e35201
--- /dev/null
+++ b/library/include/LuaTools.h
@@ -0,0 +1,92 @@
+/*
+https://github.com/peterix/dfhack
+Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#pragma once
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+
+#include "DataDefs.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+namespace DFHack { namespace Lua {
+ /**
+ * Create or initialize a lua interpreter with access to DFHack tools.
+ */
+ DFHACK_EXPORT lua_State *Open(color_ostream &out, lua_State *state = NULL);
+
+ /**
+ * Load a module using require().
+ */
+ DFHACK_EXPORT bool Require(color_ostream &out, lua_State *state,
+ const std::string &module, bool setglobal = false);
+
+ /**
+ * Push the pointer onto the stack as a wrapped DF object of the given type.
+ */
+ DFHACK_EXPORT void PushDFObject(lua_State *state, type_identity *type, void *ptr);
+
+ /**
+ * Check that the value is a wrapped DF object of the given type, and if so return the pointer.
+ */
+ DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type = false);
+
+ /**
+ * Push the pointer onto the stack as a wrapped DF object of a specific type.
+ */
+ template<class T>
+ void PushDFObject(lua_State *state, T *ptr) {
+ PushDFObject(state, df::identity_traits<T>::get(), ptr);
+ }
+
+ /**
+ * Check that the value is a wrapped DF object of the correct type, and if so return the pointer.
+ */
+ template<class T>
+ T *GetDFObject(lua_State *state, int val_index, bool exact_type = false) {
+ return (T*)GetDFObject(state, df::identity_traits<T>::get(), val_index, exact_type);
+ }
+
+ /**
+ * Invoke lua function via pcall. Returns true if success.
+ * If an error is signalled, and perr is true, it is printed and popped from the stack.
+ */
+ DFHACK_EXPORT bool SafeCall(color_ostream &out, lua_State *state, int nargs, int nres, bool perr = true);
+
+ /**
+ * Returns the ostream passed to SafeCall.
+ */
+ DFHACK_EXPORT color_ostream *GetOutput(lua_State *state);
+
+ /**
+ * Run an interactive interpreter loop if possible, or return false.
+ */
+ DFHACK_EXPORT bool InterpreterLoop(color_ostream &out, lua_State *state,
+ const char *prompt = NULL, int env = 0, const char *hfile = NULL);
+}}
+
diff --git a/library/include/LuaWrapper.h b/library/include/LuaWrapper.h
index d3f1337e..aa6e511b 100644
--- a/library/include/LuaWrapper.h
+++ b/library/include/LuaWrapper.h
@@ -214,5 +214,7 @@ namespace DFHack { namespace LuaWrapper {
void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum);
void IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct);
+
+ void AttachDFGlobals(lua_State *state);
}}
diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua
new file mode 100644
index 00000000..33d77432
--- /dev/null
+++ b/library/lua/dfhack.lua
@@ -0,0 +1,5 @@
+-- Common startup file for all dfhack plugins with lua support
+
+-- The global dfhack table is already created by C++ init
+-- code. Feed it back to the require() mechanism.
+return dfhack
diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp
index 9a277fb4..0886d2a3 100644
--- a/plugins/Dfusion/dfusion.cpp
+++ b/plugins/Dfusion/dfusion.cpp
@@ -21,6 +21,7 @@
#include "lua_FunctionCall.h"
#include "lua_Offsets.h"
#include "DataDefs.h"
+#include "LuaTools.h"
using std::vector;
using std::string;
@@ -42,11 +43,12 @@ DFhackCExport const char * plugin_name ( void )
return "dfusion";
}
-DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
+DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
{
lua::state st=lua::glua::Get();
+
//maybe remake it to run automaticaly
- DFHack::AttachDFGlobals(st);
+ Lua::Open(out, st);
lua::RegisterConsole(st);
lua::RegisterProcess(st);
@@ -64,11 +66,6 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
st.setglobal("WINDOWS");
#endif
- st.getglobal("Console");
- st.getfield("println");
- st.setglobal("print");
- st.pop();
-
commands.push_back(PluginCommand("dfusion","Run dfusion system (interactive i.e. can input further commands).",dfusion,true));
commands.push_back(PluginCommand("dfuse","Init dfusion system (not interactive).",dfuse,false));
commands.push_back(PluginCommand("lua", "Run interactive interpreter. Use 'lua <filename>' to run <filename> instead.",lua_run,true));
@@ -113,87 +110,6 @@ DFhackCExport command_result plugin_onupdate_DISABLED ( Core * c )
mymutex->unlock();
return CR_OK;
}
-
-void InterpreterLoop(color_ostream &out)
-{
-
- DFHack::CommandHistory hist;
- lua::state s=lua::glua::Get();
- string curline;
- out.print("Type quit to exit interactive lua interpreter.\n"
- "Shortcuts:\n"
- " '= foo' => '_1,_2,... = foo'\n"
- " '! foo' => 'print(foo)'\n"
- "Both assign the first result to '_'\n");
- assert(out.is_console());
- Console &con = static_cast<Console&>(out);
- int vcnt = 1;
-
- s.settop(0);
-
- for (;;) {
- con.lineedit("[lua]# ",curline,hist);
-
- if (curline.empty())
- continue;
- if (curline == "quit")
- break;
-
- hist.add(curline);
-
- try
- {
- char pfix = curline[0];
-
- if (pfix == '=' || pfix == '!')
- {
- curline = "return " + curline.substr(1);
-
- s.loadstring(curline);
- s.pcall(0, LUA_MULTRET);
- int numret = s.gettop();
-
- if (numret >= 1)
- {
- s.pushvalue(1);
- s.setglobal("_");
-
- if (pfix == '!')
- {
- s.getglobal("print");
- s.insert(1);
- s.pcall(numret,0);
- numret = 0;
- }
- }
-
- for (int i = 1; i <= numret; i++)
- {
- std::string name = stl_sprintf("_%d", vcnt++);
- s.pushvalue(i);
- s.setglobal(name);
-
- con.print("%s = ", name.c_str());
- s.getglobal("print");
- s.pushvalue(i);
- s.pcall(1,0);
- }
- }
- else
- {
- s.loadstring(curline);
- s.pcall();
- }
- }
- catch(lua::exception &e)
- {
- con.printerr("Error:%s\n",e.what());
- con.printerr("%s\n",lua::DebugDump(lua::glua::Get()).c_str());
- }
-
- s.settop(0);
- }
-}
command_result lua_run_file (color_ostream &out, std::vector <std::string> &parameters)
{
if(parameters.size()==0)
@@ -207,14 +123,14 @@ command_result lua_run (color_ostream &out, std::vector <std::string> &parameter
{
mymutex->lock();
lua::state s=lua::glua::Get();
- lua::SetConsole(s,out);
+
if(parameters.size()>0)
{
try{
s.loadfile(parameters[0]); //load file
for(size_t i=1;i<parameters.size();i++)
s.push(parameters[i]);
- s.pcall(parameters.size()-1,0);// run it
+ Lua::SafeCall(out, s, parameters.size()-1,0);// run it
}
catch(lua::exception &e)
{
@@ -224,7 +140,7 @@ command_result lua_run (color_ostream &out, std::vector <std::string> &parameter
}
else
{
- InterpreterLoop(out);
+ Lua::InterpreterLoop(out, s);
}
s.settop(0);// clean up
mymutex->unlock();
@@ -235,12 +151,10 @@ void RunDfusion(color_ostream &out, std::vector <std::string> &parameters)
mymutex->lock();
lua::state s=lua::glua::Get();
try{
- s.getglobal("err");
- int errpos=s.gettop();
s.loadfile("dfusion/init.lua"); //load script
for(size_t i=0;i<parameters.size();i++)
s.push(parameters[i]);
- s.pcall(parameters.size(),0,errpos);// run it
+ Lua::SafeCall(out, s, parameters.size(),0);
}
catch(lua::exception &e)
{
@@ -253,7 +167,6 @@ void RunDfusion(color_ostream &out, std::vector <std::string> &parameters)
command_result dfuse(color_ostream &out, std::vector <std::string> &parameters)
{
lua::state s=lua::glua::Get();
- lua::SetConsole(s,out);
s.push(1);
s.setglobal("INIT");
RunDfusion(out,parameters);
@@ -262,7 +175,6 @@ command_result dfuse(color_ostream &out, std::vector <std::string> &parameters)
command_result dfusion (color_ostream &out, std::vector <std::string> &parameters)
{
lua::state s=lua::glua::Get();
- lua::SetConsole(s,out);
s.push();
s.setglobal("INIT");
RunDfusion(out,parameters);
diff --git a/plugins/Dfusion/include/lua_Console.h b/plugins/Dfusion/include/lua_Console.h
index 227effa9..c6ac5011 100644
--- a/plugins/Dfusion/include/lua_Console.h
+++ b/plugins/Dfusion/include/lua_Console.h
@@ -7,7 +7,7 @@ namespace lua
{
void RegisterConsole(lua::state &st);
-void SetConsole(lua::state &st,DFHack::color_ostream& stream);
+
}
#endif \ No newline at end of file
diff --git a/plugins/Dfusion/src/lua_Console.cpp b/plugins/Dfusion/src/lua_Console.cpp
index 2a8222af..881ba5d2 100644
--- a/plugins/Dfusion/src/lua_Console.cpp
+++ b/plugins/Dfusion/src/lua_Console.cpp
@@ -1,64 +1,12 @@
#include "lua_Console.h"
+#include "LuaTools.h"
#include <sstream>
//TODO error management. Using lua error? or something other?
static DFHack::color_ostream* GetConsolePtr(lua::state &st)
{
- int t=st.gettop();
- st.getglobal("Console");
- st.getfield("__pointer");
- DFHack::color_ostream* c=static_cast<DFHack::color_ostream*>(lua_touserdata(st,-1));
- st.settop(t);
- return c;
-}
-
-static std::string lua_print_fmt(lua_State *L)
-{
- /* Copied from lua source to fully replicate builtin print */
- int n = lua_gettop(L); /* number of arguments */
- lua_getglobal(L, "tostring");
-
- std::stringstream ss;
-
- for (int i=1; i<=n; i++) {
- lua_pushvalue(L, -1); /* function to be called */
- lua_pushvalue(L, i); /* value to print */
- lua_call(L, 1, 1);
- const char *s = lua_tostring(L, -1); /* get result */
- if (s == NULL)
- luaL_error(L, "tostring must return a string to print");
- if (i>1)
- ss << '\t';
- ss << s;
- lua_pop(L, 1); /* pop result */
- }
-
- return ss.str();
-}
-
-static int lua_Console_print(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->print("%s", lua_print_fmt(S).c_str());
- return 0;
-}
-
-static int lua_Console_println(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->print("%s\n", lua_print_fmt(S).c_str());
- return 0;
-}
-
-static int lua_Console_printerr(lua_State *S)
-{
- lua::state st(S);
- DFHack::color_ostream* c=GetConsolePtr(st);
- c->printerr("%s", lua_print_fmt(S).c_str());
- return 0;
+ return DFHack::Lua::GetOutput(st);
}
static int lua_Console_clear(lua_State *S)
@@ -156,9 +104,6 @@ static int lua_Console_lineedit(lua_State *S)
}
const luaL_Reg lua_console_func[]=
{
- {"print",lua_Console_print},
- {"println",lua_Console_println},
- {"printerr",lua_Console_printerr},
{"clear",lua_Console_clear},
{"gotoxy",lua_Console_gotoxy},
{"color",lua_Console_color},
@@ -183,17 +128,3 @@ void lua::RegisterConsole(lua::state &st)
//TODO add color consts
st.setglobal("Console");
}
-void lua::SetConsole(lua::state &st,DFHack::color_ostream& stream)
-{
- int top=st.gettop();
- st.getglobal("Console");
- if(st.is<lua::nil>())
- {
- st.pop();
- st.newtable();
- }
-
- st.pushlightuserdata(&stream);
- st.setfield("__pointer");
- st.settop(top);
-} \ No newline at end of file