diff --git a/include/eepp/system.hpp b/include/eepp/system.hpp index e38ef3f91..c7508e05c 100644 --- a/include/eepp/system.hpp +++ b/include/eepp/system.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/include/eepp/system/process.hpp b/include/eepp/system/process.hpp index 59bdeca88..9e351423f 100644 --- a/include/eepp/system/process.hpp +++ b/include/eepp/system/process.hpp @@ -49,7 +49,8 @@ class EE_API Process { ** @param command Command line to execute for this process. ** @param options A bit field of Options's to pass. */ Process( const std::string& command, const Uint32& options = getDefaultOptions(), - const size_t& bufferSize = 132072 ); + const std::map& environment = {}, + const std::string& workingDirectory = "", const size_t& bufferSize = 132072 ); ~Process(); @@ -58,7 +59,8 @@ class EE_API Process { ** @param options A bit field of Options's to pass. ** @return On success true is returned. */ bool create( const std::string& command, const Uint32& options = getDefaultOptions(), - const std::map& environment = {} ); + const std::map& environment = {}, + const std::string& workingDirectory = "" ); /** @brief Starts a new thread to receive all stdout and stderr data */ void startAsyncRead( ReadFn readStdOut = nullptr, ReadFn readStdErr = nullptr ); diff --git a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp index 3ac41e79a..1c50d1840 100644 --- a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp +++ b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp @@ -15,28 +15,32 @@ class EE_API SyntaxDefinitionManager { const SyntaxDefinition& getPlainStyle() const; - const SyntaxDefinition& getStyleByExtension( const std::string& filePath ) const; + const SyntaxDefinition& getByExtension( const std::string& filePath ) const; - const SyntaxDefinition& getStyleByHeader( const std::string& header ) const; + const SyntaxDefinition& getByHeader( const std::string& header ) const; const SyntaxDefinition& find( const std::string& filePath, const std::string& header ); - SyntaxDefinition& getStyleByExtensionRef( const std::string& filePath ); + SyntaxDefinition& getByExtensionRef( const std::string& filePath ); - const SyntaxDefinition& getStyleByLanguageName( const std::string& name ) const; + const SyntaxDefinition& getByLanguageName( const std::string& name ) const; - const SyntaxDefinition& getStyleByLanguageId( const String::HashType& id ) const; + const SyntaxDefinition& getByLanguageId( const String::HashType& id ) const; - SyntaxDefinition& getStyleByLanguageNameRef( const std::string& name ); + SyntaxDefinition& getByLanguageNameRef( const std::string& name ); std::vector getLanguageNames() const; std::vector getExtensionsPatternsSupported() const; + const SyntaxDefinition* getPtrByLanguageName( const std::string& name ) const; + + const SyntaxDefinition* getPtrByLanguageId( const String::HashType& id ) const; + protected: SyntaxDefinitionManager(); - std::vector mStyles; + std::vector mDefinitions; void addPlainText(); diff --git a/premake4.lua b/premake4.lua index da4479c2d..862964625 100644 --- a/premake4.lua +++ b/premake4.lua @@ -551,7 +551,6 @@ function build_link_configuration( package_name, use_ee_icon ) linkoptions { "-s TOTAL_MEMORY=67108864" } linkoptions { "-s USE_SDL=2" } buildoptions { "-s USE_SDL=2" } - defines { "NO_POSIX_SPAWN" } if _OPTIONS["with-emscripten-pthreads"] then buildoptions { "-s USE_PTHREADS=1" } diff --git a/projects/android-project/app/jni/eepp.mk b/projects/android-project/app/jni/eepp.mk index bbd7fff53..ddc795b6c 100644 --- a/projects/android-project/app/jni/eepp.mk +++ b/projects/android-project/app/jni/eepp.mk @@ -39,7 +39,6 @@ EEPP_C_FLAGS := \ -DEE_MBEDTLS \ -D$(EE_SDL_VERSION) \ -DAL_LIBTYPE_STATIC \ - -DNO_POSIX_SPAWN \ -I$(EEPP_INC_PATH) \ -I$(EEPP_BASE_PATH) diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 95d7c66c2..d2969a823 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1166,6 +1166,12 @@ ../../src/tools/ecode/notificationcenter.hpp ../../src/tools/ecode/plugins/linter/linterplugin.cpp ../../src/tools/ecode/plugins/linter/linterplugin.hpp +../../src/tools/ecode/plugins/lsp/lspclient.cpp +../../src/tools/ecode/plugins/lsp/lspclient.hpp +../../src/tools/ecode/plugins/lsp/lspclientmanager.cpp +../../src/tools/ecode/plugins/lsp/lspclientmanager.hpp +../../src/tools/ecode/plugins/lsp/lspplugin.cpp +../../src/tools/ecode/plugins/lsp/lspplugin.hpp ../../src/tools/ecode/plugins/pluginmanager.cpp ../../src/tools/ecode/plugins/pluginmanager.hpp ../../src/tools/ecode/projectdirectorytree.cpp diff --git a/src/eepp/system/process.cpp b/src/eepp/system/process.cpp index 22dc1f140..ba77fe637 100644 --- a/src/eepp/system/process.cpp +++ b/src/eepp/system/process.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -21,9 +22,11 @@ namespace EE { namespace System { Process::Process() {} -Process::Process( const std::string& command, const Uint32& options, const size_t& bufferSize ) : +Process::Process( const std::string& command, const Uint32& options, + const std::map& environment, + const std::string& workingDirectory, const size_t& bufferSize ) : mBufferSize( bufferSize ) { - create( command, options ); + create( command, options, environment, workingDirectory ); } Process::~Process() { @@ -36,7 +39,8 @@ Process::~Process() { } bool Process::create( const std::string& command, const Uint32& options, - const std::map& environment ) { + const std::map& environment, + const std::string& workingDirectory ) { if ( mProcess ) return false; std::vector cmdArr = String::split( command, " ", "", "\"", true ); @@ -54,9 +58,22 @@ bool Process::create( const std::string& command, const Uint32& options, envStrings.push_back( envArr[envArr.size() - 1].c_str() ); } envStrings.push_back( NULL ); - return 0 == subprocess_create_ex( strings.data(), options, envStrings.data(), PROCESS_PTR ); + + std::string cwd; + if ( !workingDirectory.empty() ) { + cwd = FileSystem::getCurrentWorkingDirectory(); + } + + auto ret = 0 == subprocess_create_ex( strings.data(), options, envStrings.data(), + !workingDirectory.empty() ? workingDirectory.c_str() + : nullptr, + PROCESS_PTR ); + + return ret; } - return 0 == subprocess_create( strings.data(), options, PROCESS_PTR ); + return 0 == subprocess_create_ex( + strings.data(), options, nullptr, + !workingDirectory.empty() ? workingDirectory.c_str() : nullptr, PROCESS_PTR ); } size_t Process::readAllStdOut( std::string& buffer ) { diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 0be97a24d..86afd918a 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -3724,43 +3724,43 @@ void SyntaxDefinitionManager::addxit() { } SyntaxDefinition& SyntaxDefinitionManager::add( SyntaxDefinition&& syntaxStyle ) { - mStyles.emplace_back( std::move( syntaxStyle ) ); - return mStyles.back(); + mDefinitions.emplace_back( std::move( syntaxStyle ) ); + return mDefinitions.back(); } const SyntaxDefinition& SyntaxDefinitionManager::getPlainStyle() const { - return mStyles[0]; + return mDefinitions[0]; } -SyntaxDefinition& SyntaxDefinitionManager::getStyleByExtensionRef( const std::string& filePath ) { - return const_cast( getStyleByExtension( filePath ) ); +SyntaxDefinition& SyntaxDefinitionManager::getByExtensionRef( const std::string& filePath ) { + return const_cast( getByExtension( filePath ) ); } const SyntaxDefinition& -SyntaxDefinitionManager::getStyleByLanguageName( const std::string& name ) const { - for ( auto& style : mStyles ) { +SyntaxDefinitionManager::getByLanguageName( const std::string& name ) const { + for ( auto& style : mDefinitions ) { if ( style.getLanguageName() == name ) return style; } - return mStyles[0]; + return mDefinitions[0]; } const SyntaxDefinition& -SyntaxDefinitionManager::getStyleByLanguageId( const String::HashType& id ) const { - for ( auto& style : mStyles ) { +SyntaxDefinitionManager::getByLanguageId( const String::HashType& id ) const { + for ( auto& style : mDefinitions ) { if ( style.getLanguageId() == id ) return style; } - return mStyles[0]; + return mDefinitions[0]; } -SyntaxDefinition& SyntaxDefinitionManager::getStyleByLanguageNameRef( const std::string& name ) { - return const_cast( getStyleByLanguageName( name ) ); +SyntaxDefinition& SyntaxDefinitionManager::getByLanguageNameRef( const std::string& name ) { + return const_cast( getByLanguageName( name ) ); } std::vector SyntaxDefinitionManager::getLanguageNames() const { std::vector names; - for ( auto& style : mStyles ) { + for ( auto& style : mDefinitions ) { names.push_back( style.getLanguageName() ); } std::sort( names.begin(), names.end() ); @@ -3769,14 +3769,24 @@ std::vector SyntaxDefinitionManager::getLanguageNames() const { std::vector SyntaxDefinitionManager::getExtensionsPatternsSupported() const { std::vector exts; - for ( auto& style : mStyles ) + for ( auto& style : mDefinitions ) for ( auto& pattern : style.getFiles() ) exts.emplace_back( pattern ); return exts; } +const SyntaxDefinition* +SyntaxDefinitionManager::getPtrByLanguageName( const std::string& name ) const { + return &getByLanguageName( name ); +} + +const SyntaxDefinition* +SyntaxDefinitionManager::getPtrByLanguageId( const String::HashType& id ) const { + return &getByLanguageId( id ); +} + const SyntaxDefinition& -SyntaxDefinitionManager::getStyleByExtension( const std::string& filePath ) const { +SyntaxDefinitionManager::getByExtension( const std::string& filePath ) const { std::string extension( FileSystem::fileExtension( filePath ) ); std::string fileName( FileSystem::fileNameFromPath( filePath ) ); @@ -3785,7 +3795,7 @@ SyntaxDefinitionManager::getStyleByExtension( const std::string& filePath ) cons extension = FileSystem::fileNameFromPath( filePath ); if ( !extension.empty() ) { - for ( auto style = mStyles.rbegin(); style != mStyles.rend(); ++style ) { + for ( auto style = mDefinitions.rbegin(); style != mDefinitions.rend(); ++style ) { for ( const auto& ext : style->getFiles() ) { if ( String::startsWith( ext, "%." ) || String::startsWith( ext, "^" ) || String::endsWith( ext, "$" ) ) { @@ -3799,13 +3809,12 @@ SyntaxDefinitionManager::getStyleByExtension( const std::string& filePath ) cons } } } - return mStyles[0]; + return mDefinitions[0]; } -const SyntaxDefinition& -SyntaxDefinitionManager::getStyleByHeader( const std::string& header ) const { +const SyntaxDefinition& SyntaxDefinitionManager::getByHeader( const std::string& header ) const { if ( !header.empty() ) { - for ( auto style = mStyles.rbegin(); style != mStyles.rend(); ++style ) { + for ( auto style = mDefinitions.rbegin(); style != mDefinitions.rend(); ++style ) { for ( const auto& hdr : style->getHeaders() ) { LuaPattern words( hdr ); int start, end; @@ -3815,14 +3824,14 @@ SyntaxDefinitionManager::getStyleByHeader( const std::string& header ) const { } } } - return mStyles[0]; + return mDefinitions[0]; } const SyntaxDefinition& SyntaxDefinitionManager::find( const std::string& filePath, const std::string& header ) { - const SyntaxDefinition& def = getStyleByHeader( header ); - if ( def.getLanguageName() == mStyles[0].getLanguageName() ) - return getStyleByExtension( filePath ); + const SyntaxDefinition& def = getByHeader( header ); + if ( def.getLanguageName() == mDefinitions[0].getLanguageName() ) + return getByExtension( filePath ); return def; } }}} // namespace EE::UI::Doc diff --git a/src/eepp/ui/doc/syntaxtokenizer.cpp b/src/eepp/ui/doc/syntaxtokenizer.cpp index 3a4554ed5..d13e3447b 100644 --- a/src/eepp/ui/doc/syntaxtokenizer.cpp +++ b/src/eepp/ui/doc/syntaxtokenizer.cpp @@ -98,7 +98,7 @@ SyntaxState SyntaxTokenizer::retrieveSyntaxState( const SyntaxDefinition& syntax syntaxState.subsyntaxInfo = &syntaxState.currentSyntax->getPatterns()[target - 1]; syntaxState.currentSyntax = - &SyntaxDefinitionManager::instance()->getStyleByLanguageName( + &SyntaxDefinitionManager::instance()->getByLanguageName( syntaxState.subsyntaxInfo->syntax ); syntaxState.currentPatternIdx = SYNTAX_TOKENIZER_STATE_NONE; syntaxState.currentLevel++; @@ -141,7 +141,7 @@ SyntaxTokenizer::tokenize( const SyntaxDefinition& syntax, const std::string& te setSubsyntaxPatternIdx( patternIndex ); curState.currentLevel++; curState.subsyntaxInfo = &enteringSubsyntax; - curState.currentSyntax = &SyntaxDefinitionManager::instance()->getStyleByLanguageName( + curState.currentSyntax = &SyntaxDefinitionManager::instance()->getByLanguageName( curState.subsyntaxInfo->syntax ); setSubsyntaxPatternIdx( SYNTAX_TOKENIZER_STATE_NONE ); }; diff --git a/src/thirdparty/subprocess/subprocess.h b/src/thirdparty/subprocess/subprocess.h index 6c40b1a04..bfb9bd186 100644 --- a/src/thirdparty/subprocess/subprocess.h +++ b/src/thirdparty/subprocess/subprocess.h @@ -113,6 +113,7 @@ subprocess_weak int subprocess_create(const char *const command_line[], subprocess_weak int subprocess_create_ex(const char *const command_line[], int options, const char *const environment[], + const char *working_directory, struct subprocess_s *const out_process); /// @brief Get the standard input file for a process. @@ -451,11 +452,12 @@ int subprocess_create_named_pipe_helper(void **rd, void **wr) { int subprocess_create(const char *const commandLine[], int options, struct subprocess_s *const out_process) { return subprocess_create_ex(commandLine, options, SUBPROCESS_NULL, - out_process); + SUBPROCESS_NULL, out_process); } int subprocess_create_ex(const char *const commandLine[], int options, const char *const environment[], + const char* working_directory, struct subprocess_s *const out_process) { #if defined(_WIN32) int fd; @@ -710,7 +712,7 @@ int subprocess_create_ex(const char *const commandLine[], int options, 1, // handles are inherited flags, // creation flags used_environment, // used environment - SUBPROCESS_NULL, // use parent's current directory + working_directory, // set process working directory SUBPROCESS_PTR_CAST(LPSTARTUPINFOA, &startInfo), // STARTUPINFO pointer SUBPROCESS_PTR_CAST(LPPROCESS_INFORMATION, &processInfo))) { @@ -764,7 +766,7 @@ int subprocess_create_ex(const char *const commandLine[], int options, } } -#if !defined(NO_POSIX_SPAWN) +#if defined(SUBPROCESS_USE_POSIX_SPAWN) extern char **environ; posix_spawn_file_actions_t actions; char *const *used_environment; @@ -837,6 +839,13 @@ int subprocess_create_ex(const char *const commandLine[], int options, } } + if (working_directory) { + if (0 != posix_spawn_file_actions_addchdir_np(&actions, working_directory)) { + posix_spawn_file_actions_destroy(&actions); + return -1; + } + } + #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcast-qual" @@ -921,6 +930,8 @@ int subprocess_create_ex(const char *const commandLine[], int options, #pragma clang diagnostic ignored "-Wcast-qual" #pragma clang diagnostic ignored "-Wold-style-cast" #endif + if (working_directory) + chdir(working_directory); if (environment) { _Exit(execve(commandLine[0], (char *const *)commandLine, diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index d16583656..d63069332 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2,6 +2,7 @@ #include "plugins/autocomplete/autocompleteplugin.hpp" #include "plugins/formatter/formatterplugin.hpp" #include "plugins/linter/linterplugin.hpp" +// #include "plugins/lsp/lspplugin.hpp" #include "version.hpp" #include #include @@ -368,6 +369,7 @@ void App::initPluginManager() { mPluginManager->registerPlugin( LinterPlugin::Definition() ); mPluginManager->registerPlugin( FormatterPlugin::Definition() ); mPluginManager->registerPlugin( AutoCompletePlugin::Definition() ); + // mPluginManager->registerPlugin( LSPPlugin::Definition() ); } void App::loadConfig( const LogLevel& logLevel ) { @@ -682,6 +684,101 @@ UIMenu* App::createHelpMenu() { return helpMenu; } +void App::setUIScaleFactor() { + UIMessageBox* msgBox = UIMessageBox::New( + UIMessageBox::INPUT, + i18n( "set_ui_scale_factor", "Set the UI scale factor (pixel density):\nMinimum value is " + "1, and maximum 6. Requires restart." ) ); + msgBox->setTitle( mWindowTitle ); + msgBox->getTextInput()->setText( String::format( "%.2f", mConfig.windowState.pixelDensity ) ); + msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); + msgBox->showWhenReady(); + msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { + msgBox->closeWindow(); + Float val; + if ( String::fromString( val, msgBox->getTextInput()->getText() ) && val >= 1 && + val <= 6 ) { + if ( mConfig.windowState.pixelDensity != val ) { + mConfig.windowState.pixelDensity = val; + UIMessageBox* msg = UIMessageBox::New( + UIMessageBox::OK, + i18n( "new_ui_scale_factor", "New UI scale factor assigned.\nPlease " + "restart the application." ) ); + msg->show(); + setFocusEditorOnClose( msg ); + } else if ( mSplitter && mSplitter->getCurWidget() ) { + mSplitter->getCurWidget()->setFocus(); + } + } else { + UIMessageBox* msg = UIMessageBox::New( UIMessageBox::OK, "Invalid value!" ); + msg->show(); + setFocusEditorOnClose( msg ); + } + } ); +} + +void App::setEditorFontSize() { + UIMessageBox* msgBox = UIMessageBox::New( + UIMessageBox::INPUT, i18n( "set_editor_font_size", "Set the editor font size:" ) ); + msgBox->setTitle( mWindowTitle ); + msgBox->getTextInput()->setText( mConfig.editor.fontSize.toString() ); + msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); + msgBox->showWhenReady(); + msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { + mConfig.editor.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); + mSplitter->forEachEditor( [&]( UICodeEditor* editor ) { + editor->setFontSize( mConfig.editor.fontSize.asDp( 0, Sizef(), mDisplayDPI ) ); + } ); + } ); + setFocusEditorOnClose( msgBox ); +} + +void App::setTerminalFontSize() { + UIMessageBox* msgBox = UIMessageBox::New( + UIMessageBox::INPUT, i18n( "set_terminal_font_size", "Set the terminal font size:" ) ); + msgBox->setTitle( mWindowTitle ); + msgBox->getTextInput()->setText( mConfig.term.fontSize.toString() ); + msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); + msgBox->showWhenReady(); + msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { + mConfig.term.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); + mSplitter->forEachWidget( [&]( UIWidget* widget ) { + if ( widget && widget->isType( UI_TYPE_TERMINAL ) ) + widget->asType()->setFontSize( + mConfig.term.fontSize.asPixels( 0, Sizef(), mDisplayDPI ) ); + } ); + } ); + setFocusEditorOnClose( msgBox ); +} + +void App::setUIFontSize() { + UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::INPUT, + i18n( "set_ui_font_size", "Set the UI font size:" ) ); + msgBox->setTitle( mWindowTitle ); + msgBox->getTextInput()->setText( mConfig.ui.fontSize.toString() ); + msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); + msgBox->showWhenReady(); + msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { + mConfig.ui.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); + Float fontSize = mConfig.ui.fontSize.asDp( 0, Sizef(), mDisplayDPI ); + UIThemeManager* manager = mUISceneNode->getUIThemeManager(); + manager->setDefaultFontSize( fontSize ); + manager->getDefaultTheme()->setDefaultFontSize( fontSize ); + mUISceneNode->forEachNode( [&]( Node* node ) { + if ( node->isType( UI_TYPE_TEXTVIEW ) ) { + UITextView* textView = node->asType(); + if ( !textView->getUIStyle()->hasProperty( PropertyId::FontSize ) ) { + textView->setFontSize( + mConfig.ui.fontSize.asDp( node->getParent()->getPixelsSize().getWidth(), + Sizef(), mUISceneNode->getDPI() ) ); + } + } + } ); + msgBox->closeWindow(); + } ); + setFocusEditorOnClose( msgBox ); +} + UIMenu* App::createWindowMenu() { mWindowMenu = UIPopUpMenu::New(); UIPopUpMenu* colorsMenu = UIPopUpMenu::New(); @@ -797,98 +894,15 @@ UIMenu* App::createWindowMenu() { return; UIMenuItem* item = event->getNode()->asType(); if ( item->getId() == "show-side-panel" ) { - mConfig.ui.showSidePanel = item->asType()->isActive(); - showSidePanel( mConfig.ui.showSidePanel ); + switchSidePanel(); } else if ( item->getId() == "ui-scale-factor" ) { - UIMessageBox* msgBox = UIMessageBox::New( - UIMessageBox::INPUT, - i18n( "set_ui_scale_factor", - "Set the UI scale factor (pixel density):\nMinimum value is " - "1, and maximum 6. Requires restart." ) ); - msgBox->setTitle( mWindowTitle ); - msgBox->getTextInput()->setText( - String::format( "%.2f", mConfig.windowState.pixelDensity ) ); - msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); - msgBox->showWhenReady(); - msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { - msgBox->closeWindow(); - Float val; - if ( String::fromString( val, msgBox->getTextInput()->getText() ) && val >= 1 && - val <= 6 ) { - if ( mConfig.windowState.pixelDensity != val ) { - mConfig.windowState.pixelDensity = val; - UIMessageBox* msg = UIMessageBox::New( - UIMessageBox::OK, - i18n( "new_ui_scale_factor", "New UI scale factor assigned.\nPlease " - "restart the application." ) ); - msg->show(); - setFocusEditorOnClose( msg ); - } else if ( mSplitter && mSplitter->getCurWidget() ) { - mSplitter->getCurWidget()->setFocus(); - } - } else { - UIMessageBox* msg = UIMessageBox::New( UIMessageBox::OK, "Invalid value!" ); - msg->show(); - setFocusEditorOnClose( msg ); - } - } ); + setUIScaleFactor(); } else if ( item->getId() == "editor-font-size" ) { - UIMessageBox* msgBox = UIMessageBox::New( - UIMessageBox::INPUT, i18n( "set_editor_font_size", "Set the editor font size:" ) ); - msgBox->setTitle( mWindowTitle ); - msgBox->getTextInput()->setText( mConfig.editor.fontSize.toString() ); - msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); - msgBox->showWhenReady(); - msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { - mConfig.term.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); - mSplitter->forEachEditor( [&]( UICodeEditor* editor ) { - editor->setFontSize( mConfig.editor.fontSize.asDp( 0, Sizef(), mDisplayDPI ) ); - } ); - } ); - setFocusEditorOnClose( msgBox ); + setEditorFontSize(); } else if ( item->getId() == "terminal-font-size" ) { - UIMessageBox* msgBox = - UIMessageBox::New( UIMessageBox::INPUT, i18n( "set_terminal_font_size", - "Set the terminal font size:" ) ); - msgBox->setTitle( mWindowTitle ); - msgBox->getTextInput()->setText( mConfig.term.fontSize.toString() ); - msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); - msgBox->showWhenReady(); - msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { - mConfig.term.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); - mSplitter->forEachWidget( [&]( UIWidget* widget ) { - if ( widget && widget->isType( UI_TYPE_TERMINAL ) ) - widget->asType()->setFontSize( - mConfig.term.fontSize.asPixels( 0, Sizef(), mDisplayDPI ) ); - } ); - } ); - setFocusEditorOnClose( msgBox ); + setTerminalFontSize(); } else if ( item->getId() == "ui-font-size" ) { - UIMessageBox* msgBox = UIMessageBox::New( - UIMessageBox::INPUT, i18n( "set_ui_font_size", "Set the UI font size:" ) ); - msgBox->setTitle( mWindowTitle ); - msgBox->getTextInput()->setText( mConfig.ui.fontSize.toString() ); - msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); - msgBox->showWhenReady(); - msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { - mConfig.ui.fontSize = StyleSheetLength( msgBox->getTextInput()->getText() ); - Float fontSize = mConfig.ui.fontSize.asDp( 0, Sizef(), mDisplayDPI ); - UIThemeManager* manager = mUISceneNode->getUIThemeManager(); - manager->setDefaultFontSize( fontSize ); - manager->getDefaultTheme()->setDefaultFontSize( fontSize ); - mUISceneNode->forEachNode( [&]( Node* node ) { - if ( node->isType( UI_TYPE_TEXTVIEW ) ) { - UITextView* textView = node->asType(); - if ( !textView->getUIStyle()->hasProperty( PropertyId::FontSize ) ) { - textView->setFontSize( mConfig.ui.fontSize.asDp( - node->getParent()->getPixelsSize().getWidth(), Sizef(), - mUISceneNode->getDPI() ) ); - } - } - } ); - msgBox->closeWindow(); - } ); - setFocusEditorOnClose( msgBox ); + setUIFontSize(); } else if ( item->getId() == "serif-font" ) { openFontDialog( mConfig.ui.serifFont, false ); } else if ( item->getId() == "monospace-font" ) { @@ -2865,7 +2879,7 @@ UIMenu* App::createFileTypeMenu() { UIMenuItem* item = event->getNode()->asType(); const String& name = item->getText(); if ( mSplitter->curEditorExistsAndFocused() ) { - mSplitter->getCurEditor()->setSyntaxDefinition( dM->getStyleByLanguageName( name ) ); + mSplitter->getCurEditor()->setSyntaxDefinition( dM->getByLanguageName( name ) ); updateCurrentFileType(); } }; diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 6227b3d99..d855f64e1 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -155,6 +155,16 @@ class App : public UICodeEditorSplitter::Client { void debugDrawData(); + void setUIFontSize(); + + void setEditorFontSize(); + + void setTerminalFontSize(); + + void setUIScaleFactor(); + + void toggleSidePanel(); + protected: EE::Window::Window* mWindow{ nullptr }; UISceneNode* mUISceneNode{ nullptr }; diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index 55282999b..6b24f9863 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -31,7 +31,7 @@ FormatterPlugin::FormatterPlugin( const PluginManager* pluginManager ) : #if FORMATTER_THREADED mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} ); #else - load( formattersPath ); + load( pluginManager ); #endif } diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 5eb7395d2..1d2107078 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -31,7 +31,7 @@ LinterPlugin::LinterPlugin( const PluginManager* pluginManager ) : #if LINTER_THREADED mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} ); #else - load( lintersPath ); + load( pluginManager ); #endif } diff --git a/src/tools/ecode/plugins/lsp/lspclient.cpp b/src/tools/ecode/plugins/lsp/lspclient.cpp new file mode 100644 index 000000000..3d24d858c --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspclient.cpp @@ -0,0 +1,7 @@ +#include "lspclient.hpp" + +namespace ecode { + +LSPClient::LSPClient() {} + +} // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspclient.hpp b/src/tools/ecode/plugins/lsp/lspclient.hpp new file mode 100644 index 000000000..9807c466f --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspclient.hpp @@ -0,0 +1,25 @@ +#ifndef ECODE_LSPCLIENT_HPP +#define ECODE_LSPCLIENT_HPP + +#include +#include +#include + +using namespace EE::System; +using namespace EE::UI; +using namespace EE::UI::Doc; + +namespace ecode { + +class LSPClient { + public: + static std::shared_ptr get( const std::shared_ptr& doc ); + + protected: + + LSPClient(); +}; + +} // namespace ecode + +#endif // ECODE_LSPCLIENT_HPP diff --git a/src/tools/ecode/plugins/lsp/lspclientmanager.cpp b/src/tools/ecode/plugins/lsp/lspclientmanager.cpp new file mode 100644 index 000000000..8098e643d --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspclientmanager.cpp @@ -0,0 +1,13 @@ +#include "lspclientmanager.hpp" + +namespace ecode { + +LSPClientManager::LSPClientManager() {} + +void LSPClientManager::load( const PluginManager* pluginManager ) {} + +size_t LSPClientManager::clientCount() const { + return mClients.size(); +} + +} // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspclientmanager.hpp b/src/tools/ecode/plugins/lsp/lspclientmanager.hpp new file mode 100644 index 000000000..67c2af091 --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspclientmanager.hpp @@ -0,0 +1,26 @@ +#ifndef ECODE_LSPCLIENTMANAGER_HPP +#define ECODE_LSPCLIENTMANAGER_HPP + +#include "../pluginmanager.hpp" +#include "lspclient.hpp" +#include + +using namespace EE; + +namespace ecode { + +class LSPClientManager { + public: + LSPClientManager(); + + void load( const PluginManager* pluginManager ); + + size_t clientCount() const; + + protected: + std::map> mClients; +}; + +} // namespace ecode + +#endif // ECODE_LSPCLIENTMANAGER_HPP diff --git a/src/tools/ecode/plugins/lsp/lspplugin.cpp b/src/tools/ecode/plugins/lsp/lspplugin.cpp new file mode 100644 index 000000000..8f524717a --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspplugin.cpp @@ -0,0 +1,123 @@ +#include "lspplugin.hpp" +#include +#include +#include +#include +#include + +using json = nlohmann::json; + +namespace ecode { + +#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ ) +#define LSP_THREADED 1 +#else +#define LSP_THREADED 0 +#endif + +UICodeEditorPlugin* LSPPlugin::New( const PluginManager* pluginManager ) { + return eeNew( LSPPlugin, ( pluginManager ) ); +} + +LSPPlugin::LSPPlugin( const PluginManager* pluginManager ) : + mPool( pluginManager->getThreadPool() ) { +#if LSP_THREADED + mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} ); +#else + load( pluginManager ); +#endif +} + +void LSPPlugin::load( const PluginManager* pluginManager ) { + std::vector paths; + std::string path( pluginManager->getResourcesPath() + "plugins/lsp.json" ); + if ( FileSystem::fileExists( path ) ) + paths.emplace_back( path ); + path = pluginManager->getPluginsPath() + "lsp.json"; + if ( FileSystem::fileExists( path ) || + FileSystem::fileWrite( path, "{\n\"config\":{},\n\"lsp\":[]\n}\n" ) ) { + mConfigPath = path; + paths.emplace_back( path ); + } + if ( paths.empty() ) + return; + for ( const auto& path : paths ) { + try { + loadLSPConfig( path ); + } catch ( json::exception& e ) { + Log::error( "Parsing linter \"%s\" failed:\n%s", path.c_str(), e.what() ); + } + } + mReady = mClientManager.clientCount() > 0; + if ( mReady ) + fireReadyCbs(); +} + +void LSPPlugin::loadLSPConfig( const std::string& path ) { + +} + +LSPPlugin::~LSPPlugin() { + mClosing = true; + Lock l( mDocMutex ); + for ( const auto& editor : mEditors ) { + for ( auto listener : editor.second ) + editor.first->removeEventListener( listener ); + editor.first->unregisterPlugin( this ); + } +} + +void LSPPlugin::onRegister( UICodeEditor* editor ) { + Lock l( mDocMutex ); + std::vector listeners; + listeners.push_back( editor->addEventListener( Event::OnDocumentLoaded, [&]( const Event* ) { + + } ) ); + + listeners.push_back( + editor->addEventListener( Event::OnDocumentClosed, [&]( const Event* event ) { + Lock l( mDocMutex ); + const DocEvent* docEvent = static_cast( event ); + TextDocument* doc = docEvent->getDoc(); + mDocs.erase( doc ); + } ) ); + + listeners.push_back( + editor->addEventListener( Event::OnDocumentChanged, [&, editor]( const Event* ) { + TextDocument* oldDoc = mEditorDocs[editor]; + TextDocument* newDoc = editor->getDocumentRef().get(); + Lock l( mDocMutex ); + mDocs.erase( oldDoc ); + mEditorDocs[editor] = newDoc; + } ) ); + + listeners.push_back( + editor->addEventListener( Event::OnCursorPosChange, [&, editor]( const Event* ) {} ) ); + + listeners.push_back( + editor->addEventListener( Event::OnDocumentSyntaxDefinitionChange, [&]( const Event* ev ) { + // const DocSyntaxDefEvent* event = static_cast( ev ); + } ) ); + + mEditors.insert( { editor, listeners } ); + mDocs.insert( editor->getDocumentRef().get() ); + mEditorDocs[editor] = editor->getDocumentRef().get(); +} + +void LSPPlugin::onUnregister( UICodeEditor* editor ) { + if ( mClosing ) + return; + Lock l( mDocMutex ); + TextDocument* doc = mEditorDocs[editor]; + auto cbs = mEditors[editor]; + for ( auto listener : cbs ) + editor->removeEventListener( listener ); + mEditors.erase( editor ); + mEditorDocs.erase( editor ); + for ( auto editor : mEditorDocs ) + if ( editor.second == doc ) + return; + mDocs.erase( doc ); +} + +} // namespace ecode diff --git a/src/tools/ecode/plugins/lsp/lspplugin.hpp b/src/tools/ecode/plugins/lsp/lspplugin.hpp new file mode 100644 index 000000000..787a3ba41 --- /dev/null +++ b/src/tools/ecode/plugins/lsp/lspplugin.hpp @@ -0,0 +1,74 @@ +#ifndef ECODE_LSPPLUGIN_HPP +#define ECODE_LSPPLUGIN_HPP + +#include "../pluginmanager.hpp" +#include "lspclientmanager.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +using namespace EE; +using namespace EE::System; +using namespace EE::UI; + +namespace ecode { + +struct LSP { + std::string name; + std::string language; + const SyntaxDefinition* langDefinition; + std::vector filePatterns; + std::string command; + std::string url; + std::vector rootIndicationFileName; +}; + +class LSPPlugin : public UICodeEditorPlugin { + public: + static PluginDefinition Definition() { + return { + "lsp", "LSP Client", "Language Server Protocol Client.", LSPPlugin::New, { 0, 1, 0 } }; + } + + static UICodeEditorPlugin* New( const PluginManager* pluginManager ); + + virtual ~LSPPlugin(); + + std::string getId() { return Definition().id; } + + std::string getTitle() { return Definition().name; } + + std::string getDescription() { return Definition().description; } + + bool isReady() const { return true; } + + void onRegister( UICodeEditor* ); + + void onUnregister( UICodeEditor* ); + + protected: + std::shared_ptr mPool; + Clock mClock; + Mutex mDocMutex; + std::unordered_map> mEditors; + std::set mDocs; + std::unordered_map mEditorDocs; + LSPClientManager mClientManager; + std::string mConfigPath; + bool mClosing{ false }; + bool mReady{ false }; + + LSPPlugin( const PluginManager* pluginManager ); + + void load( const PluginManager* pluginManager ); + + void loadLSPConfig( const std::string& path ); +}; + +} // namespace ecode + +#endif // ECODE_LSPPLUGIN_HPP diff --git a/src/tools/ecode/uitreeviewglobalsearch.cpp b/src/tools/ecode/uitreeviewglobalsearch.cpp index 1128f86e8..98555a5fc 100644 --- a/src/tools/ecode/uitreeviewglobalsearch.cpp +++ b/src/tools/ecode/uitreeviewglobalsearch.cpp @@ -133,7 +133,7 @@ UIPushButton* UITreeViewCellGlobalSearch::updateText( const std::string& text ) ProjectSearch::ResultData* res = (ProjectSearch::ResultData*)getCurIndex().parent().internalData(); - auto styleDef = SyntaxDefinitionManager::instance()->getStyleByExtension( res->file ); + auto styleDef = SyntaxDefinitionManager::instance()->getByExtension( res->file ); Uint32 from = text.find_first_not_of( ' ' ); Uint32 to = from;