diff --git a/bin/assets/i18n/de.xml b/bin/assets/i18n/de.xml
index dbbb61bf8..92a435abe 100644
--- a/bin/assets/i18n/de.xml
+++ b/bin/assets/i18n/de.xml
@@ -561,8 +561,7 @@ Bitte die Anwendung neu starten.
Einen Ordner öffnen
Alle Dateien im Ordner öffnen
Befehlspalette öffnen
- Ordner aktueller Datei öffnen
- Ordner aktueller Datei öffnen...
+ Ordner aktueller Datei öffnen
Kontextmenü öffnen
Dokumentsymbolsuche öffnen
Geöffnete Dokumente
@@ -574,7 +573,7 @@ in einem neuen Fenster geöffnet werden.
Dateien in neuem Fenster öffnen
Zuerst muss ein Ordner geöffnet werden.
Ordner öffnen
- Ordner öffnen...
+ Ordner öffnen
Globale Suche öffnen
In neuer horizontaler Kachel öffnen
In neuem Fenster öffnen
@@ -870,7 +869,7 @@ in der Baumansicht und in Öffen-/Schließdialogen aktivieren.
Dateipfad und -position kopieren
Ausschneiden
Löschen
- Überordner öffnen...
+ Überordner öffnen
Einfügen
Wiederholen
Alles auswählen
diff --git a/bin/assets/i18n/en.xml b/bin/assets/i18n/en.xml
index f16c8e72e..1531eab40 100644
--- a/bin/assets/i18n/en.xml
+++ b/bin/assets/i18n/en.xml
@@ -546,8 +546,7 @@ Please restart the application.
Open a Folder
Open All Files in Folder
Open Command Palette
- Open Containing Folder
- Open Containing Folder...
+ Open Containing Folder in File Manager
Open Context Menu
Open Document Symbol Search
Open Documents
@@ -559,7 +558,7 @@ controls whether a new window is created or not.
Open Files in New Window
You must first open a folder.
Open Folder
- Open Folder...
+ Open Folder in File Manager
Open Global Search
Open In New Horizontal Split
Open In New Window
@@ -855,7 +854,7 @@ the directory tree and in file dialogs to open a folder or file.
Copy File Path and Position
Cut
Delete
- Open Containing Folder...
+ Open Containing Folder in File Manager
Paste
Redo
Select All
diff --git a/bin/assets/i18n/zh_CN.xml b/bin/assets/i18n/zh_CN.xml
index 27abd89c7..aad7cb60d 100644
--- a/bin/assets/i18n/zh_CN.xml
+++ b/bin/assets/i18n/zh_CN.xml
@@ -423,8 +423,7 @@ Restart ecode to see the changes.
打开一个文件
打开一个文件夹
打开命令网络
- 打开当前文件夹
- 打开当前文件夹...
+ 打开当前文件夹
打开上下文菜单
打开文档符号查找
打开文档
@@ -433,7 +432,7 @@ Restart ecode to see the changes.
从网络打开文件...
请先打开文件夹。
打开文件夹
- 打开文件夹...
+ 打开文件夹
全局搜索
在新水平分页中打开
在新窗口中打开
@@ -644,7 +643,7 @@ file in the directory tree.
Copy File Path and Position
Paste
Delete
- Open Containing Folder...
+ Open Containing Folder in File Manager
粘贴
重做
全选
diff --git a/include/eepp/system/filesystem.hpp b/include/eepp/system/filesystem.hpp
index 647aeab85..e3715d576 100644
--- a/include/eepp/system/filesystem.hpp
+++ b/include/eepp/system/filesystem.hpp
@@ -74,7 +74,7 @@ class EE_API FileSystem {
static bool fileWrite( const std::string& filepath, const std::vector& data );
/** Write a file in binary mode and close it. */
- static bool fileWrite( const std::string& filepath, const std::string& data );
+ static bool fileWrite( const std::string& filepath, std::string_view data );
/** Deletes a file from the file system. */
static bool fileRemove( const std::string& filepath );
diff --git a/src/eepp/system/filesystem.cpp b/src/eepp/system/filesystem.cpp
index 8b0bab3a9..9c3d0b713 100644
--- a/src/eepp/system/filesystem.cpp
+++ b/src/eepp/system/filesystem.cpp
@@ -186,8 +186,8 @@ bool FileSystem::fileWrite( const std::string& filepath, const std::vector( &data[0] ), (Uint32)data.size() );
}
-bool FileSystem::fileWrite( const std::string& filepath, const std::string& data ) {
- return fileWrite( filepath, (const Uint8*)data.c_str(), (Uint32)data.size() );
+bool FileSystem::fileWrite( const std::string& filepath, std::string_view data ) {
+ return fileWrite( filepath, (const Uint8*)data.data(), (Uint32)data.size() );
}
bool FileSystem::fileRemove( const std::string& filepath ) {
diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp
index 314a102b9..fc2e7592c 100644
--- a/src/eepp/ui/uicodeeditor.cpp
+++ b/src/eepp/ui/uicodeeditor.cpp
@@ -1405,10 +1405,10 @@ void UICodeEditor::createDefaultContextMenuOptions( UIPopUpMenu* menu ) {
if ( mDoc->hasFilepath() ) {
menu->addSeparator();
- menuAdd(
- menu,
- i18n( "uicodeeditor_open_containing_folder_ellipsis", "Open Containing Folder..." ),
- "folder-open", "open-containing-folder" );
+ menuAdd( menu,
+ i18n( "uicodeeditor_open_containing_folder_in_fm",
+ "Open Containing Folder in File Manager" ),
+ "folder-open", "open-containing-folder" );
menuAdd( menu,
i18n( "uicodeeditor_copy_containing_folder_path_ellipsis",
diff --git a/src/thirdparty/efsw b/src/thirdparty/efsw
index b81cd84d7..71e43ca3b 160000
--- a/src/thirdparty/efsw
+++ b/src/thirdparty/efsw
@@ -1 +1 @@
-Subproject commit b81cd84d765b255c943a93ae20b8a1d5fe7033dc
+Subproject commit 71e43ca3bd9b4df7b92bcfed792c028341eb8c62
diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp
index da0e1c525..34826be86 100644
--- a/src/tools/ecode/ecode.cpp
+++ b/src/tools/ecode/ecode.cpp
@@ -546,7 +546,9 @@ UIFileDialog* App::saveFileDialog( UICodeEditor* editor, bool focusOnClose ) {
std::string filename( editor->getDocument().getFilename() );
if ( FileSystem::fileExtension( editor->getDocument().getFilename() ).empty() )
filename += editor->getSyntaxDefinition().getFileExtension();
- std::string folderPath( FileSystem::fileRemoveFileName( editor->getDocument().getFilePath() ) );
+ std::string folderPath( !mLastFileFolder.empty() ? mLastFileFolder
+ : FileSystem::fileRemoveFileName(
+ editor->getDocument().getFilePath() ) );
if ( !FileSystem::isDirectory( folderPath ) )
folderPath = getLastUsedFolder();
UIFileDialog* dialog = UIFileDialog::New(
@@ -565,6 +567,7 @@ UIFileDialog* App::saveFileDialog( UICodeEditor* editor, bool focusOnClose ) {
if ( !path.empty() && !FileSystem::isDirectory( path ) &&
FileSystem::fileWrite( path, "" ) ) {
if ( editor->getDocument().save( path ) ) {
+ mLastFileFolder = FileSystem::fileRemoveFileName( path );
insertRecentFileAndUpdateUI( path );
updateEditorState();
} else {
@@ -1540,8 +1543,8 @@ void App::onTabCreated( UITab* tab, UIWidget* ) {
menuAdd( "split_top", "Split Top", "split-vertical", "split-top" );
menuAdd( "split_bottom", "Split Bottom", "split-vertical", "split-bottom" );
- menuAdd( "open_containing_folder_ellipsis", "Open Containing Folder...", "folder-open",
- "open-containing-folder" );
+ menuAdd( "open_containing_folder_in_fm", "Open Containing Folder in File Manager",
+ "folder-open", "open-containing-folder" );
menuAdd( "copy_containing_folder_path_ellipsis", "Copy Containing Folder Path...",
"copy", "copy-containing-folder-path" );
@@ -2483,8 +2486,8 @@ void App::fullscreenToggle() {
mSettings->updateViewMenu();
}
-void App::showGlobalSearch( bool searchAndReplace ) {
- mGlobalSearchController->showGlobalSearch( searchAndReplace );
+void App::showGlobalSearch( bool searchAndReplace, std::optional pathFilters ) {
+ mGlobalSearchController->showGlobalSearch( searchAndReplace, pathFilters );
}
void App::showFindView() {
diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp
index fdbef6e1e..cb338b500 100644
--- a/src/tools/ecode/ecode.hpp
+++ b/src/tools/ecode/ecode.hpp
@@ -124,7 +124,7 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
void downloadFileWebDialog();
- void showGlobalSearch( bool searchAndReplace );
+ void showGlobalSearch( bool searchAndReplace, std::optional pathFilters = {} );
void showFindView();
@@ -504,7 +504,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
void setTheme( const std::string& path );
- void loadImageFromMedium( const std::string& path, bool isMemory, bool forcePreview = false, bool forceTab = false );
+ void loadImageFromMedium( const std::string& path, bool isMemory, bool forcePreview = false,
+ bool forceTab = false );
void loadImageFromPath( const std::string& path );
@@ -568,6 +569,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
bool pluginsDisabled() const { return mDisablePlugins; }
+ void loadFolder( std::string path, bool forceNewWindow = false );
+
protected:
std::vector mArgs;
EE::Window::Window* mWindow{ nullptr };
@@ -717,8 +720,6 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
void saveDoc();
- void loadFolder( std::string path, bool forceNewWindow = false );
-
void loadKeybindings();
void reloadKeybindings();
diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp
index c38a2a853..78f26e5e8 100644
--- a/src/tools/ecode/globalsearchcontroller.cpp
+++ b/src/tools/ecode/globalsearchcontroller.cpp
@@ -565,7 +565,8 @@ void GlobalSearchController::initGlobalSearchBar(
mGlobalSearchTree = mGlobalSearchTreeSearch;
}
-void GlobalSearchController::showGlobalSearch( bool searchReplace ) {
+void GlobalSearchController::showGlobalSearch( bool searchReplace,
+ std::optional pathFilters ) {
mApp->hideLocateBar();
mApp->hideSearchBar();
mApp->hideStatusTerminal();
@@ -606,6 +607,8 @@ void GlobalSearchController::showGlobalSearch( bool searchReplace ) {
searchReplace, escapeSequenceChk->isChecked() );
}
}
+ if ( mGlobalSearchWhereInput && pathFilters )
+ mGlobalSearchWhereInput->setText( *pathFilters );
updateGlobalSearchBar();
mApp->getStatusBar()->updateState();
}
diff --git a/src/tools/ecode/globalsearchcontroller.hpp b/src/tools/ecode/globalsearchcontroller.hpp
index 25314521f..7ea91bc03 100644
--- a/src/tools/ecode/globalsearchcontroller.hpp
+++ b/src/tools/ecode/globalsearchcontroller.hpp
@@ -55,7 +55,7 @@ class GlobalSearchController {
void showGlobalSearch();
- void showGlobalSearch( bool searchAndReplace );
+ void showGlobalSearch( bool searchAndReplace, std::optional pathFilters = {} );
void updateColorScheme( const SyntaxColorScheme& colorScheme );
diff --git a/src/tools/ecode/plugins/plugincontextprovider.hpp b/src/tools/ecode/plugins/plugincontextprovider.hpp
index f9b7bde3a..8eefd1d9c 100644
--- a/src/tools/ecode/plugins/plugincontextprovider.hpp
+++ b/src/tools/ecode/plugins/plugincontextprovider.hpp
@@ -142,6 +142,11 @@ class PluginContextProvider {
bool forcePreview = false, bool forceTab = false ) = 0;
virtual void loadImageFromPath( const std::string& path ) = 0;
+
+ virtual void loadFolder( std::string path, bool forceNewWindow = false ) = 0;
+
+ virtual void showGlobalSearch( bool searchAndReplace,
+ std::optional pathFilters = {} ) = 0;
};
} // namespace ecode
diff --git a/src/tools/ecode/projectbuild.cpp b/src/tools/ecode/projectbuild.cpp
index 4e3a81269..e67a57bbb 100644
--- a/src/tools/ecode/projectbuild.cpp
+++ b/src/tools/ecode/projectbuild.cpp
@@ -836,7 +836,7 @@ void ProjectBuildManager::runConfig( StatusAppOutputController* saoc ) {
finalBuild.cmd = finalBuild.workingDir + finalBuild.cmd;
}
- auto cmd = finalBuild.cmd + " " + finalBuild.args;
+ auto cmd = finalBuild.cmd + ( !finalBuild.args.empty() ? ( " " + finalBuild.args ) : "" );
if ( finalBuild.runInTerminal ) {
UITerminal* term = mApp->getTerminalManager()->createTerminalInSplitter(
finalBuild.workingDir, "", {}, {}, false );
diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp
index eec714c07..9356ff2b7 100644
--- a/src/tools/ecode/settingsmenu.cpp
+++ b/src/tools/ecode/settingsmenu.cpp
@@ -47,9 +47,13 @@ void SettingsMenu::createSettingsMenu( App* app, UIMenuBar* menuBar ) {
getKeybind( "open-file" ) )
->setId( "open-file" );
mSettingsMenu
- ->add( i18n( "open_folder_ellipsis", "Open Folder..." ), findIcon( "document-open" ),
- getKeybind( "open-folder" ) )
+ ->add( i18n( "open_folder_in_fm", "Open Folder in File Manager" ),
+ findIcon( "document-open" ), getKeybind( "open-folder" ) )
->setId( "open-folder" );
+ mSettingsMenu
+ ->add( i18n( "open_folder_in_new_window", "Open Folder in New ecode Window" ),
+ findIcon( "folder-open" ) )
+ ->setId( "open-folder-in-new-window" );
mSettingsMenu
->add( i18n( "open_file_from_web_ellipsis", "Open File from Web..." ),
findIcon( "download-cloud" ), getKeybind( "download-file-web" ) )
@@ -1066,7 +1070,7 @@ UIMenu* SettingsMenu::createEditMenu() {
mEditMenu->addSeparator();
mEditMenu
- ->add( i18n( "open_containing_folder_ellipsis", "Open Containing Folder..." ),
+ ->add( i18n( "open_containing_folder_in_fm", "Open Containing Folder in File Manager" ),
findIcon( "folder-open" ), getKeybind( "open-containing-folder" ) )
->setId( "open-containing-folder" );
mEditMenu
@@ -2284,9 +2288,15 @@ void SettingsMenu::createProjectTreeMenu() {
mProjectTreeMenu
->add( i18n( "new_folder_ellipsis", "New Folder..." ), findIcon( "folder-add" ) )
->setId( "new_folder" );
+ mProjectTreeMenu->addSeparator();
mProjectTreeMenu
- ->add( i18n( "open_folder_ellipsis", "Open Folder..." ), findIcon( "folder-open" ) )
+ ->add( i18n( "open_folder_in_fm", "Open Folder in File Manager" ),
+ findIcon( "folder-open" ) )
->setId( "open_folder" );
+ mProjectTreeMenu
+ ->add( i18n( "open_folder_in_new_window", "Open Folder in New ecode Window" ),
+ findIcon( "folder-open" ) )
+ ->setId( "open-folder-in-new-window" );
mProjectTreeMenu
->add( i18n( "execute_dir_in_terminal", "Open directory in terminal" ),
findIcon( "filetype-bash" ) )
@@ -2311,8 +2321,13 @@ void SettingsMenu::createProjectTreeMenu() {
->setId( "configure-ignore-files" );
} else if ( !mApp->getFileSystemModel() ) {
mProjectTreeMenu
- ->add( i18n( "open_folder_ellipsis", "Open Folder..." ), findIcon( "folder-open" ) )
+ ->add( i18n( "open_folder_in_fm", "Open Folder in File Manager" ),
+ findIcon( "folder-open" ) )
->setId( "open-folder" );
+ mProjectTreeMenu
+ ->add( i18n( "open_folder_in_new_window", "Open Folder in New ecode Window" ),
+ findIcon( "folder-open" ) )
+ ->setId( "open_folder_in_new_window" );
}
mProjectTreeMenu->on( Event::OnItemClicked, [this]( const Event* event ) {
@@ -2320,12 +2335,16 @@ void SettingsMenu::createProjectTreeMenu() {
return;
UIMenuItem* item = event->getNode()->asType();
std::string id( item->getId() );
+ if ( id.empty() )
+ return;
if ( "new_file" == id || "new_file_in_place" == id ) {
mApp->newFile( FileInfo( mApp->getCurrentProject() ) );
} else if ( "new_folder" == id ) {
mApp->newFolder( FileInfo( mApp->getCurrentProject() ) );
} else if ( "open_folder" == id ) {
Engine::instance()->openURI( mApp->getCurrentProject() );
+ } else if ( "open_folder_in_new_window" == id ) {
+ mApp->loadFolder( mApp->getCurrentProject(), true );
} else if ( "execute_dir_in_terminal" == id ) {
mApp->getTerminalManager()->createNewTerminal( "", nullptr, mApp->getCurrentProject() );
} else if ( "show-hidden-files" == id ) {
@@ -2365,20 +2384,31 @@ void SettingsMenu::createProjectTreeMenu( const FileInfo& file ) {
mProjectTreeMenu
->add( i18n( "new_folder_ellipsis", "New Folder..." ), findIcon( "folder-add" ) )
->setId( "new_folder" );
+ mProjectTreeMenu->addSeparator();
mProjectTreeMenu
- ->add( i18n( "open_folder_ellipsis", "Open Folder..." ), findIcon( "folder-open" ) )
+ ->add( i18n( "open_folder_in_fm", "Open Folder in File Manager" ),
+ findIcon( "folder-open" ) )
->setId( "open_folder" );
+ mProjectTreeMenu
+ ->add( i18n( "open_folder_in_new_window", "Open Folder in New ecode Window" ),
+ findIcon( "folder-open" ) )
+ ->setId( "open_folder_in_new_window" );
mProjectTreeMenu
->add( i18n( "open_all_files_in_folder", "Open All Files in Folder" ),
findIcon( "folder-open" ) )
->setId( "open_all_files_in_folder" );
+ mProjectTreeMenu->addSeparator();
+ mProjectTreeMenu
+ ->add( i18n( "find_in_folder_ellipsis", "Find in Folder..." ),
+ findIcon( "file-search" ) )
+ ->setId( "find_in_folder" );
} else {
mProjectTreeMenu->add( i18n( "open_file", "Open File" ), findIcon( "document-open" ) )
->setId( "open_file" );
mProjectTreeMenu
- ->add( i18n( "open_containing_folder_ellipsis", "Open Containing Folder..." ),
+ ->add( i18n( "open_containing_folder_in_fm", "Open Containing Folder in File Manager" ),
findIcon( "folder-open" ) )
- ->setId( "open_containing_folder" );
+ ->setId( "open_containing_folder_in_fm" );
mProjectTreeMenu
->add( i18n( "new_file_in_directory_ellipsis", "New File in directory..." ),
findIcon( "file-add" ) )
@@ -2464,12 +2494,20 @@ void SettingsMenu::createProjectTreeMenu( const FileInfo& file ) {
} );
} else if ( "rename" == id ) {
mApp->renameFile( file );
- } else if ( "open_containing_folder" == id ) {
+ } else if ( "open_containing_folder_in_fm" == id ) {
Engine::instance()->openURI( file.getDirectoryPath() );
} else if ( "open_folder" == id ) {
Engine::instance()->openURI( file.getFilepath() );
+ } else if ( "open_folder_in_new_window" == id ) {
+ mApp->loadFolder( file.getFilepath(), true );
} else if ( "open_all_files_in_folder" == id ) {
mApp->openAllFilesInFolder( file );
+ } else if ( "find_in_folder" == id ) {
+ std::string folder = file.getFilepath();
+ FileSystem::filePathRemoveBasePath( mApp->getCurrentProject(), folder );
+ FileSystem::dirAddSlashAtEnd( folder );
+ folder += "*";
+ mApp->showGlobalSearch( false, folder );
} else if ( "show-hidden-files" == id ) {
mApp->toggleHiddenFiles();
} else if ( "execute_in_terminal" == id ) {
diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp
index 66d3c83a4..8a61004e7 100644
--- a/src/tools/ecode/terminalmanager.cpp
+++ b/src/tools/ecode/terminalmanager.cpp
@@ -16,7 +16,8 @@ UITerminal* TerminalManager::createTerminalInSplitter(
if ( !LuaPattern::hasMatches( os, "Windows 1%d"sv ) &&
!LuaPattern::hasMatches( os, "Windows Server 201[69]"sv ) &&
!LuaPattern::hasMatches( os, "Windows Server 202%d"sv ) ) {
- displayError( workingDir );
+ if ( fallback )
+ displayError( workingDir );
return nullptr;
}
#endif
@@ -318,7 +319,7 @@ std::string quoteString( std::string str ) {
static int 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 =
+ static const std::string_view RUN_HELPER =
R"shellscript(REM USAGE: ecode-run-helper DIRECTORY AUTOCLOSE COMMAND...
REM unnecessary, but we get the directory
@@ -353,9 +354,9 @@ if not %autoclose%==1 pause
if ( !cmd.empty() && !scriptsPath.empty() ) {
std::string runHelperPath = scriptsPath + "ecode-run-helper.bat";
bool canContinue = true;
- if ( !FileSystem::fileExists( runHelperPath ) ) {
- if ( !FileSystem::fileWrite( runHelperPath, RUN_HELPER ) )
- canContinue = false;
+ if ( !FileSystem::fileExists( runHelperPath ) &&
+ !FileSystem::fileWrite( runHelperPath, RUN_HELPER ) ) {
+ canContinue = false;
}
if ( canContinue ) {
std::string cmdDir = String::trim( FileSystem::fileRemoveFileName( cmd ) );
@@ -372,6 +373,7 @@ if not %autoclose%==1 pause
}
std::vector options;
+ options.reserve( 3 );
if ( !defShell.empty() )
options.push_back( defShell );
options.push_back( "cmd" );
@@ -393,7 +395,22 @@ if not %autoclose%==1 pause
#elif EE_PLATFORM == EE_PLATFORM_MACOS
static int openExternal( const std::string&, const std::string& cmd, const std::string&,
const std::string& workingDir ) {
- static const std::string externalShell = "open -a terminal";
+
+ std::vector options = { "ghostty", "iTerm2", "eterm" };
+ 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 );
+ return Sys::execute( fcmd, workingDir );
+ } else {
+ return Sys::execute( externalShell, workingDir );
+ }
+ }
+ }
+
+ static const std::string externalShell = "open -a terminal --args";
if ( !cmd.empty() ) {
std::string fcmd = externalShell + " \"" + cmd + "\"";
Log::info( "Running: %s", fcmd );
@@ -404,7 +421,7 @@ static int openExternal( const std::string&, const std::string& cmd, const std::
#else
static int openExternal( const std::string&, const std::string& cmd, const std::string&,
const std::string& workingDir ) {
- std::vector options = { "gnome-terminal", "konsole", "xterm", "st" };
+ std::vector options = { "gnome-terminal", "konsole", "eterm", "xterm", "st" };
for ( const auto& option : options ) {
auto externalShell( Sys::which( option ) );
if ( !externalShell.empty() ) {