From 8f2b9d65ba11d63a7536f091e032d4fa1e286efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Wed, 24 Dec 2025 00:39:26 -0300 Subject: [PATCH] Register debugger commands globally. --- include/eepp/ui/widgetcommandexecuter.hpp | 28 ++++++- .../eterm/include/eterm/ui/uiterminal.hpp | 2 +- src/modules/eterm/src/eterm/ui/uiterminal.cpp | 4 +- src/tools/ecode/ecode.cpp | 3 +- .../ecode/plugins/debugger/debuggerplugin.cpp | 74 +++++++++++-------- .../ecode/plugins/debugger/debuggerplugin.hpp | 7 ++ .../ecode/plugins/lsp/lspclientserver.cpp | 3 + 7 files changed, 85 insertions(+), 36 deletions(-) diff --git a/include/eepp/ui/widgetcommandexecuter.hpp b/include/eepp/ui/widgetcommandexecuter.hpp index 08b1a471f..8440b6d42 100644 --- a/include/eepp/ui/widgetcommandexecuter.hpp +++ b/include/eepp/ui/widgetcommandexecuter.hpp @@ -1,9 +1,12 @@ #ifndef EE_UI_WIDGETCOMMANDEXECUTER_HPP #define EE_UI_WIDGETCOMMANDEXECUTER_HPP +#include +#include +#include + #include #include -#include using namespace EE::Scene; @@ -25,14 +28,33 @@ class EE_API WidgetCommandExecuter { } } + void unsetCommand( const std::string& name ) { + mCommands.erase( name ); + auto it = std::find( mCommandList.begin(), mCommandList.end(), name ); + if ( it != mCommandList.end() ) + mCommandList.erase( it ); + } + + void unsetCommands( const std::span& names ) { + for ( const auto& name : names ) { + mCommands.erase( name ); + auto it = std::find( mCommandList.begin(), mCommandList.end(), name ); + if ( it != mCommandList.end() ) + mCommandList.erase( it ); + } + } + bool hasCommand( const std::string& name ) const { return mCommands.find( name ) != mCommands.end(); } - void execute( const std::string& command ) { + bool execute( const std::string& command ) { auto cmdIt = mCommands.find( command ); - if ( cmdIt != mCommands.end() ) + if ( cmdIt != mCommands.end() ) { cmdIt->second(); + return true; + } + return false; } size_t commandCount() const { return mCommands.size(); } diff --git a/src/modules/eterm/include/eterm/ui/uiterminal.hpp b/src/modules/eterm/include/eterm/ui/uiterminal.hpp index 0243bde4d..697d5e7ee 100644 --- a/src/modules/eterm/include/eterm/ui/uiterminal.hpp +++ b/src/modules/eterm/include/eterm/ui/uiterminal.hpp @@ -66,7 +66,7 @@ class UITerminal : public UIWidget { void addKeyBinds( const std::map& binds ); - void execute( const std::string& command ); + bool execute( const std::string& command ); void setCommands( const std::map& cmds ); diff --git a/src/modules/eterm/src/eterm/ui/uiterminal.cpp b/src/modules/eterm/src/eterm/ui/uiterminal.cpp index 046e645c9..4e9f25cfd 100644 --- a/src/modules/eterm/src/eterm/ui/uiterminal.cpp +++ b/src/modules/eterm/src/eterm/ui/uiterminal.cpp @@ -399,11 +399,13 @@ void UITerminal::addKeyBinds( const std::map mKeyBindings.addKeybinds( binds ); } -void UITerminal::execute( const std::string& command ) { +bool UITerminal::execute( const std::string& command ) { auto cmdIt = mCommands.find( command ); if ( cmdIt != mCommands.end() ) { cmdIt->second(); + return true; } + return false; } void UITerminal::setCommands( const std::map& cmds ) { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 7ce3fc909..bb5338f3e 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -616,7 +616,8 @@ void App::runCommand( const std::string& command ) { editor->getDocument().execute( command, editor ); } else if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { - mSplitter->getCurWidget()->asType()->execute( command ); + if ( !mSplitter->getCurWidget()->asType()->execute( command ) ) + mMainLayout->execute( command ); } else { mMainLayout->execute( command ); } diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp index 0cd2b658d..a6689c6a2 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.cpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.cpp @@ -176,6 +176,8 @@ DebuggerPlugin::~DebuggerPlugin() { if ( SceneManager::existsSingleton() && !SceneManager::instance()->isShuttingDown() && getPluginContext() && getPluginContext()->getMainLayout() ) { + getPluginContext()->getMainLayout()->unsetCommands( mRegisteredCommands ); + for ( const auto& kb : mKeyBindings ) getPluginContext()->getMainLayout()->getKeyBindings().removeCommandKeybind( kb.first ); } @@ -695,6 +697,7 @@ PluginRequestHandle DebuggerPlugin::processMessage( const PluginMessage& msg ) { break; } case ecode::PluginMessageType::UIReady: { + registerCommands( getPluginContext()->getMainLayout() ); for ( const auto& kb : mKeyBindings ) { getPluginContext()->getMainLayout()->getKeyBindings().addKeybindString( kb.second, kb.first ); @@ -1394,8 +1397,15 @@ DebuggerPlugin::needsToResolveInputs( nlohmann::json& json, return inputs; } -void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { - doc->setCommand( "debugger-continue-interrupt", [this] { +template +void DebuggerPlugin::registerCommand( TCommandRegister* doc, Cmd cmd, CmdCb cb ) { + doc->setCommand( cmd, cb ); + mRegisteredCommands.push_back( cmd ); +} + +template +void DebuggerPlugin::registerCommands( TCommandRegister* executer ) { + registerCommand( executer, "debugger-continue-interrupt", [this] { if ( mDebugger && mListener ) { if ( mListener->isStopped() ) { resume( mListener->getCurrentThreadId() ); @@ -1431,15 +1441,15 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { } } ); - doc->setCommand( "debugger-start", [this] { + registerCommand( executer, "debugger-start", [this] { if ( mDebugger ) exitDebugger( true ); runCurrentConfig(); } ); - doc->setCommand( "debugger-stop", [this] { exitDebugger( true ); } ); + registerCommand( executer, "debugger-stop", [this] { exitDebugger( true ); } ); - doc->setCommand( "debugger-start-stop", [this] { + registerCommand( executer, "debugger-start-stop", [this] { if ( mDebugger && mDebugger->started() ) { exitDebugger( true ); } else { @@ -1447,6 +1457,35 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { } } ); + registerCommand( executer, "debugger-step-over", [this] { + if ( mDebugger && mListener && mListener->isStopped() ) + mDebugger->stepOver( mListener->getCurrentThreadId() ); + } ); + + registerCommand( executer, "debugger-step-into", [this] { + if ( mDebugger && mListener && mListener->isStopped() ) + mDebugger->stepInto( mListener->getCurrentThreadId() ); + } ); + + registerCommand( executer, "debugger-step-out", [this] { + if ( mDebugger && mListener && mListener->isStopped() ) + mDebugger->stepOut( mListener->getCurrentThreadId() ); + } ); + + registerCommand( executer, "toggle-status-app-debugger", [this] { + if ( getStatusDebuggerController() ) + getStatusDebuggerController()->toggle(); + } ); + + registerCommand( executer, "show-debugger-tab", [this] { + if ( mTab ) + mTab->setTabSelected(); + } ); +} + +void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { + registerCommands( doc ); + doc->setCommand( "debugger-breakpoint-toggle", [doc, this] { if ( setBreakpoint( doc, doc->getSelection().start().line() + 1 ) ) getUISceneNode()->getRoot()->invalidateDraw(); @@ -1457,31 +1496,6 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) { getUISceneNode()->getRoot()->invalidateDraw(); } ); - doc->setCommand( "debugger-step-over", [this] { - if ( mDebugger && mListener && mListener->isStopped() ) - mDebugger->stepOver( mListener->getCurrentThreadId() ); - } ); - - doc->setCommand( "debugger-step-into", [this] { - if ( mDebugger && mListener && mListener->isStopped() ) - mDebugger->stepInto( mListener->getCurrentThreadId() ); - } ); - - doc->setCommand( "debugger-step-out", [this] { - if ( mDebugger && mListener && mListener->isStopped() ) - mDebugger->stepOut( mListener->getCurrentThreadId() ); - } ); - - doc->setCommand( "toggle-status-app-debugger", [this] { - if ( getStatusDebuggerController() ) - getStatusDebuggerController()->toggle(); - } ); - - doc->setCommand( "show-debugger-tab", [this]() { - if ( mTab ) - mTab->setTabSelected(); - } ); - Lock l( mClientsMutex ); mClients[doc] = std::make_unique( this, doc ); doc->registerClient( mClients[doc].get() ); diff --git a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp index ee0c14302..ced33f33c 100644 --- a/src/tools/ecode/plugins/debugger/debuggerplugin.hpp +++ b/src/tools/ecode/plugins/debugger/debuggerplugin.hpp @@ -135,6 +135,7 @@ class DebuggerPlugin : public PluginBase { std::string mLastStateJsonDump; std::string mCurDebugger; std::string mCurConfiguration; + std::vector mRegisteredCommands; class DebuggerPluginClient : public TextDocument::Client { public: @@ -290,6 +291,12 @@ class DebuggerPlugin : public PluginBase { bool replaceInVal( std::string& val, const std::optional& runConfig, ProjectBuild* buildConfig, int randomPort ); + + template + void registerCommand( TCommandRegister* doc, Cmd cmd, CmdCb cb ); + + template + void registerCommands( TCommandRegister* doc ); }; } // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index bf0a5cf9f..72093c295 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -1745,10 +1745,12 @@ void LSPClientServer::processDidChangeQueue() { } bool LSPClientServer::hasDocument( TextDocument* doc ) const { + Lock l( mClientsMutex ); return std::find( mDocs.begin(), mDocs.end(), doc ) != mDocs.end(); } bool LSPClientServer::hasDocument( const URI& uri ) const { + Lock l( mClientsMutex ); for ( const auto& doc : mDocs ) { if ( doc->getURI() == uri ) return true; @@ -1766,6 +1768,7 @@ bool LSPClientServer::hasDocumentClient( LSPDocumentClient* cl ) const { } bool LSPClientServer::hasDocuments() const { + Lock l( mClientsMutex ); return !mDocs.empty(); }