diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 41ef068b9..bd4c84a37 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -225,6 +225,9 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, term.colorScheme = ini.getValue( "terminal", "colorscheme", "eterm" ); term.newTerminalOrientation = NewTerminalOrientation::fromString( ini.getValue( "terminal", "new_terminal_orientation", "vertical" ) ); + term.workingDir = TerminalWorkingDir::fromString( + ini.getValue( "terminal", "working_dir", "project" ) ); + term.workingDirOther = ini.getValue( "terminal", "working_dir_other", "" ); term.scrollback = ini.getValueI( "terminal", "scrollback", 10000 ); term.unsupportedOSWarnDisabled = ini.getValueB( "terminal", "unsupported_os_warn_disabled", false ); @@ -403,6 +406,8 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValue( "terminal", "colorscheme", term.colorScheme ); ini.setValue( "terminal", "new_terminal_orientation", NewTerminalOrientation::toString( term.newTerminalOrientation ) ); + ini.setValue( "terminal", "working_dir", TerminalWorkingDir::toString( term.workingDir ) ); + ini.setValue( "terminal", "working_dir_other", term.workingDirOther ); ini.setValue( "terminal", "scrollback", String::toString( term.scrollback ) ); ini.setValueB( "terminal", "unsupported_os_warn_disabled", term.unsupportedOSWarnDisabled ); ini.setValueB( "terminal", "close_terminal_tab_on_exit", term.closeTerminalTabOnExit ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index 84a8f4be6..abbebb34f 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -185,6 +185,35 @@ class NewTerminalOrientation { } }; +class TerminalWorkingDir { + public: + enum Mode { ProjectRoot, CurrentFileDir, UserHome, Other }; + + static Mode fromString( const std::string& mode ) { + if ( "current" == mode ) + return Mode::CurrentFileDir; + if ( "home" == mode ) + return Mode::UserHome; + if ( "other" == mode ) + return Mode::Other; + return Mode::ProjectRoot; + } + + static std::string toString( const Mode& mode ) { + switch ( mode ) { + case Mode::CurrentFileDir: + return "current"; + case Mode::UserHome: + return "home"; + case Mode::Other: + return "other"; + case Mode::ProjectRoot: + default: + return "project"; + } + } +}; + struct TerminalConfig { std::string shell; std::string shellArgs; @@ -192,6 +221,8 @@ struct TerminalConfig { StyleSheetLength fontSize{ 11, StyleSheetLength::Dp }; NewTerminalOrientation::Orientation newTerminalOrientation{ NewTerminalOrientation::Horizontal }; + TerminalWorkingDir::Mode workingDir{ TerminalWorkingDir::ProjectRoot }; + std::string workingDirOther; Uint64 scrollback{ 10000 }; bool unsupportedOSWarnDisabled{ false }; bool closeTerminalTabOnExit{ false }; diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 4fec292b3..d841ee29f 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -369,6 +369,10 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider { if ( mTerminalManager ) mTerminalManager->configureTerminalScrollback(); } ); + t.setCommand( "configure-terminal-working-dir", [this] { + if ( mTerminalManager ) + mTerminalManager->configureTerminalWorkingDir(); + } ); t.setCommand( "check-for-updates", [this] { mSettingsActions->checkForUpdates( false ); } ); t.setCommand( "create-new-window", [this] { openInNewWindow(); } ); t.setCommand( "create-new-welcome-tab", [this] { createWelcomeTab(); } ); diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 7c38c804b..d3a207eed 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -1173,6 +1173,11 @@ UIMenu* SettingsMenu::createTerminalMenu() { findIcon( "terminal" ), getKeybind( "configure-terminal-scrollback" ) ) ->setId( "configure-terminal-scrollback" ); + mTerminalMenu + ->add( i18n( "configure_terminal_working_dir", "Configure Terminal Default Working Directory" ), + findIcon( "terminal" ), getKeybind( "configure-terminal-working-dir" ) ) + ->setId( "configure-terminal-working-dir" ); + mTerminalMenu->on( Event::OnItemClicked, [this]( const Event* event ) { const std::string& id( event->getNode()->getId() ); if ( "close-terminal-tab-on-exit" == id ) { diff --git a/src/tools/ecode/statusterminalcontroller.cpp b/src/tools/ecode/statusterminalcontroller.cpp index d93f5b985..308780021 100644 --- a/src/tools/ecode/statusterminalcontroller.cpp +++ b/src/tools/ecode/statusterminalcontroller.cpp @@ -141,8 +141,9 @@ UITerminal* StatusTerminalController::createTerminal( mContext->getTerminalFont() ? mContext->getTerminalFont() : mContext->getFontMono(), mContext->termConfig().fontSize.asPixels( 0, Sizef(), mContext->getDisplayDPI() ), initialSize, program, args, env, - !workingDir.empty() ? workingDir : mContext->getCurrentWorkingDir(), 10000, nullptr, - false ); + !workingDir.empty() ? workingDir + : mContext->getTerminalManager()->getSelectedWorkingDir(), + 10000, nullptr, false ); if ( term == nullptr || term->getTerm() == nullptr ) { mContext->getTerminalManager()->displayError( workingDir ); diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index b38e398a6..54be52774 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -50,14 +50,14 @@ UITerminal* TerminalManager::createTerminalInSplitter( } else if ( splitter ) { switch ( config.term.newTerminalOrientation ) { case NewTerminalOrientation::Vertical: { - auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir; + auto cwd = workingDir.empty() ? getSelectedWorkingDir() : workingDir; splitter->split( SplitDirection::Right, splitter->getCurWidget(), false ); term = createNewTerminal( "", nullptr, cwd, program, args, env, fallback, keepAlive ); break; } case NewTerminalOrientation::Horizontal: { - auto cwd = workingDir.empty() ? mApp->getCurrentWorkingDir() : workingDir; + auto cwd = workingDir.empty() ? getSelectedWorkingDir() : workingDir; splitter->split( SplitDirection::Bottom, splitter->getCurWidget(), false ); term = createNewTerminal( "", nullptr, cwd, program, args, env, fallback, keepAlive ); @@ -263,6 +263,102 @@ void TerminalManager::configureTerminalScrollback() { } ); } +void TerminalManager::configureTerminalWorkingDir() { + static const auto layout( R"xml( + + + + + + + + + + + + + + + )xml" ); + UIWindow* window = mApp->getUISceneNode()->loadLayoutFromString( layout )->asType(); + UIComboBox* workingDirCombo = window->find( "working_dir_combo" ); + UIWidget* otherDirContainer = window->find( "other_dir_container" ); + UITextInput* otherDirInput = window->find( "other_dir_input" ); + UIPushButton* otherDirBrowse = window->find( "other_dir_browse" ); + UIPushButton* ok = window->find( "ok" ); + UIPushButton* cancel = window->find( "cancel" ); + + const std::vector options = { + mApp->i18n( "project_root_directory", "Project Root Directory" ), + mApp->i18n( "current_file_directory", "Current File Directory" ), + mApp->i18n( "user_home_directory", "User Home" ), + mApp->i18n( "other_directory", "Other" ) + }; + + workingDirCombo->getListBox()->addListBoxItems( options ); + workingDirCombo->getListBox()->setSelected( + static_cast( mApp->getConfig().term.workingDir ) ); + otherDirInput->setText( mApp->getConfig().term.workingDirOther ); + + const auto updateOtherVisible = [otherDirContainer]( TerminalWorkingDir::Mode mode ) { + otherDirContainer->setVisible( mode == TerminalWorkingDir::Other ); + }; + + updateOtherVisible( mApp->getConfig().term.workingDir ); + + workingDirCombo->on( Event::OnItemSelected, [updateOtherVisible, workingDirCombo]( auto ) { + updateOtherVisible( static_cast( + workingDirCombo->getListBox()->getItemSelectedIndex() ) ); + } ); + + otherDirBrowse->onClick( [this, otherDirInput]( auto ) { + UIFileDialog* dialog = mApp->openFileDialog(); + dialog->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MODAL ); + dialog->setTitle( mApp->i18n( "select_working_directory", "Select Working Directory" ) ); + dialog->addFilePattern( "*", true ); + dialog->setAllowFolderSelect( true ); + dialog->on( Event::OpenFile, [otherDirInput, dialog]( const Event* ) { + otherDirInput->setText( dialog->getFullPath() ); + } ); + } ); + + ok->onClick( [this, window, workingDirCombo, otherDirInput]( auto ) { + mApp->getConfig().term.workingDir = static_cast( + workingDirCombo->getListBox()->getItemSelectedIndex() ); + mApp->getConfig().term.workingDirOther = otherDirInput->getText().toUtf8(); + mApp->saveConfig(); + window->closeWindow(); + } ); + + + cancel->onClick( [window]( auto ) { window->closeWindow(); } ); + + window->on( Event::KeyDown, [window]( const Event* event ) { + if ( event->asKeyEvent()->getKeyCode() == KEY_ESCAPE ) + window->closeWindow(); + } ); + + window->center(); + window->show(); +} + +std::string TerminalManager::getSelectedWorkingDir() const { + const auto& config = mApp->getConfig().term; + switch ( config.workingDir ) { + case TerminalWorkingDir::ProjectRoot: + return !mApp->getCurrentProject().empty() ? mApp->getCurrentProject() + : mApp->getCurrentWorkingDir(); + case TerminalWorkingDir::CurrentFileDir: + return mApp->getCurrentWorkingDir(); + case TerminalWorkingDir::UserHome: + return Sys::getUserDirectory(); + case TerminalWorkingDir::Other: + return config.workingDirOther; + default: + return mApp->getCurrentWorkingDir(); + } +} + UIMenu* TerminalManager::createColorSchemeMenu( bool emptyMenu ) { mColorSchemeMenusCreatedWithHeight = emptyMenu ? 0 : mApp->uiSceneNode()->getPixelsSize().getHeight(); @@ -536,7 +632,7 @@ UITerminal* TerminalManager::createNewTerminal( UITerminal* term = UITerminal::New( mApp->getTerminalFont() ? mApp->getTerminalFont() : mApp->getFontMono(), mApp->termConfig().fontSize.asPixels( 0, Sizef(), mApp->getDisplayDPI() ), initialSize, - program, args, env, !workingDir.empty() ? workingDir : mApp->getCurrentWorkingDir(), + program, args, env, !workingDir.empty() ? workingDir : getSelectedWorkingDir(), mApp->termConfig().scrollback, nullptr, mUseFrameBuffer, keepAlive ); if ( term == nullptr || term->getTerm() == nullptr ) { diff --git a/src/tools/ecode/terminalmanager.hpp b/src/tools/ecode/terminalmanager.hpp index 9e17e46bf..afc02083d 100644 --- a/src/tools/ecode/terminalmanager.hpp +++ b/src/tools/ecode/terminalmanager.hpp @@ -58,6 +58,10 @@ class TerminalManager { void configureTerminalScrollback(); + void configureTerminalWorkingDir(); + + std::string getSelectedWorkingDir() const; + const std::string& getTerminalCurrentColorScheme() { return mTerminalCurrentColorScheme; } void setKeybindings( UITerminal* term );