Autocomplete improvements.

This commit is contained in:
Martín Lucas Golini
2024-04-16 23:41:46 -03:00
parent 6c6ee22b00
commit fcc9eb2204
4 changed files with 68 additions and 37 deletions

View File

@@ -110,11 +110,11 @@ class EE_API Text {
Color FontShadowColor = Color( 0, 0, 0, 255 ),
Uint32 characterSize = PixelDensity::dpToPx( 12 ) );
void setString( const String::View& string );
bool setString( const String::View& string );
void setString( const String& string );
bool setString( const String& string );
void setString( String&& string );
bool setString( String&& string );
void setFont( Font* font );

View File

@@ -468,25 +468,31 @@ void Text::onNewString() {
}
}
void Text::setString( const String::View& string ) {
bool Text::setString( const String::View& string ) {
if ( mString.view() != string ) {
mString = string;
onNewString();
return true;
}
return false;
}
void Text::setString( const String& string ) {
bool Text::setString( const String& string ) {
if ( mString != string ) {
mString = string;
onNewString();
return true;
}
return false;
}
void Text::setString( String&& string ) {
bool Text::setString( String&& string ) {
if ( mString != string ) {
mString = std::move( string );
onNewString();
return true;
}
return false;
}
void Text::setFont( Font* font ) {

View File

@@ -4,6 +4,7 @@
#include <eepp/graphics/text.hpp>
#include <eepp/system/lock.hpp>
#include <eepp/system/luapattern.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <eepp/ui/uiscenenode.hpp>
#include <nlohmann/json.hpp>
using namespace EE::Graphics;
@@ -481,22 +482,30 @@ void AutoCompletePlugin::pickSuggestion( UICodeEditor* editor ) {
PluginRequestHandle
AutoCompletePlugin::processCodeCompletion( const LSPCompletionList& completion ) {
SymbolsList suggestions;
for ( const auto& item : completion.items ) {
// FIX: Find a way of passing some messages as non-const and allow to move them.
// Creating a copy of each element is unnecessary and expensive, this time we are going to
// hack it and remove the constness of the suggestions to be able to move all its internal
// values
LSPCompletionList& wcompletion = const_cast<LSPCompletionList&>( completion );
for ( auto& item : wcompletion.items ) {
if ( !item.textEdit.text.empty() ) {
suggestions.push_back( { item.kind, item.insertText, item.detail, item.sortText,
item.textEdit.range, item.textEdit.text,
item.documentation } );
suggestions.push_back( { item.kind, std::move( item.insertText ),
std::move( item.detail ), std::move( item.sortText ),
item.textEdit.range, std::move( item.textEdit.text ),
std::move( 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 } );
suggestions.push_back( { item.kind, std::move( item.insertText ),
std::move( item.detail ), std::move( item.sortText ),
item.textEdit.range, std::string{ item.insertText },
std::move( item.documentation ) } );
} else {
suggestions.push_back( { item.kind,
item.filterText,
item.detail,
item.sortText,
std::move( item.filterText ),
std::move( item.detail ),
std::move( item.sortText ),
{},
"",
item.documentation } );
std::move( item.documentation ) } );
}
}
if ( suggestions.empty() || !mSuggestionsEditor )
@@ -786,6 +795,8 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc
primitives.drawRoundedRectangle( boxRect, 0.f, Vector2f::One, 6 );
for ( size_t i = mSuggestionsStartIndex; i < maxIndex; i++ ) {
const auto& suggestion = suggestions[i];
if ( mSuggestionIndex == (int)i ) {
primitives.setColor(
Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) );
@@ -798,19 +809,18 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc
text.setFillColor( mSuggestionIndex == (int)i ? selectedStyle.color : normalStyle.color );
text.setStyle( mSuggestionIndex == (int)i ? selectedStyle.style : normalStyle.style );
auto nlPos = suggestions[i].text.find_first_of( '\n' );
auto nlPos = suggestion.text.find_first_of( '\n' );
if ( nlPos == std::string::npos ) {
text.setString( suggestions[i].text );
text.setString( suggestion.text );
} else {
text.setString( suggestions[i].text.substr( 0, nlPos ) );
text.setString( suggestion.text.substr( 0, nlPos ) );
}
text.draw( cursorPos.x + iconSpace.getWidth() + mBoxPadding.Left,
cursorPos.y + mRowHeight * count + mBoxPadding.Top );
Drawable* icon = editor->getUISceneNode()->findIconDrawable(
LSPCompletionItemHelper::toIconString( suggestions[i].kind ),
PixelDensity::dpToPxI( 12 ) );
LSPCompletionItemHelper::toIconString( suggestion.kind ), PixelDensity::dpToPxI( 12 ) );
if ( icon ) {
Vector2f padding(
@@ -819,19 +829,34 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc
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 );
if ( mSuggestionIndex == (int)i && !suggestion.documentation.value.empty() ) {
mSuggestionDoc.setFont( editor->getFont() );
mSuggestionDoc.setFontSize( editor->getFontSize() );
mSuggestionDoc.setFillColor( normalStyle.color );
mSuggestionDoc.setStyle( normalStyle.style );
bool changed = mSuggestionDoc.setString( suggestion.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 };
Sizef boxSize = { mSuggestionDoc.getTextWidth() + mBoxPadding.Left + mBoxPadding.Right,
mSuggestionDoc.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 );
if ( changed ) {
bool forceHTML = String::startsWith( suggestion.detail, "Emmet" );
if ( suggestion.documentation.kind == LSPMarkupKind::MarkDown || forceHTML ) {
const auto& syntaxDef = forceHTML ?
SyntaxDefinitionManager::instance()->getByLSPName( "html" ) :
SyntaxDefinitionManager::instance()->getByLSPName( "markdown" );
SyntaxTokenizer::tokenizeText( syntaxDef, editor->getColorScheme(),
mSuggestionDoc, 0, 0xFFFFFFFF, true, "\n\t " );
}
}
mSuggestionDoc.draw( boxPos.x + mBoxPadding.Left, boxPos.y + mBoxPadding.Top );
}
count++;
}

View File

@@ -37,16 +37,15 @@ class AutoCompletePlugin : public Plugin {
Suggestion( const std::string& text ) : text( text ), sortText( text ) {}
Suggestion( const LSPCompletionItemKind& kind, const std::string& text,
const std::string& detail, const std::string& sortText,
const TextRange& range = {}, const std::string insertText = "",
LSPMarkupContent doc = {} ) :
Suggestion( LSPCompletionItemKind kind, std::string&& text, std::string&& detail,
std::string&& sortText, const TextRange& range, std::string&& insertText,
LSPMarkupContent&& doc ) :
kind( kind ),
text( text ),
detail( detail ),
sortText( sortText.empty() ? text : sortText ),
text( std::move( text ) ),
detail( std::move( detail ) ),
sortText( sortText.empty() ? std::string{ text } : std::move( sortText ) ),
range( range ),
insertText( insertText ),
insertText( std::move( insertText ) ),
documentation( doc ){};
bool operator<( const Suggestion& other ) const { return getCmpStr() < other.getCmpStr(); }
@@ -149,6 +148,7 @@ class AutoCompletePlugin : public Plugin {
std::unordered_map<TextDocument*, std::vector<PluginIDType>> mHandles;
std::unordered_map<TextDocument*, std::atomic<bool>> mDocsUpdating;
Mutex mDocsUpdatingMutex;
Text mSuggestionDoc;
Float mRowHeight{ 0 };
Rectf mBoxRect;