diff --git a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp index 138feb183..445cfab60 100644 --- a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp +++ b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp @@ -92,6 +92,8 @@ class EE_API SyntaxDefinitionManager { bool isFileFormatSupported( const std::string& filePath, std::string_view header ); + void resetFileAssociations(); + void setFileAssociations( FileAssociations&& fa ); FileAssociations getFileAssociations() const; diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index b34831afe..47f0e337d 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -1469,6 +1469,11 @@ bool SyntaxDefinitionManager::isFileFormatSupported( const std::string& filePath return &find( filePath, header ) != mDefinitions[0].get(); } +void SyntaxDefinitionManager::resetFileAssociations() { + Lock l( mFileAssociationsMutex ); + mFileAssociations.clear(); +} + void SyntaxDefinitionManager::setFileAssociations( SyntaxDefinitionManager::FileAssociations&& fa ) { Lock l( mFileAssociationsMutex ); diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 0841521cf..37e6f8cfd 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -919,10 +919,56 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed plugin->onLoadProject( projectFolder, projectPluginsStatePath ); } ); } + + loadFileAssociations( projectFolder ); } bool AppConfig::isNewVersion() const { return windowState.lastRunVersion != ecode::Version::getVersionNum(); } +void AppConfig::loadFileAssociations( const std::string& projectFolder ) { + std::string faPath( projectFolder + ".ecode/settings.json" ); + + if ( !FileSystem::fileExists( faPath ) ) { + faPath = projectFolder + ".vscode/settings.json"; + if ( !FileSystem::fileExists( faPath ) ) + return; + } + + std::string data; + if ( !FileSystem::fileGet( faPath, data ) ) + return; + + json j; + try { + j = json::parse( data, nullptr, true, true ); + } catch ( const json::exception& e ) { + Log::error( "AppConfig::loadFileAssociations - Error parsing config from " + "path %s, error: %s, config file content:\n%s", + faPath, e.what(), data ); + return; + } + + if ( j.contains( "files.associations" ) && j["files.associations"].is_object() ) { + const auto& associations = j["files.associations"]; + SyntaxDefinitionManager::FileAssociations fa; + + for ( const auto& item : associations.items() ) { + const std::string& key = item.key(); + const json& val = item.value(); + + if ( val.is_string() ) { + fa[key] = val; + } else { + Log::warning( "AppConfig::loadFileAssociations - Skipping key '%s' because its " + "value is not a string.", + key ); + } + } + + SyntaxDefinitionManager::instance()->setFileAssociations( std::move( fa ) ); + } +} + } // namespace ecode diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index 9bd754333..d6102be40 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -269,6 +269,8 @@ class AppConfig { void editorLoadedCounter( ecode::App* app ); + void loadFileAssociations( const std::string& projectFolder ); + nlohmann::json saveNode( Node* node ); Mutex tabWidgetTypesMutex; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 2dbd6bf18..1e77598ed 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2108,6 +2108,9 @@ void App::closeFolder() { mFileSystemModel->setRootPath( "" ); mPluginManager->setWorkspaceFolder( "" ); updateOpenRecentFolderBtn(); + + SyntaxDefinitionManager::instance()->resetFileAssociations(); + if ( mUniversalLocator ) mUniversalLocator->updateFilesTable(); if ( getConfig().ui.welcomeScreen ) { @@ -3524,6 +3527,8 @@ void App::loadFolder( std::string path, bool forceNewWindow ) { if ( mProjectBuildManager ) mProjectBuildManager.reset(); + SyntaxDefinitionManager::instance()->resetFileAssociations(); + mProjectBuildManager = std::make_unique( rpath, mThreadPool, mSidePanel, this ); mConfig.loadProject( rpath, mSplitter, mConfigPath, mProjectDocConfig, this,