Hi all! I'd like to hear your comments on a small hack which I added to our lua hooks code: output redirection for print() and io.write().
The rationale behind this is that lua code (be it hooks or even custom commands), which likes to "talk" to the user, most likely use the above mentioned built-ins. These however work directly on STDOUT and this imposes at least three problems: 1) users cannot distinguish lua output from the application's normal output 2) like 1), but even worse for (remote) stdio: for remote_stdio the problem is that the user does not even see it (while he maybe wants to), while for normal stdio the output possibly leads to parsing errors 3) monotone's logging facility (--log) won't catch the output either, which makes it f.e. hard to debug netsync hooks which are executed in daemon mode (f.e. Debian's start-stop-daemon has no way to redirect the daemon's output somewhere else, the application has to take care of that itself or you need to write some simple wrapper script for that) So the patch basically introduces a new function "message" (naming proposals welcome...) which calls our print macro with the given text input while prefixing every line with "lua: ", and secondly overwrites print() and io.write() at startup to use the new implementation. Some notes: 1) io.stdout:write() and io.stderr:write() are still available - partially because I could not find a way to overwrite / disable them (they're of userdata type...) and partially because I still wanted to give the not-so-usual lua hacker a chance to really write to stdout or stderr if he really wants to do so 2) I haven't yet find a way to print something without a newline with our sanity setup, so io.write() always up with a newline which is different from the original behaviour, so it should be documented at least. 3) While both, io.write() and print() previously outputted on stdout, the new output goes exclusively to stderr (otherwise the points 1) and 2) above wouldn't be easily solvable) - so this is surely another thing which needs to be documented, in case somebody expects his (lua) output exclusively on stdout. So what do you think? Is this something we should do or do you think this is a bad idea? Thanks, Thomas. -- GPG-Key 0x160D1092 | tommyd3...@jabber.ccc.de | http://thomaskeller.biz Please note that according to the EU law on data retention, information on every electronic information exchange might be retained for a period of six months or longer: http://www.vorratsdatenspeicherung.de/?lang=en
# # old_revision [3085ca18b6493371676bbd39d757ff29112404bc] # # patch "lua_hooks.cc" # from [d4f06492ebfd19893156cf0021b7afef29009332] # to [b549dbc88019ef637da9a1cd2205162485b1d0b2] # ============================================================ --- lua_hooks.cc d4f06492ebfd19893156cf0021b7afef29009332 +++ lua_hooks.cc b549dbc88019ef637da9a1cd2205162485b1d0b2 @@ -30,6 +30,7 @@ #include "cmd.hh" #include "commands.hh" #include "globish.hh" +#include "simplestring_xform.hh" // defined in std_hooks.c, generated from std_hooks.lua extern char const std_hooks_constant[]; @@ -77,6 +78,38 @@ extern "C" lua_pushnil(LS); return 1; } + // taken from http://medek.wordpress.com/2009/02/03/wrapping-lua-errors-and-print-function/ + static int + monotone_message(lua_State *LS) + { + int nArgs = lua_gettop(LS); + lua_getglobal(LS, "tostring"); + + std::string ret; + for (int i = 1; i <= nArgs; ++i) + { + const char *s; + lua_pushvalue(LS, -1); + lua_pushvalue(LS, i); + lua_call(LS, 1, 1); + s = lua_tostring(LS, -1); + if (s == NULL) + return luaL_error( + LS, LUA_QL("tostring") " must return a string to ", LUA_QL("print") + ); + + if (i > 1) + ret.append("\t"); + + ret.append(s); + lua_pop(LS, 1); + } + + string prefixed; + prefix_lines_with(_("lua: "), ret, prefixed); + P(F("%s") % prefixed); + return 0; + } } app_state* @@ -116,6 +149,7 @@ lua_hooks::lua_hooks(app_state * app) luaL_openlibs(st); lua_register(st, "get_confdir", monotone_get_confdir_for_lua); + lua_register(st, "message", monotone_message); add_functions(st); // Disable any functions we don't want. This is easiest @@ -132,6 +166,21 @@ lua_hooks::lua_hooks(app_state * app) "<disabled dangerous functions>")) throw oops("lua error while disabling existing functions"); + // redirect output to internal message handler which calls into + // our user interface code. Note that we send _everything_ to stderr + // or as out-of-band progress stream to keep our stdout clean + static char const redirect_output[] = + "io.write = function(...) " + " message(...) " + "end " + "print = function(...) " + " message(...) " + "end "; + + if (!run_string(st, redirect_output, + "<redirect output>")) + throw oops("lua error while redirecting output"); + map_of_lua_to_app.insert(make_pair(st, app)); }
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Monotone-devel mailing list Monotone-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/monotone-devel