diff options
| author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2025-03-14 16:08:42 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-14 16:08:42 +0200 |
| commit | e2333b4d312301206f80f60e9c2f0258bc8e6235 (patch) | |
| tree | f85fc4db056330c8cfb63d4e3045b77db182facd | |
| parent | 7aad509d19c75277519dbcf119c3ba2e1f8a9c7c (diff) | |
| parent | da0a819d64514cad17cf306c3ebe2ac79db8283a (diff) | |
Merge pull request #3701 from secondlife/marchcat/lua_editor
Lua editor: WIP updates
| -rw-r--r-- | indra/llui/llkeywords.cpp | 92 | ||||
| -rw-r--r-- | indra/newview/app_settings/keywords_lua_default.xml | 7 | ||||
| -rw-r--r-- | indra/newview/llpreviewscript.cpp | 71 | ||||
| -rw-r--r-- | indra/newview/llpreviewscript.h | 33 | ||||
| -rw-r--r-- | indra/newview/llscripteditor.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llscripteditor.h | 3 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_script_ed.xml | 10 |
7 files changed, 132 insertions, 92 deletions
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index a81cd8affb..7064e270a4 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -359,8 +359,11 @@ void LLKeywords::processTokensGroup(const LLSD& tokens, std::string_view group) break; case LLKeywordToken::TT_FUNCTION: tooltip = getAttribute("return") + " " + outer_itr->first + "(" + getArguments(arguments) + ");"; - tooltip.append("\nEnergy: "); - tooltip.append(getAttribute("energy").empty() ? "0.0" : getAttribute("energy")); + if (std::stod(getAttribute("energy")) >= 0) + { + tooltip.append("\nEnergy: "); + tooltip.append(getAttribute("energy").empty() ? "0.0" : getAttribute("energy")); + } if (!getAttribute("sleep").empty()) { tooltip += ", Sleep: " + getAttribute("sleep"); @@ -675,35 +678,86 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW // check against words llwchar prev = cur > base ? *(cur-1) : 0; - if( !iswalnum( prev ) && (prev != '_') ) + if (!iswalnum(prev) && prev != '_' && prev != '.') { - const llwchar* p = cur; - while( iswalnum( *p ) || (*p == '_') - || (mLuauLanguage && *p == '.') ) // Allow dots in Lua to pass the functions. For example, "ll.Say()" instead of "llSay()" in LSL + const llwchar* word_start = cur; + S32 namespace_dots = 0; + const llwchar* last_dot = nullptr; + + // Find the full extent of the word, potentially including namespace dots + while (iswalnum(*cur) || *cur == '_' || (mLuauLanguage && *cur == '.' && iswalnum(*(cur+1)))) { - p++; + if (mLuauLanguage && *cur == '.') + { + namespace_dots++; + last_dot = cur; + } + cur++; } - S32 seg_len = (S32)(p - cur); - if( seg_len > 0 ) + + S32 seg_len = (S32)(cur - word_start); + if (seg_len > 0) { - WStringMapIndex word( cur, seg_len ); - word_token_map_t::iterator map_iter = mWordTokenMap.find(word); - if( map_iter != mWordTokenMap.end() ) + S32 seg_start = (S32)(word_start - base); + S32 seg_end = seg_start + seg_len; + + // First try to match the whole token (including dots for Lua namespaces) + WStringMapIndex whole_token(word_start, seg_len); + word_token_map_t::iterator map_iter = mWordTokenMap.find(whole_token); + + if (map_iter != mWordTokenMap.end()) { + // Found a match for the complete token (including any namespace) LLKeywordToken* cur_token = map_iter->second; - S32 seg_start = (S32)(cur - base); - S32 seg_end = seg_start + seg_len; + insertSegments(wtext, *seg_list, cur_token, text_len, seg_start, seg_end, style, editor); + } + else if (namespace_dots > 0 && mLuauLanguage) + { + // If using Lua and we have namespace dots but didn't match the whole token, + // check if we have a match for just the namespace prefix (e.g., "ll") + if (last_dot > word_start) + { + // Get the namespace prefix (part before the first dot) + S32 prefix_len = (S32)(last_dot - word_start); + WStringMapIndex prefix_token(word_start, prefix_len); + map_iter = mWordTokenMap.find(prefix_token); + + if (map_iter != mWordTokenMap.end()) + { + // Found a match for the namespace prefix, highlight just that part + LLKeywordToken* cur_token = map_iter->second; + insertSegments(wtext, *seg_list, cur_token, text_len, seg_start, seg_start + prefix_len, style, editor); - // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; + // Now try to match the function part (after the dot) + const llwchar* func_part = last_dot + 1; + S32 func_len = (S32)(cur - func_part); - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); + if (func_len > 0) + { + // Look for complete function matches + WStringMapIndex func_token(func_part, func_len); + map_iter = mWordTokenMap.find(func_token); + + if (map_iter != mWordTokenMap.end()) + { + // Found a match for the function part + LLKeywordToken* cur_token = map_iter->second; + insertSegments(wtext, *seg_list, cur_token, text_len, seg_start, seg_end, style, editor); + } + else + { + // No token found, continue without incrementing cur + // since we already advanced it while collecting the word + } + } + } + } } - cur += seg_len; - continue; + continue; // Continue to next token regardless of match } } - if( *cur && *cur != '\n' ) + if (*cur && *cur != '\n') { cur++; } diff --git a/indra/newview/app_settings/keywords_lua_default.xml b/indra/newview/app_settings/keywords_lua_default.xml index d667e05501..d4b3d3476b 100644 --- a/indra/newview/app_settings/keywords_lua_default.xml +++ b/indra/newview/app_settings/keywords_lua_default.xml @@ -7454,6 +7454,13 @@ </map> <key>functions</key><!-- TODO: Adjust functions to match the new format --> <map> + <key>ll</key> + <map> + <key>energy</key> + <real>-1.0</real> + <key>tooltip</key> + <string>ll namespace.</string> + </map> <key>ll.Abs</key> <map> <key>energy</key> diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 28988f9564..98c28ffadc 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -90,20 +90,8 @@ #include "lltoggleablemenu.h" #include "llmenubutton.h" #include "llinventoryfunctions.h" +#include <regex> -const std::string HELLO_LSL = - "default\n" - "{\n" - " state_entry()\n" - " {\n" - " llSay(0, \"Hello, Avatar!\");\n" - " }\n" - "\n" - " touch_start(integer total_number)\n" - " {\n" - " llSay(0, \"Touched.\");\n" - " }\n" - "}\n"; const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal"; const std::string DEFAULT_SCRIPT_NAME = "New Script"; // *TODO:Translate? @@ -142,6 +130,19 @@ static bool have_lua_enabled(const LLUUID& object_id) return false; } +// TEMPORARY: Quick check to see if the code is Lua +// since we don't have another way to determine the language yet +static bool is_lua_script(const std::string& code) +{ + // Check for LSL's signature "default" state pattern + std::regex lsl_pattern("\\s*default\\s*\\{"); + if (std::regex_search(code, lsl_pattern)) + return false; + + // "default" state not found, assuming it's Lua + return true; +} + /// --------------------------------------------------------------------------- /// LLLiveLSLFile /// --------------------------------------------------------------------------- @@ -396,9 +397,9 @@ LLScriptEdCore::LLScriptEdCore( LLScriptEdContainer* container, const std::string& sample, const LLHandle<LLFloater>& floater_handle, - void (*load_callback)(void*), - void (*save_callback)(void*, bool), - void (*search_replace_callback) (void* userdata), + script_ed_callback_t load_callback, + save_callback_t save_callback, + script_ed_callback_t search_replace_callback, void* userdata, bool live, S32 bottom_pad) @@ -1617,7 +1618,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata) self->mScriptEd = new LLScriptEdCore( self, - HELLO_LSL, + std::string(), self->getHandle(), LLPreviewLSL::onLoad, LLPreviewLSL::onSave, @@ -1758,12 +1759,6 @@ void LLPreviewLSL::loadAsset() getChildView("lock")->setVisible( !is_modifiable); mScriptEd->getChildView("Insert...")->setEnabled(is_modifiable); } - else - { - mScriptEd->setScriptText(std::string(HELLO_LSL), true); - mScriptEd->setEnableEditing(true); - mAssetStatus = PREVIEW_ASSET_LOADED; - } } @@ -1942,6 +1937,12 @@ void LLPreviewLSL::onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType t preview->mScriptEd->setEnableEditing(is_modifiable); preview->mScriptEd->setAssetID(asset_uuid); preview->mAssetStatus = PREVIEW_ASSET_LOADED; + + // Temporary hack to determine if the script is LSL or SLua when loaded from the inventory. + bool is_lua = is_lua_script(std::string(buffer.begin(), buffer.end())); + preview->mScriptEd->mEditor->setLuauLanguage(is_lua); + preview->mScriptEd->mCompileTarget->setValue(is_lua ? "luau" : "lsl-luau"); + preview->mScriptEd->processKeywords(is_lua); } else { @@ -1979,7 +1980,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata) self->mScriptEd = new LLScriptEdCore( self, - HELLO_LSL, + std::string(), self->getHandle(), &LLLiveLSLEditor::onLoad, &LLLiveLSLEditor::onSave, @@ -2007,7 +2008,7 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : bool LLLiveLSLEditor::postBuild() { - mResetButton = getChild<LLButton>("reset"); + mResetButton = getChild<LLButton>("Reset"); mResetButton->setClickedCallback([&](LLUICtrl*, const LLSD&) { onReset(); }); mRunningCheckbox = getChild<LLCheckBoxCtrl>("running"); @@ -2153,26 +2154,6 @@ void LLLiveLSLEditor::loadAsset() */ } } - else - { - mScriptEd->setScriptText(std::string(HELLO_LSL), true); - mScriptEd->enableSave(false); - LLPermissions perm; - perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID()); - perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); - mItem = new LLViewerInventoryItem(mItemUUID, - mObjectUUID, - perm, - LLUUID::null, - LLAssetType::AT_LSL_TEXT, - LLInventoryType::IT_LSL, - DEFAULT_SCRIPT_NAME, - DEFAULT_SCRIPT_DESC, - LLSaleInfo::DEFAULT, - LLInventoryItemFlags::II_FLAGS_NONE, - time_corrected()); - mAssetStatus = PREVIEW_ASSET_LOADED; - } requestExperiences(); } diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 430ca4cc76..117be03fc6 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -82,15 +82,19 @@ class LLScriptEdCore : public LLPanel friend class LLScriptEdContainer; friend class LLFloaterGotoLine; +public: + typedef boost::function<void(void*)> script_ed_callback_t; + typedef boost::function<void(void*, bool)> save_callback_t; + protected: // Supposed to be invoked only by the container. LLScriptEdCore( LLScriptEdContainer* container, const std::string& sample, const LLHandle<LLFloater>& floater_handle, - void (*load_callback)(void* userdata), - void (*save_callback)(void* userdata, bool close_after_save), - void (*search_replace_callback)(void* userdata), + script_ed_callback_t load_callback, + save_callback_t save_callback, + script_ed_callback_t search_replace_callback, void* userdata, bool live, S32 bottom_pad = 0); // pad below bottom row of buttons @@ -139,11 +143,11 @@ public: LLUUID getAssociatedExperience()const; void setAssociatedExperience( const LLUUID& experience_id ); - void setScriptName(const std::string& name){mScriptName = name;}; + void setScriptName(const std::string& name) { mScriptName = name; } - void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;}; + void setItemRemoved(bool script_removed) { mScriptRemoved = script_removed; } - void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; }; + void setAssetID(const LLUUID& asset_id) { mAssetID = asset_id; } LLUUID getAssetID() { return mAssetID; } bool isFontSizeChecked(const LLSD &userdata); @@ -152,16 +156,15 @@ public: virtual bool handleKeyHere(KEY key, MASK mask); void selectAll() { mEditor->selectAll(); } + void enableSave(bool b) { mEnableSave = b; } + bool hasChanged(); + private: void onBtnDynamicHelp(); void onBtnUndoChanges(); - bool hasChanged(); - void selectFirstError(); - void enableSave(bool b) {mEnableSave = b;} - protected: void deleteBridges(); void setHelpPage(const std::string& help_string); @@ -176,9 +179,9 @@ private: std::string mSampleText; std::string mScriptName; LLScriptEditor* mEditor; - void (*mLoadCallback)(void* userdata); - void (*mSaveCallback)(void* userdata, bool close_after_save); - void (*mSearchReplaceCallback) (void* userdata); + script_ed_callback_t mLoadCallback; + save_callback_t mSaveCallback; + script_ed_callback_t mSearchReplaceCallback; void* mUserdata; LLComboBox *mFunctions; bool mForceClose; @@ -204,7 +207,6 @@ private: public: boost::signals2::connection mSyntaxIDConnection; - }; class LLScriptEdContainer : public LLPreview @@ -269,10 +271,8 @@ protected: S32 mPendingUploads; LLScriptMovedObserver* mItemObserver; - }; - // Used to view and edit an LSL script that is attached to an object. class LLLiveLSLEditor : public LLScriptEdContainer { @@ -280,7 +280,6 @@ class LLLiveLSLEditor : public LLScriptEdContainer public: LLLiveLSLEditor(const LLSD& key); - static void processScriptRunningReply(LLMessageSystem* msg, void**); virtual void callbackLSLCompileSucceeded(const LLUUID& task_id, diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index 0edaf43753..2a9dd73936 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -45,7 +45,8 @@ LLScriptEditor::Params::Params() LLScriptEditor::LLScriptEditor(const Params& p) : LLTextEditor(p) , mShowLineNumbers(p.show_line_numbers), - mUseDefaultFontSize(p.default_font_size) + mUseDefaultFontSize(p.default_font_size), + mLuauLanguage(false) { if (mShowLineNumbers) { @@ -200,12 +201,12 @@ void LLScriptEditor::clearSegments() LLKeywords::keyword_iterator_t LLScriptEditor::keywordsBegin() { - return mLuauLanguage ? mKeywordsLua.begin() : mKeywordsLSL.begin(); + return getKeywords().begin(); } LLKeywords::keyword_iterator_t LLScriptEditor::keywordsEnd() { - return mLuauLanguage ? mKeywordsLua.end() : mKeywordsLSL.end(); + return getKeywords().end(); } LLKeywords& LLScriptEditor::getKeywords() @@ -237,7 +238,6 @@ void LLScriptEditor::drawSelectionBackground() ++rect_it) { LLRect selection_rect = *rect_it; - selection_rect = *rect_it; selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); gl_rect_2d(selection_rect, selection_color); } diff --git a/indra/newview/llscripteditor.h b/indra/newview/llscripteditor.h index ad61405917..ba44d77ea0 100644 --- a/indra/newview/llscripteditor.h +++ b/indra/newview/llscripteditor.h @@ -54,6 +54,7 @@ public: LLKeywords::keyword_iterator_t keywordsEnd(); LLKeywords& getKeywords(); bool getIsLuauLanguage() { return mLuauLanguage; } + void setLuauLanguage(bool luau_language) { mLuauLanguage = luau_language; } static std::string getScriptFontSize(); LLFontGL* getScriptFont(); @@ -67,8 +68,6 @@ private: void drawLineNumbers(); /* virtual */ void updateSegments(); /* virtual */ void drawSelectionBackground(); - void loadKeywords(const std::string& filename_keywords, - const std::string& filename_colors); LLKeywords mKeywordsLua; LLKeywords mKeywordsLSL; diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml index 3f1aeeb626..2ccf379b8d 100644 --- a/indra/newview/skins/default/xui/en/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml @@ -250,13 +250,13 @@ name="compile_target_mono" value="mono" /> <combo_box.item - label="Lua" - name="compile_target_luau" - value="luau" /> - <combo_box.item - label="LSL/Luau" + label="LSL: 2025 VM" name="compile_target_lsl_luau" value="lsl-luau" /> + <combo_box.item + label="SLua" + name="compile_target_luau" + value="luau" /> </combo_box> <text name="compile_target_label" |
