diff --git a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp index a50dc6515..1d308c5bf 100644 --- a/include/eepp/ui/doc/syntaxdefinitionmanager.hpp +++ b/include/eepp/ui/doc/syntaxdefinitionmanager.hpp @@ -78,10 +78,17 @@ class EE_API SyntaxDefinitionManager { /* empty = all */ bool save( const std::string& path, const std::vector& def = {} ); + void setLanguageExtensionsPriority( const std::map& priorities ); + + const std::map& getLanguageExtensionsPriority() { + return mPriorities; + } + protected: SyntaxDefinitionManager(); std::vector mDefinitions; + std::map mPriorities; std::optional getLanguageIndex( const std::string& langName ); }; diff --git a/include/eepp/ui/doc/syntaxhighlighter.hpp b/include/eepp/ui/doc/syntaxhighlighter.hpp index 25119f0d6..af5eddc44 100644 --- a/include/eepp/ui/doc/syntaxhighlighter.hpp +++ b/include/eepp/ui/doc/syntaxhighlighter.hpp @@ -77,6 +77,8 @@ class EE_API SyntaxHighlighter { Int64 mFirstInvalidLine; Int64 mMaxWantedLine; Int64 mMaxTokenizationLength{ 0 }; + std::mutex mAsyncTokenizeMutex; + std::condition_variable mAsyncTokenizeConf; bool mTokenizeAsync{ false }; bool mStopTokenizing{ false }; }; diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 9b816b71c..ccb4d100c 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -708,6 +708,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Uint32 mLineBreakingColumn{ 100 }; TextRange mMatchingBrackets; Float mLongestLineWidth{ 0 }; + size_t mLongestLineIndex{ 0 }; Time mFindLongestLineWidthUpdateFrequency; Clock mLongestLineWidthLastUpdate; Clock mLastActivity; @@ -761,7 +762,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void invalidateLinesCache(); - virtual void findLongestLine(); + void findLongestLine(); + + std::pair findLongestLineInRange( const TextRange& range ); virtual Uint32 onFocus(); diff --git a/include/eepp/ui/uitreeview.hpp b/include/eepp/ui/uitreeview.hpp index 452d5aa6a..9a5e1ea2c 100644 --- a/include/eepp/ui/uitreeview.hpp +++ b/include/eepp/ui/uitreeview.hpp @@ -136,7 +136,7 @@ class EE_API UITreeView : public UIAbstractTableView { void traverseTree( TreeViewCallback ) const; - mutable UnorderedMap mViewMetadata; + mutable std::unordered_map mViewMetadata; virtual size_t getItemCount() const; diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 944e4a6e0..99a202e60 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -1841,6 +1841,11 @@ bool SyntaxDefinitionManager::save( const std::string& path, return false; } +void SyntaxDefinitionManager::setLanguageExtensionsPriority( + const std::map& priorities ) { + mPriorities = priorities; +} + std::optional SyntaxDefinitionManager::getLanguageIndex( const std::string& langName ) { size_t pos = 0; for ( const auto& def : mDefinitions ) { @@ -2276,6 +2281,15 @@ const SyntaxDefinition& SyntaxDefinitionManager::getByExtension( const std::stri std::string fileName( FileSystem::fileNameFromPath( filePath ) ); bool extHasMultipleLangs = extensionCanRepresentManyLanguages( extension ); + auto priorityLanguage = mPriorities.end(); + if ( extHasMultipleLangs ) { + priorityLanguage = mPriorities.find( extension ); + const SyntaxDefinition* def = nullptr; + if ( priorityLanguage != mPriorities.end() && + ( def = getPtrByLSPName( priorityLanguage->second ) ) ) { + return *def; + } + } // Use the filename instead if ( extension.empty() ) diff --git a/src/eepp/ui/doc/syntaxhighlighter.cpp b/src/eepp/ui/doc/syntaxhighlighter.cpp index f4f9af324..4840a17af 100644 --- a/src/eepp/ui/doc/syntaxhighlighter.cpp +++ b/src/eepp/ui/doc/syntaxhighlighter.cpp @@ -35,6 +35,11 @@ void SyntaxHighlighter::changeDoc( TextDocument* doc ) { } void SyntaxHighlighter::reset() { + if ( mTokenizeAsync ) { + mStopTokenizing = true; + std::unique_lock lock( mAsyncTokenizeMutex ); + mAsyncTokenizeConf.wait( lock, [this]() { return !mTokenizeAsync; } ); + } Lock l( mLinesMutex ); mLines.clear(); mFirstInvalidLine = 0; @@ -129,10 +134,14 @@ void SyntaxHighlighter::tokenizeAsync( std::shared_ptr pool, return; mTokenizeAsync = true; pool->run( [this, onDone] { - for ( size_t i = mFirstInvalidLine; i < mDoc->linesCount() && !mStopTokenizing; i++ ) - getLine( i ); - mStopTokenizing = false; - mTokenizeAsync = false; + { + std::unique_lock lock( mAsyncTokenizeMutex ); + for ( size_t i = mFirstInvalidLine; i < mDoc->linesCount() && !mStopTokenizing; i++ ) + getLine( i ); + mStopTokenizing = false; + mTokenizeAsync = false; + mAsyncTokenizeConf.notify_all(); + } if ( onDone ) onDone(); } ); diff --git a/src/eepp/ui/doc/syntaxtokenizer.cpp b/src/eepp/ui/doc/syntaxtokenizer.cpp index c8cb4a8ba..b64f74751 100644 --- a/src/eepp/ui/doc/syntaxtokenizer.cpp +++ b/src/eepp/ui/doc/syntaxtokenizer.cpp @@ -263,9 +263,9 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax } bool matched = false; + size_t patternsCount = curState.currentSyntax->getPatterns().size(); - for ( size_t patternIndex = 0; patternIndex < curState.currentSyntax->getPatterns().size(); - patternIndex++ ) { + for ( size_t patternIndex = 0; patternIndex < patternsCount; patternIndex++ ) { const SyntaxPattern& pattern = curState.currentSyntax->getPatterns()[patternIndex]; if ( i != 0 && pattern.patterns[0][0] == '^' ) continue; diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index f4425f546..5cea882f6 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -2259,7 +2259,7 @@ const SyntaxDefinition& TextDocument::getSyntaxDefinition() const { } void TextDocument::setSyntaxDefinition( const SyntaxDefinition& definition ) { - if ( &mSyntaxDefinition != &definition ) { + if ( mSyntaxDefinition.getLSPName() != definition.getLSPName() ) { mSyntaxDefinition = definition; notifySyntaxDefinitionChange(); } diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index f72c8ade9..f377d1e52 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -1554,12 +1554,28 @@ void UICodeEditor::onPaddingChange() { invalidateEditor( false ); } +std::pair UICodeEditor::findLongestLineInRange( const TextRange& range ) { + std::pair curRange{ mLongestLineIndex, mLongestLineWidth }; + Float longestLineWidth = mLongestLineWidth; + if ( mHorizontalScrollBarEnabled ) { + for ( Int64 lineIndex = range.start().line(); lineIndex <= range.end().line(); + lineIndex++ ) { + Float lineWidth = getLineWidth( lineIndex ); + if ( lineWidth > longestLineWidth ) { + curRange.first = lineIndex; + curRange.second = lineWidth; + longestLineWidth = lineWidth; + } + } + } + return curRange; +} + void UICodeEditor::findLongestLine() { if ( mHorizontalScrollBarEnabled ) { - mLongestLineWidth = 0; - for ( size_t lineIndex = 0; lineIndex < mDoc->linesCount(); lineIndex++ ) { - mLongestLineWidth = eemax( mLongestLineWidth, getLineWidth( lineIndex ) ); - } + auto range = findLongestLineInRange( mDoc->getDocRange() ); + mLongestLineIndex = range.first; + mLongestLineWidth = range.second; } } @@ -1581,9 +1597,6 @@ Float UICodeEditor::getLineWidth( const Int64& lineIndex ) { void UICodeEditor::updateScrollBar() { int notVisibleLineCount = (int)mDoc->linesCount() - (int)getViewPortLineCount().y; - if ( mLongestLineWidthDirty && mFont ) - updateLongestLineWidth(); - mHScrollBar->setEnabled( false ); mHScrollBar->setVisible( false ); @@ -1700,11 +1713,14 @@ void UICodeEditor::updateEditor() { mDirtyScroll = false; } -void UICodeEditor::onDocumentTextChanged( const DocumentContentChange& ) { +void UICodeEditor::onDocumentTextChanged( const DocumentContentChange& change ) { invalidateDraw(); checkMatchingBrackets(); sendCommonEvent( Event::OnTextChanged ); - invalidateLongestLineWidth(); + + auto range = findLongestLineInRange( change.range ); + mLongestLineIndex = range.first; + mLongestLineWidth = range.second; } void UICodeEditor::onDocumentCursorChange( const Doc::TextPosition& ) { @@ -2004,8 +2020,11 @@ template Float UICodeEditor::getTextWidth( const StringTyp Float UICodeEditor::getXOffsetColSanitized( TextPosition position ) const { position.setLine( eeclamp( position.line(), 0L, mDoc->linesCount() - 1 ) ); // This is different from sanitizePosition, sinze allows the last character. - position.setColumn( eeclamp( position.column(), 0L, - eemax( 0, mDoc->line( position.line() ).size() ) ) ); + position.setColumn( + eeclamp( position.column(), 0L, + eemax( 0, position.line() < static_cast( mDoc->linesCount() ) + ? mDoc->line( position.line() ).size() + : 0 ) ) ); return getXOffsetCol( position ); } @@ -2402,8 +2421,8 @@ void UICodeEditor::setEnableColorPickerOnSelection( const bool& enableColorPicke void UICodeEditor::setSyntaxDefinition( const SyntaxDefinition& definition ) { std::string oldLang( mDoc->getSyntaxDefinition().getLanguageName() ); - mDoc->setSyntaxDefinition( definition ); mDoc->getHighlighter()->reset(); + mDoc->setSyntaxDefinition( definition ); invalidateDraw(); DocSyntaxDefEvent event( this, mDoc.get(), Event::OnDocumentSyntaxDefinitionChange, oldLang, mDoc->getSyntaxDefinition().getLanguageName() ); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index a4deb6bbd..a7bfe1ee3 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2323,6 +2323,8 @@ void App::createDocManyLangsAlert( UICodeEditor* editor ) { docAlert->close(); editor->setFocus(); mConfig.languagesExtensions.priorities[ext] = lang->getLSPName(); + SyntaxDefinitionManager::instance()->setLanguageExtensionsPriority( + mConfig.languagesExtensions.priorities ); } ); } @@ -3672,6 +3674,8 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe Clock defClock; SyntaxDefinitionManager::createSingleton(); + SyntaxDefinitionManager::instance()->setLanguageExtensionsPriority( + mConfig.languagesExtensions.priorities ); Log::info( "Syntax definitions loaded in %.2f ms.", defClock.getElapsedTimeAndReset().asMilliseconds() );