summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2023-09-30 11:51:09 -0400
committerNat Goodspeed <nat@lindenlab.com>2023-09-30 11:51:09 -0400
commitde61551df3219dae2238591bae5fa7b6c857e6b0 (patch)
treef862de93761661afba4cd3299507b3e6f2ebfd8d
parent48dc344a9e65451c9e2b267fba7d3e01bdbbf801 (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.h2
-rw-r--r--indra/newview/llfloaterluadebug.cpp12
-rw-r--r--indra/newview/llfloaterluadebug.h3
-rw-r--r--indra/newview/llluamanager.cpp91
-rw-r--r--indra/newview/skins/default/xui/en/floater_lua_debug.xml1
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" />