diff --git a/bin/assets/plugins/lspclient.json b/bin/assets/plugins/lspclient.json index aac1f2121..142d40fb0 100644 --- a/bin/assets/plugins/lspclient.json +++ b/bin/assets/plugins/lspclient.json @@ -54,16 +54,19 @@ "name": "clangd", "url": "https://clang.llvm.org/extra/clangd/", "command": "clangd -log=error --background-index --header-insertion=never --limit-results=0 --limit-references=0 --clang-tidy=0 --use-dirty-headers --completion-style=bundled -j $NPROC", + "share_process": true, "file_patterns": ["%.c$", "%.h$", "%.C$", "%.H$", "%.objc$"] }, { "language": "cpp", "use": "clangd", + "share_process": true, "file_patterns": ["%.inl$", "%.cpp$", "%.hpp$", "%.cc$", "%.cxx$", "%.c++$", "%.hh$", "%.hxx$", "%.h++$", "%.objcpp$"] }, { "language": "objective-c", "use": "clangd", + "share_process": true, "file_patterns": ["%.m$"] }, { diff --git a/include/eepp/ui/doc/syntaxhighlighter.hpp b/include/eepp/ui/doc/syntaxhighlighter.hpp index 30b00d85a..52c9e2cd8 100644 --- a/include/eepp/ui/doc/syntaxhighlighter.hpp +++ b/include/eepp/ui/doc/syntaxhighlighter.hpp @@ -56,6 +56,10 @@ class EE_API SyntaxHighlighter { Uint64 getTokenizedLineSignature( const size_t& index ); + const Int64& getMaxTokenizationLength() const; + + void setMaxTokenizationLength( const Int64& maxTokenizationLength ); + protected: TextDocument* mDoc; std::unordered_map mLines; @@ -63,6 +67,7 @@ class EE_API SyntaxHighlighter { Mutex mLinesMutex; Int64 mFirstInvalidLine; Int64 mMaxWantedLine; + Int64 mMaxTokenizationLength{ 0 }; }; }}} // namespace EE::UI::Doc diff --git a/src/eepp/ui/doc/syntaxhighlighter.cpp b/src/eepp/ui/doc/syntaxhighlighter.cpp index 339980c12..fb3a550b6 100644 --- a/src/eepp/ui/doc/syntaxhighlighter.cpp +++ b/src/eepp/ui/doc/syntaxhighlighter.cpp @@ -46,11 +46,28 @@ void SyntaxHighlighter::invalidate( Int64 lineIndex ) { } TokenizedLine SyntaxHighlighter::tokenizeLine( const size_t& line, const Uint64& state ) { + auto& ln = mDoc->line( line ); TokenizedLine tokenizedLine; tokenizedLine.initState = state; - tokenizedLine.hash = mDoc->line( line ).getHash(); - auto res = SyntaxTokenizer::tokenizePosition( mDoc->getSyntaxDefinition(), - mDoc->line( line ).toUtf8(), state ); + tokenizedLine.hash = ln.getHash(); + if ( mMaxTokenizationLength != 0 && (Int64)ln.size() > mMaxTokenizationLength ) { + Int64 textSize = ln.size(); + Int64 pos = 0; + while ( textSize > 0 ) { + size_t chunkSize = + textSize > mMaxTokenizationLength ? mMaxTokenizationLength : textSize; + std::string substr = ln.substr( pos, chunkSize ); + SyntaxTokenPosition token{ "normal", pos, chunkSize }; + token.len = ln.size(); + tokenizedLine.tokens.emplace_back( token ); + textSize -= chunkSize; + pos += chunkSize; + } + tokenizedLine.state = state; + tokenizedLine.updateSignature(); + return tokenizedLine; + } + auto res = SyntaxTokenizer::tokenizePosition( mDoc->getSyntaxDefinition(), ln.toUtf8(), state ); tokenizedLine.tokens = std::move( res.first ); tokenizedLine.state = std::move( res.second ); tokenizedLine.updateSignature(); @@ -97,6 +114,14 @@ Uint64 SyntaxHighlighter::getTokenizedLineSignature( const size_t& index ) { return 0; } +const Int64& SyntaxHighlighter::getMaxTokenizationLength() const { + return mMaxTokenizationLength; +} + +void SyntaxHighlighter::setMaxTokenizationLength( const Int64& maxTokenizationLength ) { + mMaxTokenizationLength = maxTokenizationLength; +} + const std::vector& SyntaxHighlighter::getLine( const size_t& index ) { if ( mDoc->getSyntaxDefinition().getPatterns().empty() ) { static std::vector noHighlightVector = { { "normal", 0 } }; diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index d1c9b7ba1..8d9ec4ed0 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -2733,15 +2733,20 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo } Text& txt = mLineTextCache; + String buff; for ( const auto& token : tokens ) { - String text( pos < strLine.size() ? strLine.substr( pos, token.len ) : String() ); + const String* text = &strLine; + if ( pos < strLine.size() && !( pos == 0 && text->size() == token.len ) ) { + buff = strLine.substr( pos, token.len ); + text = &buff; + } pos += token.len; - Float textWidth = isMonospace ? getTextWidth( text ) : 0; + Float textWidth = isMonospace ? getTextWidth( *text ) : 0; if ( !isMonospace || ( position.x + textWidth >= mScreenPos.x && position.x <= mScreenPos.x + mSize.getWidth() ) ) { - Int64 curCharsWidth = text.size(); + Int64 curCharsWidth = text->size(); Int64 curPositionChar = eefloor( mScroll.x / getGlyphWidth() ); Float curMaxPositionChar = curPositionChar + maxWidth; txt.setFont( mFont ); @@ -2759,10 +2764,10 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo mLinkPosition.start().line() == line ) { if ( mLinkPosition.start().column() >= curChar && mLinkPosition.end().column() <= curChar + curCharsWidth ) { - size_t linkPos = text.find( mLink ); + size_t linkPos = text->find( mLink ); if ( linkPos != String::InvalidPos ) { - String beforeString( text.substr( 0, linkPos ) ); - String afterString( text.substr( linkPos + mLink.size() ) ); + String beforeString( text->substr( 0, linkPos ) ); + String afterString( text->substr( linkPos + mLink.size() ) ); Float offset = 0.f; Uint32 lineStyle = txt.getStyle(); @@ -2825,7 +2830,7 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo textWidth = offset; position.x += textWidth; - curChar += characterWidth( text ); + curChar += characterWidth( *text ); continue; } } @@ -2844,17 +2849,17 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo Int64 totalChars = curCharsWidth - start; Int64 end = eemin( totalChars, minimumCharsToCoverScreen ); if ( curCharsWidth >= charsToVisible ) { - txt.setString( text.substr( start, end ) ); + txt.setString( text->substr( start, end ) ); txt.draw( position.x + start * getGlyphWidth(), position.y + lineOffset ); if ( minimumCharsToCoverScreen == end ) break; } } else { - txt.setString( text.substr( 0, eemin( curCharsWidth, maxWidth ) ) ); + txt.setString( text->substr( 0, eemin( curCharsWidth, maxWidth ) ) ); txt.draw( position.x, position.y + lineOffset ); } } else { - txt.setString( text ); + txt.setString( *text ); txt.draw( position.x, position.y + lineOffset ); } @@ -2865,7 +2870,7 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo } position.x += textWidth; - curChar += characterWidth( text ); + curChar += characterWidth( *text ); } if ( mDoc->mightBeBinary() && mFont->getType() == FontType::TTF ) { diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index 58ea1320f..261cdb2d9 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -841,6 +841,10 @@ void LSPClientPlugin::loadLSPConfig( std::vector& lsps, const std std::string name = obj.contains( "name" ) ? obj["name"] : obj["use"]; if ( lspR.name == name ) { lspOverwritten = true; + lspR.usesOtherDefinition = obj.contains( "use" ); + if ( obj.contains( "share_process" ) && obj["share_process"].is_boolean() ) { + lspR.shareProcessWithOtherDefinition = obj["share_process"].get(); + } if ( obj.contains( "command" ) ) { lspR.command = parseCommand( obj["command"] ); } @@ -888,6 +892,10 @@ void LSPClientPlugin::loadLSPConfig( std::vector& lsps, const std lsp.host = tlsp.host; lsp.port = tlsp.port; lsp.initializationOptions = tlsp.initializationOptions; + lsp.usesOtherDefinition = true; + if ( obj.contains( "share_process" ) && obj["share_process"].is_boolean() ) { + lsp.shareProcessWithOtherDefinition = obj["share_process"].get(); + } break; } } @@ -903,6 +911,7 @@ void LSPClientPlugin::loadLSPConfig( std::vector& lsps, const std lsp.url = obj.value( "url", "" ); lsp.host = obj.value( "host", "" ); lsp.port = obj.value( "port", 0 ); + lsp.shareProcessWithOtherDefinition = obj.value( "share_process", false ); } lsp.commandParameters = obj.value( "command_parameters", lsp.commandParameters ); diff --git a/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp b/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp index fb7f6c80a..5ea3b106a 100644 --- a/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientservermanager.cpp @@ -88,7 +88,9 @@ void LSPClientServerManager::tryRunServer( const std::shared_ptr& std::string rootPath = mLSPWorkspaceFolder.isEmpty() ? findRootPath( lsp, doc ) : mLSPWorkspaceFolder.uri.getFSPath(); auto lspName = lsp.name.empty() ? lsp.command : lsp.name; - String::HashType id = String::hash( lspName + "|" + lsp.language + "|" + rootPath ); + String::HashType id = lsp.shareProcessWithOtherDefinition + ? String::hash( lspName + "|" + rootPath ) + : String::hash( lspName + "|" + lsp.language + "|" + rootPath ); LSPClientServer* server = nullptr; { Lock l( mClientsMutex ); diff --git a/src/tools/ecode/plugins/lsp/lspdefinition.hpp b/src/tools/ecode/plugins/lsp/lspdefinition.hpp index b1eb13f3f..2224ab2be 100644 --- a/src/tools/ecode/plugins/lsp/lspdefinition.hpp +++ b/src/tools/ecode/plugins/lsp/lspdefinition.hpp @@ -24,6 +24,8 @@ struct LSPDefinition { int port{ 0 }; nlohmann::json initializationOptions; + bool usesOtherDefinition{ false }; + bool shareProcessWithOtherDefinition{ false }; bool disabled{ false }; bool commandAvailable() const { diff --git a/src/tools/ecode/projectbuild.cpp b/src/tools/ecode/projectbuild.cpp index f12a8b9a3..73fce619b 100644 --- a/src/tools/ecode/projectbuild.cpp +++ b/src/tools/ecode/projectbuild.cpp @@ -612,41 +612,13 @@ void ProjectBuildManager::updateSidePanelTab() { buildList->setEnabled( !buildList->getListBox()->isEmpty() ); - UIDropDownList* buildTypeList = buildTab->find( "build_type_list" ); - - buildTypeList->getListBox()->clear(); - - first = buildList->getListBox()->getItemSelectedText(); - if ( !first.empty() ) { - auto foundIt = mBuilds.find( first ); - if ( foundIt != mBuilds.end() ) { - const auto& buildTypes = foundIt->second.buildTypes(); - std::vector buildTypesItems; - for ( const auto& buildType : buildTypes ) - buildTypesItems.emplace_back( buildType ); - buildTypeList->getListBox()->addListBoxItems( buildTypesItems ); - if ( buildTypeList->getListBox()->getItemIndex( mConfig.buildType ) != - eeINDEX_NOT_FOUND ) { - buildTypeList->getListBox()->setSelected( mConfig.buildType ); - mConfig.buildType = first; - } else if ( !buildTypeList->getListBox()->isEmpty() ) { - buildTypeList->getListBox()->setSelected( 0 ); - mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText(); - } - } - } - buildTypeList->setEnabled( !buildTypeList->getListBox()->isEmpty() ); + updateBuildType(); buildList->removeEventsOfType( Event::OnItemSelected ); buildList->addEventListener( Event::OnItemSelected, [this, buildList]( const Event* ) { mConfig.buildName = buildList->getListBox()->getItemSelectedText(); mConfig.buildType = ""; - updateSidePanelTab(); - } ); - - buildTypeList->removeEventsOfType( Event::OnItemSelected ); - buildTypeList->addEventListener( Event::OnItemSelected, [this, buildTypeList]( const Event* ) { - mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText(); + updateBuildType(); } ); buildButton->setEnabled( !mConfig.buildName.empty() && hasBuild( mConfig.buildName ) && @@ -676,4 +648,37 @@ void ProjectBuildManager::updateSidePanelTab() { MouseButton::EE_BUTTON_LEFT ); } +void ProjectBuildManager::updateBuildType() { + UIWidget* buildTab = mTab->getOwnedWidget()->find( "build_tab" ); + UIDropDownList* buildList = buildTab->find( "build_list" ); + UIDropDownList* buildTypeList = buildTab->find( "build_type_list" ); + + buildTypeList->getListBox()->clear(); + + String first = buildList->getListBox()->getItemSelectedText(); + if ( !first.empty() ) { + auto foundIt = mBuilds.find( first ); + if ( foundIt != mBuilds.end() ) { + const auto& buildTypes = foundIt->second.buildTypes(); + std::vector buildTypesItems; + for ( const auto& buildType : buildTypes ) + buildTypesItems.emplace_back( buildType ); + buildTypeList->getListBox()->addListBoxItems( buildTypesItems ); + if ( buildTypeList->getListBox()->getItemIndex( mConfig.buildType ) != + eeINDEX_NOT_FOUND ) { + buildTypeList->getListBox()->setSelected( mConfig.buildType ); + } else if ( !buildTypeList->getListBox()->isEmpty() ) { + buildTypeList->getListBox()->setSelected( 0 ); + mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText(); + } + } + } + buildTypeList->setEnabled( !buildTypeList->getListBox()->isEmpty() ); + + buildTypeList->removeEventsOfType( Event::OnItemSelected ); + buildTypeList->addEventListener( Event::OnItemSelected, [this, buildTypeList]( const Event* ) { + mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText(); + } ); +} + } // namespace ecode diff --git a/src/tools/ecode/projectbuild.hpp b/src/tools/ecode/projectbuild.hpp index f558a5c1a..f1933f164 100644 --- a/src/tools/ecode/projectbuild.hpp +++ b/src/tools/ecode/projectbuild.hpp @@ -268,6 +268,8 @@ class ProjectBuildManager { void buildSidePanelTab(); void updateSidePanelTab(); + + void updateBuildType(); }; } // namespace ecode diff --git a/src/tools/ecode/statusbuildoutputcontroller.cpp b/src/tools/ecode/statusbuildoutputcontroller.cpp index a04d2119c..11b45b36a 100644 --- a/src/tools/ecode/statusbuildoutputcontroller.cpp +++ b/src/tools/ecode/statusbuildoutputcontroller.cpp @@ -121,6 +121,7 @@ void StatusBuildOutputController::runBuild( const std::string& buildName, mContainer->getDocument().setSyntaxDefinition( synDef ); mContainer->getVScrollBar()->setValue( 1.f ); + mContainer->getDocument().getHighlighter()->setMaxTokenizationLength( 2048 ); UIPushButton* buildButton = getBuildButton( mApp ); if ( buildButton )