From 7d7a97e60dfecdbe684ee9b73106b13b906cc0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 5 Mar 2023 18:09:58 -0300 Subject: [PATCH] ecode: Added an option to configure the default shell used by ecode terminal. Closes SpartanJ/ecode#70. --- include/eepp/ui/uicombobox.hpp | 2 + include/eepp/ui/uilistbox.hpp | 2 +- include/eepp/version.hpp | 2 +- src/eepp/ui/uicombobox.cpp | 4 ++ src/eepp/ui/uilistbox.cpp | 10 +-- src/eepp/ui/uipushbutton.cpp | 3 +- src/eepp/ui/uiwindow.cpp | 2 +- .../src/eterm/terminal/terminaldisplay.cpp | 2 +- src/tools/ecode/appconfig.cpp | 2 + src/tools/ecode/appconfig.hpp | 1 + src/tools/ecode/ecode.cpp | 5 +- src/tools/ecode/ecode.hpp | 4 ++ .../autocomplete/autocompleteplugin.hpp | 2 +- .../plugins/formatter/formatterplugin.hpp | 2 +- .../ecode/plugins/linter/linterplugin.hpp | 2 +- .../ecode/plugins/lsp/lspclientplugin.hpp | 2 +- src/tools/ecode/settingsmenu.cpp | 18 ++++- src/tools/ecode/terminalmanager.cpp | 72 ++++++++++++++++++- src/tools/ecode/terminalmanager.hpp | 5 +- src/tools/ecode/version.hpp | 2 +- 20 files changed, 120 insertions(+), 24 deletions(-) diff --git a/include/eepp/ui/uicombobox.hpp b/include/eepp/ui/uicombobox.hpp index 5970e14ab..9ab2ca481 100644 --- a/include/eepp/ui/uicombobox.hpp +++ b/include/eepp/ui/uicombobox.hpp @@ -27,6 +27,8 @@ class EE_API UIComboBox : public UIWidget { const String& getText(); + void setText( const String& text ); + virtual bool applyProperty( const StyleSheetProperty& attribute ); virtual std::string getPropertyString( const PropertyDefinition* propertyDef, diff --git a/include/eepp/ui/uilistbox.hpp b/include/eepp/ui/uilistbox.hpp index 050ed6aa5..cc4efa76f 100644 --- a/include/eepp/ui/uilistbox.hpp +++ b/include/eepp/ui/uilistbox.hpp @@ -27,7 +27,7 @@ class EE_API UIListBox : public UITouchDraggableWidget { void clear(); - void addListBoxItems( std::vector Texts ); + void addListBoxItems( std::vector texts ); Uint32 addListBoxItem( const String& Text ); diff --git a/include/eepp/version.hpp b/include/eepp/version.hpp index 426898678..4fd0e2327 100644 --- a/include/eepp/version.hpp +++ b/include/eepp/version.hpp @@ -6,7 +6,7 @@ #define EEPP_MAJOR_VERSION 2 #define EEPP_MINOR_VERSION 5 -#define EEPP_PATCH_LEVEL 8 +#define EEPP_PATCH_LEVEL 9 #define EEPP_CODENAME "Bindu" /** The compiled version of the library */ diff --git a/src/eepp/ui/uicombobox.cpp b/src/eepp/ui/uicombobox.cpp index 6e5a5d339..c68bf0148 100644 --- a/src/eepp/ui/uicombobox.cpp +++ b/src/eepp/ui/uicombobox.cpp @@ -67,6 +67,10 @@ const String& UIComboBox::getText() { return mDropDownList->getText(); } +void UIComboBox::setText( const String& text ) { + mDropDownList->setText( text ); +} + void UIComboBox::loadFromXmlNode( const pugi::xml_node& node ) { beginAttributesTransaction(); diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp index 1567d063b..9e69da35f 100644 --- a/src/eepp/ui/uilistbox.cpp +++ b/src/eepp/ui/uilistbox.cpp @@ -122,12 +122,12 @@ UIScrollBar* UIListBox::getHorizontalScrollBar() const { return mHScrollBar; } -void UIListBox::addListBoxItems( std::vector Texts ) { - mItems.reserve( mItems.size() + Texts.size() ); - mTexts.reserve( mTexts.size() + Texts.size() ); +void UIListBox::addListBoxItems( std::vector texts ) { + mItems.reserve( mItems.size() + texts.size() ); + mTexts.reserve( mTexts.size() + texts.size() ); - for ( Uint32 i = 0; i < Texts.size(); i++ ) { - mTexts.push_back( Texts[i] ); + for ( Uint32 i = 0; i < texts.size(); i++ ) { + mTexts.push_back( std::move( texts[i] ) ); mItems.push_back( NULL ); } diff --git a/src/eepp/ui/uipushbutton.cpp b/src/eepp/ui/uipushbutton.cpp index a7d9dd443..5459c43e2 100644 --- a/src/eepp/ui/uipushbutton.cpp +++ b/src/eepp/ui/uipushbutton.cpp @@ -507,8 +507,7 @@ bool UIPushButton::applyProperty( const StyleSheetProperty& attribute ) { switch ( attribute.getPropertyDefinition()->getPropertyId() ) { case PropertyId::Text: if ( NULL != mSceneNode && mSceneNode->isUISceneNode() ) - setText( static_cast( mSceneNode ) - ->getTranslatorString( attribute.asString() ) ); + setText( getUISceneNode()->getTranslatorString( attribute.asString() ) ); break; case PropertyId::Icon: { std::string val = attribute.asString(); diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index f9e6ccb9c..8db95d658 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -1643,7 +1643,7 @@ bool UIWindow::applyProperty( const StyleSheetProperty& attribute ) { setSize( getSize().getWidth(), attribute.asDpDimension( this ) ); break; case PropertyId::WindowTitle: - setTitle( attribute.asString() ); + setTitle( getUISceneNode()->getTranslatorString( attribute.asString() ) ); break; case PropertyId::WindowOpacity: setWindowOpacity( (Uint8)eemin( (Uint32)attribute.asFloat() * 255.f, 255u ) ); diff --git a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp index 7859bfffc..e63a05388 100644 --- a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp +++ b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp @@ -393,7 +393,7 @@ TerminalDisplay::create( EE::Window::Window* window, Font* font, const Float& fo if ( program.empty() ) { const char* shellenv = getenv( "SHELL" ); #ifdef _WIN32 - program = shellenv != nullptr ? shellenv : "cmd.exe"; + program = shellenv != nullptr ? shellenv : "powershell.exe"; #else #if EE_PLATFORM == EE_PLATFORM_ANDROID program = shellenv != nullptr ? shellenv : "/bin/sh"; diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 8a438c48f..e872442c9 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -142,6 +142,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, globalSearchBarConfig.escapeSequence = ini.getValueB( "global_search_bar", "escape_sequence", false ); + term.shell = ini.getValue( "terminal", "shell" ); term.fontSize = ini.getValue( "terminal", "font_size", "11dp" ); term.colorScheme = ini.getValue( "terminal", "colorscheme", "eterm" ); @@ -246,6 +247,7 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValueB( "global_search_bar", "whole_word", globalSearchBarConfig.wholeWord ); ini.setValueB( "global_search_bar", "escape_sequence", globalSearchBarConfig.escapeSequence ); + ini.setValue( "terminal", "shell", term.shell ); ini.setValue( "terminal", "font_size", term.fontSize.toString() ); ini.setValue( "terminal", "colorscheme", term.colorScheme ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index d3dc63f2a..4410fda80 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -106,6 +106,7 @@ struct ProjectDocumentConfig { }; struct TerminalConfig { + std::string shell; std::string colorScheme{ "eterm" }; StyleSheetLength fontSize{ 11, StyleSheetLength::Dp }; }; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 2c3b9fa7f..eb3913290 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1034,7 +1034,8 @@ std::string App::getCurrentWorkingDir() const { if ( !mCurrentProject.empty() ) return mCurrentProject; - if ( mSplitter && mSplitter->curEditorIsNotNull() && mSplitter->getCurEditor()->hasDocument() && + if ( mSplitter && mSplitter->curEditorIsNotNull() && mSplitter->curEditorExists() && + mSplitter->getCurEditor()->hasDocument() && mSplitter->getCurEditor()->getDocument().hasFilepath() ) { return mSplitter->getCurEditor()->getDocument().getFileInfo().getDirectoryPath(); } @@ -3084,7 +3085,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe { "cursor-pointer", 0xec09 }, { "drive", 0xedf8 }, { "refresh", 0xf064 }, - }; + { "hearth-pulse", 0xee10 } }; for ( const auto& icon : icons ) iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 77e6f21da..d189a11c9 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -238,6 +238,10 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "fallback-font", [&] { openFontDialog( mConfig.ui.fallbackFont, false ); } ); t.setCommand( "tree-view-configure-ignore-files", [&] { treeViewConfigureIgnoreFiles(); } ); t.setCommand( "check-languages-health", [&] { checkLanguagesHealth(); } ); + t.setCommand( "configure-terminal-shell", [&] { + if ( mTerminalManager ) + mTerminalManager->configureTerminalShell(); + } ); mSplitter->registerSplitterCommands( t ); } diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index a5fdd2bb8..93a9dad30 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -57,7 +57,7 @@ class AutoCompletePlugin : public UICodeEditorPlugin { "Auto complete shows the completion popup as you type, so you can fill " "in long words by typing only a few characters.", AutoCompletePlugin::New, - { 0, 1, 0 } }; + { 0, 2, 0 } }; } static UICodeEditorPlugin* New( PluginManager* pluginManager ); diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.hpp b/src/tools/ecode/plugins/formatter/formatterplugin.hpp index f6d71e928..ffecf160e 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.hpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.hpp @@ -33,7 +33,7 @@ class FormatterPlugin : public UICodeEditorPlugin { static PluginDefinition Definition() { return { "autoformatter", "Auto Formatter", "Enables the code formatter/prettifier plugin.", - FormatterPlugin::New, { 0, 1, 0 }, FormatterPlugin::NewSync }; + FormatterPlugin::New, { 0, 2, 0 }, FormatterPlugin::NewSync }; } static UICodeEditorPlugin* New( PluginManager* pluginManager ); diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index 52896e992..b6c08bbcb 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -55,7 +55,7 @@ class LinterPlugin : public UICodeEditorPlugin { "Use static code analysis tool used to flag programming errors, bugs, " "stylistic errors, and suspicious constructs.", LinterPlugin::New, - { 0, 1, 0 }, + { 0, 2, 0 }, LinterPlugin::NewSync }; } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp index 978205d2a..fdc2485f0 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp @@ -25,7 +25,7 @@ class LSPClientPlugin : public UICodeEditorPlugin { public: static PluginDefinition Definition() { return { "lspclient", "LSP Client", "Language Server Protocol Client.", - LSPClientPlugin::New, { 0, 0, 2 }, LSPClientPlugin::NewSync }; + LSPClientPlugin::New, { 0, 2, 0 }, LSPClientPlugin::NewSync }; } static UICodeEditorPlugin* New( PluginManager* pluginManager ); diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 2960c8cf8..666f49a79 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -728,6 +728,13 @@ UIMenu* SettingsMenu::createTerminalMenu() { getKeybind( "terminal-rename" ) ) ->setId( "terminal-rename" ); + mTerminalMenu->addSeparator(); + + mTerminalMenu + ->add( i18n( "configure_terminal_shell", "Configure Terminal Shell" ), + findIcon( "terminal" ), getKeybind( "configure-terminal-shell" ) ) + ->setId( "configure-terminal-shell" ); + mTerminalMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { const std::string& id( event->getNode()->getId() ); if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { @@ -1222,12 +1229,19 @@ UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu->addSeparator(); mToolsMenu - ->add( i18n( "check_languages_health", "Check Languages Health" ), nullptr, - getKeybind( "check-languages-health" ) ) + ->add( i18n( "check_languages_health", "Check Languages Health" ), + findIcon( "hearth-pulse" ), getKeybind( "check-languages-health" ) ) ->setId( "check-languages-health" ); mToolsMenu->addSeparator(); + mToolsMenu + ->add( i18n( "configure_terminal_shell", "Configure Terminal Shell" ), + findIcon( "terminal" ), getKeybind( "configure-terminal-shell" ) ) + ->setId( "configure-terminal-shell" ); + + mToolsMenu->addSeparator(); + mToolsMenu ->add( i18n( "load_cur_dir_as_folder", "Load current document directory as folder" ), findIcon( "folder" ), getKeybind( "load-current-dir" ) ) diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 474c5f22e..434e851a0 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -89,6 +89,72 @@ void TerminalManager::setUseFrameBuffer( bool useFrameBuffer ) { mUseFrameBuffer = useFrameBuffer; } +void TerminalManager::configureTerminalShell() { + const std::string layout( R"xml( + + + + + + + + + + + + + )xml" ); + UIWindow* window = mApp->getUISceneNode()->loadLayoutFromString( layout )->asType(); + UIComboBox* shellCombo = window->find( "shell_combo" ); + UIPushButton* ok = window->find( "ok" ); + UIPushButton* cancel = window->find( "cancel" ); + const std::vector list{ + "bash", "sh", "zsh", "fish", "nu", "csh", "tcsh", "ksh", "dash", "cmd", "powershell", + }; + std::vector found; + for ( const auto& i : list ) { + std::string f( Sys::which( i ) ); + if ( !f.empty() ) + found.emplace_back( std::move( f ) ); + } + shellCombo->getListBox()->addListBoxItems( found ); + const char* shellEnv = std::getenv( "SHELL" ); + if ( !mApp->termConfig().shell.empty() ) { + shellCombo->getListBox()->setSelected( mApp->termConfig().shell ); + shellCombo->setText( mApp->termConfig().shell ); + } else if ( shellEnv ) { + std::string shellEnvStr( FileSystem::fileExists( shellEnv ) ? shellEnv + : Sys::which( shellEnv ) ); + if ( !shellEnvStr.empty() ) + shellCombo->getListBox()->setSelected( shellEnvStr ); + } + auto setShellFn = []( App* app, UIWindow* window, UIComboBox* shellCombo ) { + std::string shell( shellCombo->getText().toUtf8() ); + if ( !Sys::which( shell ).empty() || FileSystem::fileExists( shell ) ) { + app->getConfig().term.shell = shell; + window->closeWindow(); + } else { + app->errorMsgBox( app->i18n( + "shell_not_found", "The shell selected was not found in the file system.\nMake " + "sure that the shell is visible in your PATH" ) ); + } + }; + ok->setFocus(); + ok->addMouseClickListener( + [&, window, shellCombo]( const MouseEvent* ) { setShellFn( mApp, window, shellCombo ); }, + MouseButton::EE_BUTTON_LEFT ); + cancel->addMouseClickListener( [window]( const MouseEvent* ) { window->closeWindow(); }, + EE_BUTTON_LEFT ); + window->on( Event::KeyDown, [window]( const Event* event ) { + if ( event->asKeyEvent()->getKeyCode() == KEY_ESCAPE ) + window->closeWindow(); + } ); + window->center(); + window->on( Event::OnWindowReady, [ok] ( const Event* ) { + ok->setFocus(); + } ); +} + UIMenu* TerminalManager::createColorSchemeMenu() { mColorSchemeMenuesCreatedWithHeight = mApp->uiSceneNode()->getPixelsSize().getHeight(); size_t maxItems = 19; @@ -140,8 +206,7 @@ void TerminalManager::updateMenuColorScheme( UIMenuSubMenu* colorSchemeMenu ) { } UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabWidget* inTabWidget, - const std::string& workingDir, - const std::string& program, + const std::string& workingDir, std::string program, const std::vector& args ) { #if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN UIMessageBox* msgBox = UIMessageBox::New( @@ -179,6 +244,9 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW } } + if ( program.empty() && !mApp->termConfig().shell.empty() ) + program = mApp->termConfig().shell; + UITerminal* term = UITerminal::New( mApp->getTerminalFont() ? mApp->getTerminalFont() : mApp->getFontMono(), mApp->termConfig().fontSize.asPixels( 0, Sizef(), mApp->getDisplayDPI() ), initialSize, diff --git a/src/tools/ecode/terminalmanager.hpp b/src/tools/ecode/terminalmanager.hpp index 85a47fc6d..c40b87fa0 100644 --- a/src/tools/ecode/terminalmanager.hpp +++ b/src/tools/ecode/terminalmanager.hpp @@ -17,8 +17,7 @@ class TerminalManager { UITerminal* createNewTerminal( const std::string& title = "", UITabWidget* inTabWidget = nullptr, - const std::string& workingDir = "", - const std::string& program = "", + const std::string& workingDir = "", std::string program = "", const std::vector& args = {} ); void applyTerminalColorScheme( const TerminalColorScheme& colorScheme ); @@ -47,6 +46,8 @@ class TerminalManager { void setUseFrameBuffer( bool useFrameBuffer ); + void configureTerminalShell(); + protected: App* mApp; std::string mTerminalColorSchemesPath; diff --git a/src/tools/ecode/version.hpp b/src/tools/ecode/version.hpp index 7ce495c95..a62751e6d 100644 --- a/src/tools/ecode/version.hpp +++ b/src/tools/ecode/version.hpp @@ -8,7 +8,7 @@ using namespace EE; #define ECODE_MAJOR_VERSION 0 #define ECODE_MINOR_VERSION 4 -#define ECODE_PATCH_LEVEL 6 +#define ECODE_PATCH_LEVEL 7 #define ECODE_CODENAME "Vajra" /** The compiled version of the library */