From c6a2bc2c44f495ee08f10c031b66e93503a2cfaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 15 Apr 2024 23:51:33 -0300 Subject: [PATCH] Auto-complete improvements. Added some partial Emmet support via emmet lsp. --- bin/assets/plugins/lspclient.json | 19 +++- src/eepp/graphics/text.cpp | 1 + .../autocomplete/autocompleteplugin.cpp | 86 +++++++++++++------ .../autocomplete/autocompleteplugin.hpp | 11 ++- src/tools/ecode/settingsmenu.cpp | 14 ++- 5 files changed, 90 insertions(+), 41 deletions(-) diff --git a/bin/assets/plugins/lspclient.json b/bin/assets/plugins/lspclient.json index 81986df28..51383e2c3 100644 --- a/bin/assets/plugins/lspclient.json +++ b/bin/assets/plugins/lspclient.json @@ -172,10 +172,14 @@ }, { "language": "html", - "name": "vscode-html-languageserver", - "url": "https://github.com/vscode-langservers/vscode-html-languageserver-bin", - "command": "html-languageserver --stdio", - "file_patterns": ["%.htm", "%.html"] + "name": "emmet-language-server", + "url": "https://github.com/olrtg/emmet-language-server", + "command": "emmet-language-server --stdio", + "file_patterns": ["%.htm", "%.html"], + "rootIndicationFileNames": [".git"], + "initializationOptions": { + "showSuggestionsAsSnippets": true + } }, { "language": "dockerfile", @@ -306,6 +310,13 @@ }, "command": "adeptls --infrastructure $ADEPT_ROOT", "file_patterns": ["%.adept$"] + }, + { + "language": "latex", + "name": "texlab", + "url": "https://github.com/latex-lsp", + "command": "texlab", + "file_patterns": ["%.tex$"] } ] } diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 73366d5cc..9ae9237d8 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -263,6 +263,7 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo } size.x = eemax( width, cpos.x ); width = 0; + cpos.x = pos.x; cpos.y += height; if ( i != ssize - 1 ) size.y += height; diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 45a7f7f4e..7d54b61d5 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -45,9 +45,10 @@ fuzzyMatchSymbols( const std::vector& sy int score; for ( const auto& symbols : symbolsVec ) { for ( const auto& symbol : *symbols ) { - if ( ( score = String::fuzzyMatch( symbol.text, match, false, + if ( symbol.kind == LSPCompletionItemKind::Snippet || + ( score = String::fuzzyMatch( symbol.text, match, false, symbol.kind != LSPCompletionItemKind::Text ) ) > - 0 ) { + 0 ) { if ( std::find( matches.begin(), matches.end(), symbol ) == matches.end() ) { symbol.setScore( score ); matches.push_back( symbol ); @@ -130,18 +131,17 @@ void AutoCompletePlugin::onRegister( UICodeEditor* editor ) { mDirty = true; } ) ); - listeners.push_back( - editor->addEventListener( Event::OnCursorPosChange, [this, editor]( const Event* ) { - if ( !mReplacing ) - resetSuggestions( editor ); + listeners.push_back( editor->addEventListener( Event::OnCursorPosChange, [this, editor]( + const Event* ) { + if ( !mReplacing ) + resetSuggestions( editor ); - if ( mSignatureHelpVisible && mSignatureHelpPosition.isValid() && - !editor->getDocument().getSelection().hasSelection() && - mSignatureHelpPosition.line() != - editor->getDocument().getSelection().end().line() ) { - resetSignatureHelp(); - } - } ) ); + if ( mSignatureHelpVisible && mSignatureHelpPosition.isValid() && + !editor->getDocument().getSelection().hasSelection() && + mSignatureHelpPosition.line() != editor->getDocument().getSelection().end().line() ) { + resetSignatureHelp(); + } + } ) ); listeners.push_back( editor->addEventListener( Event::OnFocusLoss, [this]( const Event* ) { resetSignatureHelp(); } ) ); @@ -459,9 +459,21 @@ void AutoCompletePlugin::updateLangCache( const std::string& langName ) { void AutoCompletePlugin::pickSuggestion( UICodeEditor* editor ) { mReplacing = true; std::string symbol( getPartialSymbol( editor->getDocumentRef().get() ) ); - if ( !symbol.empty() ) - editor->getDocument().execute( "delete-to-previous-word" ); - editor->getDocument().textInput( mSuggestions[mSuggestionIndex].text ); + const auto& suggestion = mSuggestions[mSuggestionIndex]; + auto doc = editor->getDocumentRef(); + + if ( doc->getSelections().size() == 1 && suggestion.range.isValid() && + doc->isValidRange( suggestion.range ) ) { + auto sels = doc->getSelections(); + + doc->setSelection( suggestion.range ); + doc->textInput( suggestion.insertText ); + } else { + if ( !symbol.empty() ) + doc->execute( "delete-to-previous-word" ); + doc->textInput( suggestion.text ); + } + mReplacing = false; resetSuggestions( editor ); } @@ -470,15 +482,22 @@ PluginRequestHandle AutoCompletePlugin::processCodeCompletion( const LSPCompletionList& completion ) { SymbolsList suggestions; for ( const auto& item : completion.items ) { - if ( !item.insertText.empty() ) - suggestions.push_back( - { item.kind, item.insertText, item.detail, item.sortText, item.textEdit.range } ); - - else if ( !item.textEdit.text.empty() ) - suggestions.push_back( { item.kind, item.textEdit.text, item.detail, item.sortText, - item.textEdit.range } ); - else - suggestions.push_back( { item.kind, item.filterText, item.detail, item.sortText } ); + if ( !item.textEdit.text.empty() ) { + suggestions.push_back( { item.kind, item.insertText, item.detail, item.sortText, + item.textEdit.range, item.textEdit.text, + item.documentation } ); + } else if ( !item.insertText.empty() ) { + suggestions.push_back( { item.kind, item.insertText, item.detail, item.sortText, + item.textEdit.range, item.insertText, item.documentation } ); + } else { + suggestions.push_back( { item.kind, + item.filterText, + item.detail, + item.sortText, + {}, + "", + item.documentation } ); + } } if ( suggestions.empty() || !mSuggestionsEditor ) return {}; @@ -799,6 +818,21 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc eefloor( ( iconSpace.getHeight() - icon->getSize().getHeight() ) * 0.5f ) ); icon->draw( { cursorPos.x + padding.x, cursorPos.y + mRowHeight * count + padding.y } ); } + + if ( mSuggestionIndex == (int)i && !suggestions[i].documentation.value.empty() ) { + Text text( "", editor->getFont(), editor->getFontSize() ); + text.setFillColor( normalStyle.color ); + text.setStyle( normalStyle.style ); + text.setString( suggestions[i].documentation.value ); + Vector2f boxPos = { cursorPos.x + mBoxRect.getWidth(), + cursorPos.y + mRowHeight * count }; + Sizef boxSize = { text.getTextWidth() + mBoxPadding.Left + mBoxPadding.Right, + text.getTextHeight() + mBoxPadding.Top + mBoxPadding.Bottom }; + primitives.setColor( + Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) ); + primitives.drawRoundedRectangle( { boxPos, boxSize }, 0.f, Vector2f::One, 6 ); + text.draw( boxPos.x + mBoxPadding.Left, boxPos.y + mBoxPadding.Top ); + } count++; } @@ -984,7 +1018,7 @@ void AutoCompletePlugin::runUpdateSuggestions( const std::string& symbol, } if ( tryRequestCapabilities( editor ) ) requestCodeCompletion( editor ); - if ( symbol.empty() ) + if ( symbol.empty() || symbols.empty() ) return; Lock l( mLangSymbolsMutex ); Lock l2( mSuggestionsMutex ); diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index 12c93c7c3..4ece37d46 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -27,7 +27,9 @@ class AutoCompletePlugin : public Plugin { std::string detail; std::string sortText; TextRange range; + std::string insertText; double score{ 0 }; + LSPMarkupContent documentation; void setScore( const double& score ) const { const_cast( this )->score = score; @@ -37,12 +39,15 @@ class AutoCompletePlugin : public Plugin { Suggestion( const LSPCompletionItemKind& kind, const std::string& text, const std::string& detail, const std::string& sortText, - const TextRange& range = {} ) : + const TextRange& range = {}, const std::string insertText = "", + LSPMarkupContent doc = {} ) : kind( kind ), text( text ), detail( detail ), sortText( sortText.empty() ? text : sortText ), - range( range ){}; + range( range ), + insertText( insertText ), + documentation( doc ){}; bool operator<( const Suggestion& other ) const { return getCmpStr() < other.getCmpStr(); } @@ -59,7 +64,7 @@ class AutoCompletePlugin : public Plugin { "Auto complete shows the completion popup as you type, so you can fill " "in long words by typing only a few characters.", AutoCompletePlugin::New, - { 0, 2, 2 } }; + { 0, 2, 3 } }; } static Plugin* New( PluginManager* pluginManager ); diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index fd40fa77d..c0049925d 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -118,12 +118,11 @@ void SettingsMenu::createSettingsMenu( App* app, UIMenuBar* menuBar ) { ->setId( "window-menu" ) ->asType(); - mSettingsMenu->add( i18n( "plugin_manager", "Plugin Manager" ), findIcon( "extensions" ) ) - ->setId( "plugin-manager-open" ); auto helpMenuButton = mSettingsMenu->addSubMenu( i18n( "help", "Help" ), findIcon( "help" ), createHelpMenu() ) ->setId( "help-menu" ) ->asType(); + mSettingsMenu->addSeparator(); mSettingsMenu ->add( i18n( "close", "Close" ), findIcon( "document-close" ), getKeybind( "close-tab" ) ) @@ -1439,6 +1438,11 @@ UIMenu* SettingsMenu::createViewMenu() { UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu = UIPopUpMenu::New(); + mToolsMenu->add( i18n( "plugin_manager", "Plugin Manager" ), findIcon( "extensions" ) ) + ->setId( "plugin-manager-open" ); + + mToolsMenu->addSeparator(); + mToolsMenu ->add( i18n( "locate_ellipsis", "Locate..." ), findIcon( "search" ), getKeybind( "open-locatebar" ) ) @@ -1470,11 +1474,6 @@ UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu->addSeparator(); - mToolsMenu->add( i18n( "plugin_manager", "Plugin Manager" ), findIcon( "extensions" ) ) - ->setId( "plugin-manager-open" ); - - mToolsMenu->addSeparator(); - mToolsMenu ->add( i18n( "check_languages_health", "Check Languages Health" ), findIcon( "hearth-pulse" ), getKeybind( "check-languages-health" ) ) @@ -2207,7 +2206,6 @@ void SettingsMenu::updateMenu() { mSettingsMenu->getItemId( "tools-menu" )->setVisible( !showMenuBar ); mSettingsMenu->getItemId( "window-menu" )->setVisible( !showMenuBar ); mSettingsMenu->getItemId( "help-menu" )->setVisible( !showMenuBar ); - mSettingsMenu->getItemId( "plugin-manager-open" )->setVisible( !showMenuBar ); } } // namespace ecode