diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2023-09-30 11:51:09 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2023-09-30 11:51:09 -0400 |
commit | de61551df3219dae2238591bae5fa7b6c857e6b0 (patch) | |
tree | f862de93761661afba4cd3299507b3e6f2ebfd8d | |
parent | 48dc344a9e65451c9e2b267fba7d3e01bdbbf801 (diff) |
DRTVWR-589: Emulate print() better, show output on Lua floater.
Break out a lua_print_msg() function common to print_debug(), print_info() and
print_warning(). Instead of accepting a single argument, lua_print_msg()
accepts arbitrary arguments, passing each to the Lua tostring() function and
concatenating the results. In addition to returning the combined string to its
caller for level-appropriate logging, it also posts the message to a "lua
output" LLEventPump for any interested party.
Make LLFloaterLUADebug listen on "lua output" when the floater is constructed,
storing the connection in an LLTempBoundListener to stop listening when the
floater is destroyed. Append each message to the floater's output panel with a
line break.
Make LLTextEditor::addLineBreakChar() public. insertText("\n") only appends a
little rectangle glyph.
Enlarge the text capacity of the floater's output panel to be able to report
whatever messages a Lua script wants to print.
Add diagnostic logging for posting events from Lua, and receiving events to
forward to Lua.
Since lua_pop() is a macro implemented on lua_settop(), replace the awkward
construct lua_pop(L, lua_gettop(L)) with lua_settop(L, 0).
Use lambdas instead of std::bind() to connect LuaListener and LLLeapListener.
-rw-r--r-- | indra/llui/lltexteditor.h | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterluadebug.cpp | 12 | ||||
-rw-r--r-- | indra/newview/llfloaterluadebug.h | 3 | ||||
-rw-r--r-- | indra/newview/llluamanager.cpp | 91 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_lua_debug.xml | 1 |
5 files changed, 82 insertions, 27 deletions
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index f3939248c2..ec2b9a4b7d 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -241,7 +241,9 @@ protected: // Undoable operations void addChar(llwchar c); // at mCursorPos S32 addChar(S32 pos, llwchar wc); +public: void addLineBreakChar(BOOL group_together = FALSE); +protected: S32 overwriteChar(S32 pos, llwchar wc); void removeChar(); S32 removeChar(S32 pos); diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp index 9ca554d4ad..44454d7be0 100644 --- a/indra/newview/llfloaterluadebug.cpp +++ b/indra/newview/llfloaterluadebug.cpp @@ -54,6 +54,14 @@ BOOL LLFloaterLUADebug::postBuild() mResultOutput = getChild<LLTextEditor>("result_text"); mLineInput = getChild<LLLineEditor>("lua_cmd"); mScriptPath = getChild<LLLineEditor>("script_path"); + mOutConnection = LLEventPumps::instance().obtain("lua output") + .listen("LLFloaterLUADebug", + [mResultOutput=mResultOutput](const LLSD& data) + { + mResultOutput->insertText(data.asString()); + mResultOutput->addLineBreakChar(true); + return false; + }); getChild<LLButton>("execute_btn")->setClickedCallback(boost::bind(&LLFloaterLUADebug::onExecuteClicked, this)); getChild<LLButton>("browse_btn")->setClickedCallback(boost::bind(&LLFloaterLUADebug::onBtnBrowse, this)); @@ -77,7 +85,7 @@ void LLFloaterLUADebug::onExecuteClicked() std::string cmd = mLineInput->getText(); LLLUAmanager::runScriptLine(cmd, [this](std::string msg) { - mResultOutput->setText(msg); + mResultOutput->insertText(msg); }); } @@ -107,7 +115,7 @@ void LLFloaterLUADebug::runSelectedScript(const std::vector<std::string> &filena mScriptPath->setText(filepath); LLLUAmanager::runScriptFile(filepath, [this](std::string msg) { - mResultOutput->setText(msg); + mResultOutput->insertText(msg); }); } } diff --git a/indra/newview/llfloaterluadebug.h b/indra/newview/llfloaterluadebug.h index 300d954aea..fd61e29ebe 100644 --- a/indra/newview/llfloaterluadebug.h +++ b/indra/newview/llfloaterluadebug.h @@ -26,6 +26,7 @@ #ifndef LL_LLFLOATERLUADEBUG_H #define LL_LLFLOATERLUADEBUG_H +#include "llevents.h" #include "llfloater.h" extern "C" @@ -54,6 +55,8 @@ class LLFloaterLUADebug : void runSelectedScript(const std::vector<std::string> &filenames); private: + LLTempBoundListener mOutConnection; + LLTextEditor* mResultOutput; LLLineEditor* mLineInput; LLLineEditor* mScriptPath; diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index b18708bd84..2cc809ff0f 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -66,6 +66,7 @@ extern "C" #include <cstring> // std::memcpy() #include <map> #include <memory> // std::unique_ptr +#include <sstream> #include <string_view> #include <vector> @@ -109,8 +110,10 @@ public: super(getUniqueKey()), mState(L), mReplyPump(LLUUID::generateNewID().asString()), - mListener(new LLLeapListener(std::bind(&LuaListener::connect, this, - std::placeholders::_1, std::placeholders::_2))) + mListener( + new LLLeapListener( + [this](LLEventPump& pump, const std::string& listener) + { return connect(pump, listener); })) { mReplyConnection = connect(mReplyPump, "LuaListener"); } @@ -136,13 +139,15 @@ private: LLBoundListener connect(LLEventPump& pump, const std::string& listener) { - return pump.listen(listener, - std::bind(&LuaListener::call_lua, mState, pump.getName(), - std::placeholders::_1)); + return pump.listen( + listener, + [mState=mState, pumpname=pump.getName()](const LLSD& data) + { return call_lua(mState, pumpname, data); }); } static bool call_lua(lua_State* L, const std::string& pump, const LLSD& data) { + LL_INFOS("Lua") << "LuaListener::call_lua('" << pump << "', " << data << ")" << LL_ENDL; if (! lua_checkstack(L, 3)) { LL_WARNS("Lua") << "Cannot extend Lua stack to call listen_events() callback" @@ -275,28 +280,63 @@ int name##_::call(lua_State* L) // ... supply method body here, referencing 'L' ... // } -lua_function(print_debug) +// This function consumes ALL Lua stack arguments and returns concatenated +// message string +std::string lua_print_msg(lua_State* L, const std::string_view& level) { + // On top of existing Lua arguments, push 'where' info + luaL_checkstack(L, 1, nullptr); luaL_where(L, 1); - LL_DEBUGS("Lua") << lua_tostring(L, 2) << ": " << lua_tostring(L, 1) << LL_ENDL; - lua_pop(L, 2); + // start with the 'where' info at the top of the stack + std::ostringstream out; + out << lua_tostring(L, -1); + lua_pop(L, 1); + const char* sep = ""; // 'where' info ends with ": " + // now iterate over arbitrary args, calling Lua tostring() on each and + // concatenating with separators + for (int p = 1; p <= lua_gettop(L); ++p) + { + out << sep; + sep = " "; + // push Lua tostring() function -- note, semantically different from + // lua_tostring()! + lua_getglobal(L, "tostring"); + // Now the stack is arguments 1 .. N, plus tostring(). + // Rotate downwards, producing stack args 2 .. N, tostring(), arg1. + lua_rotate(L, 1, -1); + // pop tostring() and arg1, pushing tostring(arg1) + // (ignore potential error code from lua_pcall() because, if there was + // an error, we expect the stack top to be an error message -- which + // we'll print) + lua_pcall(L, 1, 1, 0); + // stack now holds args 2 .. N, tostring(arg1) + out << lua_tostring(L, -1); + } + // pop everything + lua_settop(L, 0); + // capture message string + std::string msg{ out.str() }; + // put message out there for any interested party (*koff* LLFloaterLUADebug *koff*) + LLEventPumps::instance().obtain("lua output").post(stringize(level, ": ", msg)); + return msg; +} + +lua_function(print_debug) +{ + LL_DEBUGS("Lua") << lua_print_msg(L, "DEBUG") << LL_ENDL; return 0; } // also used for print(); see LuaState constructor lua_function(print_info) { - luaL_where(L, 1); - LL_INFOS("Lua") << lua_tostring(L, 2) << ": " << lua_tostring(L, 1) << LL_ENDL; - lua_pop(L, 2); + LL_INFOS("Lua") << lua_print_msg(L, "INFO") << LL_ENDL; return 0; } lua_function(print_warning) { - luaL_where(L, 1); - LL_WARNS("Lua") << lua_tostring(L, 2) << ": " << lua_tostring(L, 1) << LL_ENDL; - lua_pop(L, 2); + LL_WARNS("Lua") << lua_print_msg(L, "WARN") << LL_ENDL; return 0; } @@ -421,7 +461,7 @@ lua_function(get_avatar_name) { std::string name = gAgentAvatarp->getFullname(); luaL_checkstack(L, 1, nullptr); - lua_pushstring(L, name.c_str()); + lua_pushstdstring(L, name); return 1; } @@ -513,7 +553,7 @@ lua_function(show_notification) LLNotificationsUtil::add(notification); } - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -540,7 +580,7 @@ lua_function(add_menu_item) gMenuBarView->findChildMenuByName(menu, true)->append(menu_item); } - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -568,7 +608,7 @@ lua_function(add_menu) gMenuBarView->appendMenu(menu); } - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -588,7 +628,7 @@ lua_function(add_branch) gMenuBarView->findChildMenuByName(menu, true)->appendMenu(branch); } - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -610,7 +650,7 @@ lua_function(rez_prim) LL_INFOS() << "Rezing a prim: type " << LLPrimitive::pCodeToString(type) << ", coordinates: " << obj_pos << " Success: " << res << LL_ENDL; - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -664,7 +704,7 @@ lua_function(move_by) } move_to_dest(dest, L, response_cb); - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -690,7 +730,7 @@ lua_function(move_to) } move_to_dest(dest, L, response_cb); - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); return 0; } @@ -716,15 +756,16 @@ lua_function(run_ui_command) } sUIListener.call(event); - lua_pop(L, top); + lua_settop(L, 0); return 0; } lua_function(post_on) { - std::string pumpname{ lua_tostring(L, 1) }; + std::string pumpname{ lua_tostdstring(L, 1) }; LLSD data{ lua_tollsd(L, 2) }; lua_pop(L, 2); + LL_INFOS("Lua") << "post_on('" << pumpname << "', " << data << ")" << LL_ENDL; LLEventPumps::instance().obtain(pumpname).post(data); return 0; } @@ -804,7 +845,7 @@ lua_function(await_event) auto timeout{ lua_tonumber(L, 2) }; // with no 3rd argument, should be LLSD() auto dftval{ lua_tollsd(L, 3) }; - lua_pop(L, lua_gettop(L)); + lua_settop(L, 0); result = llcoro::suspendUntilEventOnWithTimeout(pumpname, timeout, dftval); } else diff --git a/indra/newview/skins/default/xui/en/floater_lua_debug.xml b/indra/newview/skins/default/xui/en/floater_lua_debug.xml index 0de26161e7..f03739f7c2 100644 --- a/indra/newview/skins/default/xui/en/floater_lua_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_lua_debug.xml @@ -55,6 +55,7 @@ layout="topleft" name="result_text" follows="left|top" + max_length="65536" width="515" top_delta="40" word_wrap="true" /> |