diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index b5a2754b7..6bffa859e 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -505,6 +505,7 @@ bool App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool s mPluginsPath = mConfigPath + "plugins"; mLanguagesPath = mConfigPath + "languages"; mThemesPath = mConfigPath + "themes"; + mScriptsPath = mConfigPath + "scripts"; mColorSchemesPath = mConfigPath + "editor" + FileSystem::getOSSlash() + "colorschemes" + FileSystem::getOSSlash(); mTerminalManager = std::make_unique( this ); @@ -525,6 +526,10 @@ bool App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool s FileSystem::makeDir( mThemesPath ); FileSystem::dirAddSlashAtEnd( mThemesPath ); + if ( !FileSystem::fileExists( mScriptsPath ) ) + FileSystem::makeDir( mScriptsPath ); + FileSystem::dirAddSlashAtEnd( mScriptsPath ); + mLogsPath = mConfigPath + "ecode.log"; #ifndef EE_DEBUG diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index b4efd114d..a781c0def 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -443,6 +443,8 @@ class App : public UICodeEditorSplitter::Client { std::pair generateConfigPath(); + const std::string getScriptsPath() const { return mScriptsPath; } + protected: std::vector mArgs; EE::Window::Window* mWindow{ nullptr }; @@ -479,6 +481,7 @@ class App : public UICodeEditorSplitter::Client { std::string mThemesPath; std::string mLogsPath; std::string mi18nPath; + std::string mScriptsPath; Float mDisplayDPI{ 96 }; std::shared_ptr mThreadPool; std::shared_ptr mDirTree; diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 2181a6b65..946d58ec5 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -43,7 +43,7 @@ fuzzyMatchSymbols( const std::vector& sy const std::string& match, const size_t& max ) { AutoCompletePlugin::SymbolsList matches; matches.reserve( max ); - int score; + int score = 0; for ( const auto& symbols : symbolsVec ) { for ( const auto& symbol : *symbols ) { if ( symbol.kind == LSPCompletionItemKind::Snippet || diff --git a/src/tools/ecode/projectbuild.cpp b/src/tools/ecode/projectbuild.cpp index 457822773..91b1d5154 100644 --- a/src/tools/ecode/projectbuild.cpp +++ b/src/tools/ecode/projectbuild.cpp @@ -314,7 +314,8 @@ ProjectBuildManager::~ProjectBuildManager() { ProjectBuildCommandsRes ProjectBuildManager::generateBuildCommands( const std::string& buildName, const ProjectBuildi18nFn& i18n, - const std::string& buildType ) { + const std::string& buildType, + bool isClean ) { const auto& buildIt = mBuilds.find( buildName ); if ( buildIt == mBuilds.end() ) @@ -337,7 +338,7 @@ ProjectBuildCommandsRes ProjectBuildManager::generateBuildCommands( const std::s FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( curDoc ) ); ProjectBuildCommandsRes res; - auto finalBuild( build.replaceVars( build.mBuild ) ); + auto finalBuild( build.replaceVars( isClean ? build.mClean : build.mBuild ) ); for ( const auto& step : finalBuild ) { ProjectBuildCommand buildCmd( step ); @@ -358,76 +359,11 @@ ProjectBuildCommandsRes ProjectBuildManager::generateBuildCommands( const std::s return res; } -ProjectBuildCommandsRes ProjectBuildManager::build( const std::string& buildName, - const ProjectBuildi18nFn& i18n, - const std::string& buildType, - const ProjectBuildProgressFn& progressFn, - const ProjectBuildDoneFn& doneFn ) { - ProjectBuildCommandsRes res = generateBuildCommands( buildName, i18n, buildType ); - if ( !res.isValid() ) - return res; - if ( !mThreadPool ) { - res.errorMsg = i18n( "no_threads", "Threaded ecode required to compile builds." ); - return res; - } - - mThreadPool->run( [this, res, progressFn, doneFn, i18n, buildName, buildType]() { - runBuild( buildName, buildType, i18n, res, progressFn, doneFn ); - } ); - - return res; -}; - -ProjectBuildCommandsRes ProjectBuildManager::generateCleanCommands( const std::string& buildName, - const ProjectBuildi18nFn& i18n, - const std::string& buildType ) { - const auto& buildIt = mBuilds.find( buildName ); - - if ( buildIt == mBuilds.end() ) - return { i18n( "build_name_not_found", "Build name not found!" ) }; - - const auto& build = buildIt->second; - - if ( !build.mBuildTypes.empty() && buildType.empty() ) - return { i18n( "build_type_required", "Build type must be set!" ) }; - - std::string currentOS = String::toLower( Sys::getPlatform() ); - - if ( !build.isOSSupported( currentOS ) ) - return { - i18n( "build_os_not_supported", "Operating System not supported for this build!" ) }; - - std::string nproc = String::format( "%d", Sys::getCPUCount() ); - std::string curDoc = getCurrentDocument(); - std::string curDocName = - FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( curDoc ) ); - ProjectBuildCommandsRes res; - - auto finalBuild( build.replaceVars( build.mClean ) ); - - for ( const auto& step : finalBuild ) { - ProjectBuildCommand buildCmd( step ); - replaceVar( buildCmd, VAR_OS, currentOS ); - replaceVar( buildCmd, VAR_NPROC, nproc ); - replaceVar( buildCmd, VAR_CURRENT_DOC, curDoc ); - replaceVar( buildCmd, VAR_CURRENT_DOC_NAME, curDocName ); - if ( !buildType.empty() ) - replaceVar( buildCmd, VAR_BUILD_TYPE, buildType ); - buildCmd.config = build.mConfig; - res.cmds.emplace_back( std::move( buildCmd ) ); - } - - res.envs = build.mEnvs; - - return res; -} - -ProjectBuildCommandsRes ProjectBuildManager::clean( const std::string& buildName, - const ProjectBuildi18nFn& i18n, - const std::string& buildType, - const ProjectBuildProgressFn& progressFn, - const ProjectBuildDoneFn& doneFn ) { - ProjectBuildCommandsRes res = generateCleanCommands( buildName, i18n, buildType ); +ProjectBuildCommandsRes +ProjectBuildManager::build( const std::string& buildName, const ProjectBuildi18nFn& i18n, + const std::string& buildType, const ProjectBuildProgressFn& progressFn, + const ProjectBuildDoneFn& doneFn, bool isClean ) { + ProjectBuildCommandsRes res = generateBuildCommands( buildName, i18n, buildType, isClean ); if ( !res.isValid() ) return res; if ( !mThreadPool ) { @@ -725,8 +661,8 @@ void ProjectBuildManager::cleanCurrentConfig( StatusBuildOutputController* sboc build = &buildIt.second; if ( build ) - sboc->runClean( build->getName(), mConfig.buildType, - getOutputParser( build->getName() ) ); + sboc->runBuild( build->getName(), mConfig.buildType, + getOutputParser( build->getName() ), true ); } } @@ -756,7 +692,8 @@ void ProjectBuildManager::runCurrentConfig( StatusBuildOutputController* /* not UITerminal* term = mApp->getTerminalManager()->createTerminalInSplitter( finalBuild.workingDir, false ); if ( term == nullptr || term->getTerm() == nullptr ) { - mApp->getTerminalManager()->openInExternalTerminal( cmd ); + mApp->getTerminalManager()->openInExternalTerminal( cmd, + finalBuild.workingDir ); } else { term->executeFile( cmd ); } diff --git a/src/tools/ecode/projectbuild.hpp b/src/tools/ecode/projectbuild.hpp index c3cf6e86b..608634b60 100644 --- a/src/tools/ecode/projectbuild.hpp +++ b/src/tools/ecode/projectbuild.hpp @@ -251,20 +251,12 @@ class ProjectBuildManager { ProjectBuildCommandsRes build( const std::string& buildName, const ProjectBuildi18nFn& i18n, const std::string& buildType = "", const ProjectBuildProgressFn& progressFn = {}, - const ProjectBuildDoneFn& doneFn = {} ); + const ProjectBuildDoneFn& doneFn = {}, bool isClean = false ); ProjectBuildCommandsRes generateBuildCommands( const std::string& buildName, const ProjectBuildi18nFn& i18n, - const std::string& buildType = "" ); - - ProjectBuildCommandsRes clean( const std::string& buildName, const ProjectBuildi18nFn& i18n, - const std::string& buildType = "", - const ProjectBuildProgressFn& progressFn = {}, - const ProjectBuildDoneFn& doneFn = {} ); - - ProjectBuildCommandsRes generateCleanCommands( const std::string& buildName, - const ProjectBuildi18nFn& i18n, - const std::string& buildType = "" ); + const std::string& buildType = "", + bool isClean = false ); ProjectBuildOutputParser getOutputParser( const std::string& buildName ); diff --git a/src/tools/ecode/statusbuildoutputcontroller.cpp b/src/tools/ecode/statusbuildoutputcontroller.cpp index b574dba99..0368784fd 100644 --- a/src/tools/ecode/statusbuildoutputcontroller.cpp +++ b/src/tools/ecode/statusbuildoutputcontroller.cpp @@ -101,7 +101,8 @@ static void safeInsertBuffer( TextDocument& doc, const std::string& buffer ) { void StatusBuildOutputController::runBuild( const std::string& buildName, const std::string& buildType, - const ProjectBuildOutputParser& outputParser ) { + const ProjectBuildOutputParser& outputParser, + bool isClean ) { if ( nullptr == mApp->getProjectBuildManager() ) return; @@ -111,7 +112,7 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, showBuildOutput(); mStatusResults.clear(); - if ( mTableIssues ) + if ( !isClean && mTableIssues ) mTableIssues->getSelection().clear(); mBuildOutput->getDocument().reset(); mBuildOutput->invalidateLongestLineWidth(); @@ -149,28 +150,48 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, mScrollLocked = true; UIPushButton* buildButton = getBuildButton( mApp ); - if ( buildButton ) - buildButton->setText( mApp->i18n( "cancel_build", "Cancel Build" ) ); UIPushButton* cleanButton = getCleanButton( mApp ); + + bool enableBuildButton = false; bool enableCleanButton = false; - if ( cleanButton && cleanButton->isEnabled() ) { + + if ( isClean && buildButton && buildButton->isEnabled() ) { + buildButton->setEnabled( false ); + enableBuildButton = true; + } + + if ( !isClean && cleanButton && cleanButton->isEnabled() ) { cleanButton->setEnabled( false ); enableCleanButton = true; } - const auto updateBuildButton = [this, enableCleanButton]() { + if ( isClean ) { + if ( cleanButton ) + cleanButton->setText( mApp->i18n( "cancel_clean", "Cancel Clean" ) ); + } else { + if ( buildButton ) + buildButton->setText( mApp->i18n( "cancel_build", "Cancel Build" ) ); + } + + const auto updateBuildButton = [this, isClean, enableBuildButton, enableCleanButton]() { UIPushButton* buildButton = getBuildButton( mApp ); - if ( buildButton ) { + UIPushButton* cleanButton = getCleanButton( mApp ); + + if ( !isClean && buildButton ) { buildButton->runOnMainThread( [this, buildButton] { buildButton->setText( mApp->i18n( "build", "Build" ) ); } ); } - if ( enableCleanButton ) { - UIPushButton* cleanButton = getCleanButton( mApp ); - if ( cleanButton ) { - cleanButton->runOnMainThread( [cleanButton] { cleanButton->setEnabled( true ); } ); - } + if ( isClean && cleanButton ) { + cleanButton->runOnMainThread( + [this, cleanButton] { cleanButton->setText( mApp->i18n( "clean", "Clean" ) ); } ); } + + if ( enableBuildButton && buildButton ) + buildButton->setEnabled( true ); + + if ( enableCleanButton && cleanButton ) + cleanButton->runOnMainThread( [cleanButton] { cleanButton->setEnabled( true ); } ); }; auto res = pbm->build( @@ -199,17 +220,19 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, } } while ( !buffer.empty() ); }, - [this, updateBuildButton]( auto exitCode, const ProjectBuildCommand* cmd ) { + [this, updateBuildButton, isClean]( auto exitCode, const ProjectBuildCommand* cmd ) { if ( !mCurLineBuffer.empty() && nullptr != cmd ) searchFindAndAddStatusResult( mPatternHolder, mCurLineBuffer, cmd ); String buffer; if ( EXIT_SUCCESS == exitCode ) { buffer = Sys::getDateTimeStr() + ": " + - mApp->i18n( "build_successful", "Build run successfully\n" ); + ( isClean ? mApp->i18n( "clean_successful", "Clean run successfully\n" ) + : mApp->i18n( "build_successful", "Build run successfully\n" ) ); } else { buffer = Sys::getDateTimeStr() + ": " + - mApp->i18n( "build_failed", "Build run with errors\n" ); + ( isClean ? mApp->i18n( "clean_failed", "Clean run with errors\n" ) + : mApp->i18n( "build_failed", "Build run with errors\n" ) ); } mBuildOutput->runOnMainThread( [this, buffer]() { @@ -222,7 +245,8 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, if ( !mApp->getWindow()->hasFocus() ) mApp->getWindow()->flash( WindowFlashOperation::UntilFocused ); - } ); + }, + isClean ); if ( !res.isValid() ) { mApp->getNotificationCenter()->addNotification( res.errorMsg ); @@ -230,96 +254,6 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, } } -void StatusBuildOutputController::runClean( const std::string& buildName, - const std::string& buildType, - const ProjectBuildOutputParser& outputParser ) { - if ( nullptr == mApp->getProjectBuildManager() ) - return; - - auto pbm = mApp->getProjectBuildManager(); - - show(); - - mBuildOutput->getDocument().reset(); - mBuildOutput->invalidateLongestLineWidth(); - mBuildOutput->setScrollY( mBuildOutput->getMaxScroll().y ); - - std::vector patterns; - - for ( const auto& parser : outputParser.getConfig() ) { - SyntaxPattern ptn( { parser.pattern }, getProjectOutputParserTypeToString( parser.type ) ); - patterns.emplace_back( std::move( ptn ) ); - } - - patterns.emplace_back( - SyntaxPattern( { "%d%d%d%d%-%d%d%-%d%d%s%d%d%:%d%d%:%d%d%:.*error.*[^\n]+" }, "error" ) ); - patterns.emplace_back( SyntaxPattern( - { "%d%d%d%d%-%d%d%-%d%d%s%d%d%:%d%d%:%d%d%:.*warning.*[^\n]+" }, "warning" ) ); - patterns.emplace_back( - SyntaxPattern( { "%d%d%d%d%-%d%d%-%d%d%s%d%d%:%d%d%:%d%d%:[^\n]+" }, "notice" ) ); - - SyntaxDefinition synDef( "custom_build", {}, std::move( patterns ) ); - - mBuildOutput->getDocument().setSyntaxDefinition( synDef ); - mBuildOutput->getVScrollBar()->setValue( 1.f ); - mScrollLocked = true; - - UIPushButton* buildButton = getBuildButton( mApp ); - bool enableBuildButton = false; - if ( buildButton && buildButton->isEnabled() ) { - buildButton->setEnabled( false ); - enableBuildButton = true; - } - UIPushButton* cleanButton = getCleanButton( mApp ); - if ( cleanButton ) - cleanButton->setText( mApp->i18n( "cancel_clean", "Cancel Clean" ) ); - - auto res = pbm->clean( - buildName, [this]( const auto& key, const auto& def ) { return mApp->i18n( key, def ); }, - buildType, - [this]( auto, auto buffer, auto ) { - mBuildOutput->runOnMainThread( [this, buffer]() { - safeInsertBuffer( mBuildOutput->getDocument(), buffer ); - if ( mScrollLocked ) - mBuildOutput->setScrollY( mBuildOutput->getMaxScroll().y ); - } ); - }, - [this, enableBuildButton]( auto exitCode, auto ) { - String buffer; - - if ( EXIT_SUCCESS == exitCode ) { - buffer = Sys::getDateTimeStr() + ": " + - mApp->i18n( "clean_successful", "Clean run successfully\n" ); - } else { - buffer = Sys::getDateTimeStr() + ": " + - mApp->i18n( "clean_failed", "Clean run with errors\n" ); - } - - mBuildOutput->runOnMainThread( [this, buffer]() { - safeInsertBuffer( mBuildOutput->getDocument(), buffer ); - if ( mScrollLocked ) - mBuildOutput->setScrollY( mBuildOutput->getMaxScroll().y ); - } ); - - UIPushButton* cleanButton = getCleanButton( mApp ); - if ( cleanButton ) - cleanButton->setText( mApp->i18n( "clean", "Clean" ) ); - - if ( enableBuildButton ) { - UIPushButton* buildButton = getBuildButton( mApp ); - if ( buildButton ) - buildButton->setEnabled( true ); - } - - if ( !mApp->getWindow()->hasFocus() ) - mApp->getWindow()->flash( WindowFlashOperation::UntilFocused ); - } ); - - if ( !res.isValid() ) { - mApp->getNotificationCenter()->addNotification( res.errorMsg ); - } -} - UIWidget* StatusBuildOutputController::getWidget() { return mContainer; } diff --git a/src/tools/ecode/statusbuildoutputcontroller.hpp b/src/tools/ecode/statusbuildoutputcontroller.hpp index f87dc935c..5d3c5b8aa 100644 --- a/src/tools/ecode/statusbuildoutputcontroller.hpp +++ b/src/tools/ecode/statusbuildoutputcontroller.hpp @@ -39,13 +39,10 @@ class StatusBuildOutputController : public StatusBarElement { public: StatusBuildOutputController( UISplitter* mainSplitter, UISceneNode* uiSceneNode, App* app ); - virtual ~StatusBuildOutputController() {}; + virtual ~StatusBuildOutputController(){}; void runBuild( const std::string& buildName, const std::string& buildType, - const ProjectBuildOutputParser& outputParser = {} ); - - void runClean( const std::string& buildName, const std::string& buildType, - const ProjectBuildOutputParser& outputParser = {} ); + const ProjectBuildOutputParser& outputParser = {}, bool isClean = false ); UIWidget* getWidget(); diff --git a/src/tools/ecode/statusterminalcontroller.cpp b/src/tools/ecode/statusterminalcontroller.cpp index 768002be2..923b4afa6 100644 --- a/src/tools/ecode/statusterminalcontroller.cpp +++ b/src/tools/ecode/statusterminalcontroller.cpp @@ -35,7 +35,7 @@ UITerminal* StatusTerminalController::createTerminal( const std::string& working nullptr, false ); if ( term == nullptr || term->getTerm() == nullptr ) { - mApp->getTerminalManager()->displayError(); + mApp->getTerminalManager()->displayError( workingDir ); return nullptr; } diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 8ca3768ed..926ae509a 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -2,12 +2,22 @@ #include "ecode.hpp" #include +using namespace std::literals; + namespace ecode { TerminalManager::TerminalManager( App* app ) : mApp( app ) {} UITerminal* TerminalManager::createTerminalInSplitter( const std::string& workingDir, bool fallback ) { +#if EE_PLATFORM == EE_PLATFORM_WIN + std::string os = Sys::getOSName( true ); + if ( !LuaPattern::matches( os, "Windows 1%d"sv ) && + !LuaPattern::matches( os, "Windows Server 201[69]"sv ) && + !LuaPattern::matches( os, "Windows Server 202%d"sv ) ) + return nullptr; +#endif + UITerminal* term = nullptr; auto splitter = mApp->getSplitter(); auto& config = mApp->getConfig(); @@ -282,42 +292,125 @@ void TerminalManager::updateMenuColorScheme( UIMenuSubMenu* colorSchemeMenu ) { } #if EE_PLATFORM == EE_PLATFORM_WIN -static void openExternal( const std::string& defShell, const std::string& cmd = "" ) { +std::string quoteString( std::string str ) { + std::string escapedStr = ""; + for ( char chr : str ) { + if ( std::strchr( "()%!^\"<>&| ", chr ) ) + escapedStr += '^'; + escapedStr += chr; + } + return escapedStr; +} + +static void openExternal( const std::string& defShell, const std::string& cmd, + const std::string& scriptsPath, const std::string& workingDir ) { + // This is an utility bat script based in the Geany utility script called "geany-run-helper" + static const std::string RUN_HELPER = + R"shellscript(REM USAGE: ecode-run-helper DIRECTORY AUTOCLOSE COMMAND... + +REM unnecessary, but we get the directory +cd %1 +shift +REM save autoclose option and remove it +set autoclose=%1 +shift + +REM spawn the child +REM it's tricky because shift doesn't affect %*, so hack it out +REM https://en.wikibooks.org/wiki/Windows_Batch_Scripting#Command-line_arguments +set SPAWN= +:argloop +if -%1-==-- goto argloop_end + set SPAWN=%SPAWN% %1 + shift +goto argloop +:argloop_end +%SPAWN% + +REM show the result +echo: +echo: +echo:------------------ +echo:(program exited with code: %ERRORLEVEL%) +echo: + +REM and if wanted, wait on the user +if not %autoclose%==1 pause + )shellscript"; + if ( !cmd.empty() && !scriptsPath.empty() ) { + std::string runHelperPath = scriptsPath + "ecode-run-helper.bat"; + if ( !FileSystem::fileExists( runHelperPath ) ) + FileSystem::fileWrite( runHelperPath, RUN_HELPER ); + std::string cmdDir = String::trim( FileSystem::fileRemoveFileName( cmd ) ); + if ( cmdDir.empty() ) + cmdDir = workingDir; + std::string cmdFile = String::trim( FileSystem::fileNameFromPath( cmd ) ); + auto fcmd = "cmd.exe /q /c " + quoteString( "\"" + runHelperPath + "\" \"" + cmdDir + + "\" 0 \"" + cmdFile + "\"" ); + Log::info( "Running: %s", fcmd ); + Sys::execute( fcmd, workingDir ); + return; + } + std::vector options; if ( !defShell.empty() ) options.push_back( defShell ); options.push_back( "cmd" ); options.push_back( "powershell" ); -#else -static void openExternal( const std::string&, const std::string& cmd = "" ) { - std::vector options = { "gnome-terminal", "konsole", "xterm", "st" }; -#endif for ( const auto& option : options ) { auto externalShell( Sys::which( option ) ); if ( !externalShell.empty() ) { if ( !cmd.empty() ) { -#if EE_PLATFORM == EE_PLATFORM_WIN - auto fcmd = externalShell + " /q /c " + cmd; -#else - auto fcmd = externalShell + " -e " + cmd; -#endif - Sys::execute( fcmd ); + auto fcmd = externalShell + " /q /c " + quoteString( "\"" + cmd + "\"" ); + Log::info( "Running: %s", fcmd ); + Sys::execute( fcmd, workingDir ); return; } else { - Sys::execute( externalShell ); + Sys::execute( externalShell, workingDir ); return; } } } } +#elif EE_PLATFORM == EE_PLATFORM_MACOS +static void openExternal( const std::string&, const std::string& cmd, const std::string&, + const std::string& workingDir ) { + static const std::string externalShell = "open -a terminal"; + if ( !cmd.empty() ) + std::string fcmd = externalShell + " \"" + cmd + "\""; + Log::info( "Running: %s", fcmd ); + Sys::execute( fcmd, workingDir ); + else Sys::execute( externalShell, workingDir ); +} +#else +static void openExternal( const std::string&, const std::string& cmd, const std::string&, + const std::string& workingDir ) { + std::vector options = { "gnome-terminal", "konsole", "xterm", "st" }; + for ( const auto& option : options ) { + auto externalShell( Sys::which( option ) ); + if ( !externalShell.empty() ) { + if ( !cmd.empty() ) { + auto fcmd = externalShell + " -e \"" + cmd + "\""; + Log::info( "Running: %s", fcmd ); + Sys::execute( fcmd, workingDir ); + return; + } else { + Sys::execute( externalShell, workingDir ); + return; + } + } + } +} +#endif -void TerminalManager::openInExternalTerminal( const std::string& cmd ) { - openExternal( mApp->termConfig().shell, cmd ); +void TerminalManager::openInExternalTerminal( const std::string& cmd, + const std::string& workingDir ) { + openExternal( mApp->termConfig().shell, cmd, mApp->getScriptsPath(), workingDir ); } -void TerminalManager::displayError() { +void TerminalManager::displayError( const std::string& workingDir ) { if ( mApp->getConfig().term.unsupportedOSWarnDisabled ) { - openExternal( mApp->termConfig().shell ); + openExternal( mApp->termConfig().shell, "", mApp->getScriptsPath(), workingDir ); } else { UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::OK, @@ -335,10 +428,10 @@ void TerminalManager::displayError() { chkDoNotWarn->setText( mApp->i18n( "terminal_not_supported_do_not_warn", "Always open an external terminal (do not warn)" ) ); chkDoNotWarn->toPosition( 1 ); - msgBox->on( Event::OnConfirm, [this, chkDoNotWarn]( const Event* ) { + msgBox->on( Event::OnConfirm, [this, chkDoNotWarn, workingDir]( const Event* ) { if ( chkDoNotWarn->isChecked() ) mApp->getConfig().term.unsupportedOSWarnDisabled = true; - openExternal( mApp->termConfig().shell ); + openExternal( mApp->termConfig().shell, "", mApp->getScriptsPath(), workingDir ); } ); msgBox->showWhenReady(); } @@ -395,7 +488,7 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW if ( term == nullptr || term->getTerm() == nullptr ) { if ( fallback ) - displayError(); + displayError( workingDir ); return nullptr; } diff --git a/src/tools/ecode/terminalmanager.hpp b/src/tools/ecode/terminalmanager.hpp index 023b920ef..56ae06033 100644 --- a/src/tools/ecode/terminalmanager.hpp +++ b/src/tools/ecode/terminalmanager.hpp @@ -58,9 +58,9 @@ class TerminalManager { void setKeybindings( UITerminal* term ); - void displayError(); + void displayError( const std::string& workingDir ); - void openInExternalTerminal( const std::string& cmd ); + void openInExternalTerminal( const std::string& cmd, const std::string& workingDir ); protected: App* mApp;