From b4583fac09657cb64ed02e82e12ce69c4ace225d Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 12 Feb 2024 17:10:42 -0500
Subject: WIP: Changes towards supporting Lua console help text.

---
 indra/llcommon/lua_function.cpp     | 65 +++++++++++++++++++++++++++++++++++--
 indra/llcommon/lua_function.h       |  4 ++-
 indra/llui/lltexteditor.cpp         |  2 +-
 indra/llui/lltexteditor.h           |  3 +-
 indra/newview/llfloaterluadebug.cpp |  8 ++---
 5 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index 07e0c1fac2..455e853e8f 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -25,6 +25,9 @@
 #include "llsdutil.h"
 #include "lualistener.h"
 
+/*****************************************************************************
+*   luau namespace
+*****************************************************************************/
 namespace
 {
     // can't specify free function free() as a unique_ptr deleter
@@ -53,6 +56,9 @@ int lluau::dostring(lua_State* L, const std::string& desc, const std::string& te
     return lua_pcall(L, 0, LUA_MULTRET, 0);
 }
 
+/*****************************************************************************
+*   Lua <=> C++ conversions
+*****************************************************************************/
 std::string lua_tostdstring(lua_State* L, int index)
 {
     size_t len;
@@ -414,6 +420,9 @@ void lua_pushllsd(lua_State* L, const LLSD& data)
     }
 }
 
+/*****************************************************************************
+*   LuaState class
+*****************************************************************************/
 LuaState::LuaState(script_finished_fn cb):
     mCallback(cb),
     mState(luaL_newstate())
@@ -499,7 +508,9 @@ std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string&
     return result;
 }
 
-
+/*****************************************************************************
+*   LuaPopper class
+*****************************************************************************/
 LuaPopper::~LuaPopper()
 {
     if (mCount)
@@ -508,6 +519,9 @@ LuaPopper::~LuaPopper()
     }
 }
 
+/*****************************************************************************
+*   LuaFunction class
+*****************************************************************************/
 LuaFunction::LuaFunction(const std::string_view& name, lua_CFunction function,
                          const std::string_view& helptext)
 {
@@ -539,7 +553,9 @@ LuaFunction::Registry& LuaFunction::getRegistry()
     return registry;
 }
 
-
+/*****************************************************************************
+*   lua_what
+*****************************************************************************/
 std::ostream& operator<<(std::ostream& out, const lua_what& self)
 {
     switch (lua_type(self.L, self.index))
@@ -595,6 +611,9 @@ std::ostream& operator<<(std::ostream& out, const lua_what& self)
     return out;
 }
 
+/*****************************************************************************
+*   lua_stack
+*****************************************************************************/
 std::ostream& operator<<(std::ostream& out, const lua_stack& self)
 {
     const char* sep = "stack: [";
@@ -607,7 +626,49 @@ std::ostream& operator<<(std::ostream& out, const lua_stack& self)
     return out;
 }
 
+/*****************************************************************************
+*   DebugExit
+*****************************************************************************/
 DebugExit::~DebugExit()
 {
     LL_DEBUGS("Lua") << "exit " << mName << LL_ENDL;
 }
+
+/*****************************************************************************
+*   help()
+*****************************************************************************/
+lua_function(help,
+             "help(): list viewer's Lua functions\n"
+             "help(function): show help string for specific function")
+{
+    auto& luapump{ LLEventPumps::instance().obtain("lua output") };
+    const auto& registered{ LuaFunction::getRegistered() };
+    if (! lua_gettop(L))
+    {
+        // no arguments passed: list all lua_functions
+        for (const auto& [name, pair] : registered)
+        {
+            const auto& [fptr, helptext] = pair;
+            luapump.post(helptext);
+        }
+    }
+    else
+    {
+        // arguments passed: list each of the specified lua_functions
+        for (int idx = 1, top = lua_gettop(L); idx <= top; ++idx)
+        {
+            auto arg{ lua_tostdstring(L, idx) };
+            if (auto found = registered.find(arg); found != registered.end())
+            {
+                luapump.post(found->second.second);
+            }
+            else
+            {
+                luapump.post(arg + ": NOT FOUND");
+            }
+        }
+        // pop all arguments
+        lua_settop(L, 0);
+    }
+    return 0;                       // void return
+}
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
index c23bf533ba..3129b5eaca 100644
--- a/indra/llcommon/lua_function.h
+++ b/indra/llcommon/lua_function.h
@@ -131,8 +131,10 @@ public:
 
     static lua_CFunction get(const std::string& key);
 
-private:
     using Registry = std::map<std::string, std::pair<lua_CFunction, std::string>>;
+    static const Registry& getRegistered() { return getRegistry(); }
+
+private:
     static Registry& getRegistry();
 };
 
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3d2a426913..99154bab83 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1504,7 +1504,7 @@ void LLTextEditor::cleanStringForPaste(LLWString & clean_string)
 }
 
 
-void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)
+void LLTextEditor::pasteTextWithLinebreaks(const LLWString & clean_string)
 {
 	std::basic_string<llwchar>::size_type start = 0;
 	std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index ec2b9a4b7d..6cc2c32d4e 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -289,6 +289,8 @@ protected:
 	void				updateLinkSegments();
 	void				keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
 	class LLViewBorder*	mBorder;
+	void			pasteTextWithLinebreaks(const LLWString & clean_string);
+//	void			pasteTextWithLinebreaks(const std::string & clean_string);
 
 private:
 	//
@@ -296,7 +298,6 @@ private:
 	//
 	void	        pasteHelper(bool is_primary);
 	void			cleanStringForPaste(LLWString & clean_string);
-	void			pasteTextWithLinebreaks(LLWString & clean_string);
 
 	void			onKeyStroke();
 
diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp
index d7b46eaa71..245cc88f79 100644
--- a/indra/newview/llfloaterluadebug.cpp
+++ b/indra/newview/llfloaterluadebug.cpp
@@ -57,7 +57,7 @@ BOOL LLFloaterLUADebug::postBuild()
         .listen("LLFloaterLUADebug",
                 [mResultOutput=mResultOutput](const LLSD& data)
                 {
-                    mResultOutput->insertText(data.asString());
+                    mResultOutput->pasteTextWithLinebreaks(data.asString());
                     mResultOutput->addLineBreakChar(true);
                     return false;
                 });
@@ -120,13 +120,13 @@ void LLFloaterLUADebug::completion(int count, const LLSD& result)
     {
         // error: show error message
         mResultOutput->insertText("*** ");
-        mResultOutput->insertText(result.asString());
+        mResultOutput->pasteTextWithLinebreaks(result.asString());
         return;
     }
     if (count == 1)
     {
         // single result
-        mResultOutput->insertText(stringize(result));
+        mResultOutput->pasteTextWithLinebreaks(stringize(result));
         return;
     }
     // 0 or multiple results
@@ -134,7 +134,7 @@ void LLFloaterLUADebug::completion(int count, const LLSD& result)
     for (const auto& item : llsd::inArray(result))
     {
         mResultOutput->insertText(sep);
-        mResultOutput->insertText(stringize(item));
+        mResultOutput->pasteTextWithLinebreaks(stringize(item));
         sep = ", ";
     }
 }
-- 
cgit v1.2.3