From f5ce1589e30b44cc893e805c23eaee6bf264e9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 18 Jul 2026 13:31:06 -0300 Subject: [PATCH] Some snippets improvements to support `insertTextFormat` (SpartanJ/ecode/discussions#929). Closes SpartanJ/ecode#933 --- .../src/eepp/ui/doc/languages/objective-c.cpp | 4 +-- .../eepp/ui/doc/languages/objective-cpp.cpp | 4 +-- .../autocomplete/autocompleteplugin.cpp | 36 ++++++++++--------- .../autocomplete/autocompleteplugin.hpp | 5 ++- .../ecode/plugins/lsp/lspclientserver.cpp | 9 +++-- src/tools/ecode/plugins/lsp/lspprotocol.hpp | 6 ++++ 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.cpp b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.cpp index fbe0dc638..5822016f9 100644 --- a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.cpp +++ b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.cpp @@ -12,9 +12,9 @@ SyntaxDefinition& addObjectiveC() { { { { "//.-\n" }, "comment" }, { { "/%*", "%*/" }, "comment" }, - { { "(#%s*include)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" }, + { { "(#%s*include)%s+([<%\"][%w%d%.%\\%/%_%-%+]+[>%\"])" }, { "keyword", "keyword", "literal" } }, - { { "(#%s*import)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" }, + { { "(#%s*import)%s+([<%\"][%w%d%.%\\%/%_%-%+]+[>%\"])" }, { "keyword", "keyword", "literal" } }, { { "\"", "[\"\n]", "\\" }, "string" }, { { "'", "'", "\\" }, "string" }, diff --git a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-cpp.cpp b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-cpp.cpp index ae33ae7b5..2506bbc6f 100644 --- a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-cpp.cpp +++ b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-cpp.cpp @@ -20,9 +20,9 @@ SyntaxDefinition& addObjectiveCPP() { { { "/%*", "%*/" }, "comment" }, { { "\"", "[\"\n]", "\\" }, "string" }, { { "'", "'", "\\" }, "string" }, - { { "(#%s*include)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" }, + { { "(#%s*include)%s+([<%\"][%w%d%.%\\%/%_%-%+]+[>%\"])" }, { "keyword", "keyword", "literal" } }, - { { "(#%s*import)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" }, + { { "(#%s*import)%s+([<%\"][%w%d%.%\\%/%_%-%+]+[>%\"])" }, { "keyword", "keyword", "literal" } }, { { "cpp_number_parser" }, "number", "", SyntaxPatternMatchType::Parser }, { { "[%+%-=/%*%^%%<>!~|&]" }, "operator" }, diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp index 59873f6be..f4f49e845 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.cpp @@ -21,7 +21,7 @@ using namespace std::literals; namespace ecode { static constexpr auto SNIPPET_PTRN1 = "%$%{%d+%}"sv; -static constexpr auto SNIPPET_PTRN2 = "%$%{%d+%:([%w,.%s%+%-]+)}"sv; +static constexpr auto SNIPPET_PTRN2 = "%$%{%d+%:([%w,.%s%+%-_]+)}"sv; static constexpr auto SNIPPET_PTRN3 = "%$%d+"sv; static json getURIJSON( TextDocument* doc, const PluginIDType& id ) { @@ -789,12 +789,13 @@ void AutoCompletePlugin::tryStartSnippetNav( const Suggestion& suggestion, UICod } bool AutoCompletePlugin::hasCompleteSteps( const Suggestion& suggestion ) { - if ( suggestion.kind != LSPCompletionItemKind::Snippet ) - return false; - if ( LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN1 ) || - LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN2 ) || - LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN3 ) ) { - return true; + if ( suggestion.kind == LSPCompletionItemKind::Snippet || + suggestion.insertTextFormat == LSPInsertTextFormat::Snippet ) { + if ( LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN1 ) || + LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN2 ) || + LuaPattern::hasMatches( suggestion.insertText, SNIPPET_PTRN3 ) ) { + return true; + } } return false; } @@ -809,15 +810,17 @@ AutoCompletePlugin::processCodeCompletion( const LSPCompletionList& completion ) LSPCompletionList& wcompletion = const_cast( completion ); for ( auto& item : wcompletion.items ) { if ( !item.textEdit.text.empty() ) { - suggestions.push_back( - { item.kind, std::move( item.label.empty() ? item.insertText : item.label ), - std::move( item.detail ), std::move( item.sortText ), item.textEdit.range, - std::move( item.textEdit.text ), std::move( item.documentation ) } ); + suggestions.push_back( { item.kind, + std::move( item.label.empty() ? item.insertText : item.label ), + std::move( item.detail ), std::move( item.sortText ), + item.textEdit.range, std::move( item.textEdit.text ), + std::move( item.documentation ), item.insertTextFormat } ); } else if ( !item.insertText.empty() ) { - suggestions.push_back( - { item.kind, std::move( item.label.empty() ? item.insertText : item.label ), - std::move( item.detail ), std::move( item.sortText ), item.textEdit.range, - std::string{ item.insertText }, std::move( item.documentation ) } ); + suggestions.push_back( { item.kind, + std::move( item.label.empty() ? item.insertText : item.label ), + std::move( item.detail ), std::move( item.sortText ), + item.textEdit.range, std::string{ item.insertText }, + std::move( item.documentation ), item.insertTextFormat } ); } else { suggestions.push_back( { item.kind, std::move( item.filterText ), @@ -825,7 +828,8 @@ AutoCompletePlugin::processCodeCompletion( const LSPCompletionList& completion ) std::move( item.sortText ), {}, "", - std::move( item.documentation ) } ); + std::move( item.documentation ), + item.insertTextFormat } ); } } if ( suggestions.empty() || !mSuggestionsEditor ) diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index b6863a9e4..8b42c68e8 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -27,6 +27,7 @@ class AutoCompletePlugin : public Plugin { std::string sortText; TextRange range; std::string insertText; + LSPInsertTextFormat insertTextFormat{ LSPInsertTextFormat::PlainText }; double score{ 0 }; LSPMarkupContent documentation; @@ -38,13 +39,15 @@ class AutoCompletePlugin : public Plugin { Suggestion( LSPCompletionItemKind kind, std::string&& text, std::string&& detail, std::string&& sortText, const TextRange& range, std::string&& insertText, - LSPMarkupContent&& doc ) : + LSPMarkupContent&& doc, + LSPInsertTextFormat insertTextFormat ) : kind( kind ), text( std::move( text ) ), detail( std::move( detail ) ), sortText( sortText.empty() ? std::string{ this->text } : std::move( sortText ) ), range( range ), insertText( std::move( insertText ) ), + insertTextFormat( insertTextFormat ), documentation( doc ) {}; bool operator<( const Suggestion& other ) const { return getCmpStr() < other.getCmpStr(); } diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index 8f1fb4c4a..c4b3a8b40 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -86,6 +86,7 @@ static const char* MEMBER_SUCCESS = "success"; static const char* MEMBER_LIMIT = "limit"; static const char* MEMBER_OPTIONS = "options"; static const char* MEMBER_PREVIOUS_RESULT_IDS = "previousResultIds"; +static const char* MEMBER_INSERT_TEXT_FORMAT = "insertTextFormat"; static json newRequest( const std::string& method, const json& params = json{} ) { json j; @@ -885,9 +886,11 @@ static LSPCompletionList parseDocumentCompletion( const json& result ) { item.contains( "additionalTextEdits" ) ? parseTextEditArray( item.at( "additionalTextEdits" ) ) : std::vector{}; - - ret.items.push_back( { label, kind, detail, doc, sortText, insertText, filterText, - textEdit, additionalTextEdits } ); + auto itf = item.value( MEMBER_INSERT_TEXT_FORMAT, 1 ); + LSPInsertTextFormat insertTextFormat = + itf == 2 ? LSPInsertTextFormat::Snippet : LSPInsertTextFormat::PlainText; + ret.items.push_back( { label, kind, detail, doc, sortText, insertText, insertTextFormat, + filterText, textEdit, additionalTextEdits } ); } #ifndef EE_DEBUG } catch ( const json::exception& err ) { diff --git a/src/tools/ecode/plugins/lsp/lspprotocol.hpp b/src/tools/ecode/plugins/lsp/lspprotocol.hpp index b48849edf..5a352274f 100644 --- a/src/tools/ecode/plugins/lsp/lspprotocol.hpp +++ b/src/tools/ecode/plugins/lsp/lspprotocol.hpp @@ -531,6 +531,11 @@ class LSPCompletionItemHelper { } }; +enum class LSPInsertTextFormat { + PlainText = 1, + Snippet = 2, +}; + struct LSPCompletionItem { std::string label; LSPCompletionItemKind kind; @@ -538,6 +543,7 @@ struct LSPCompletionItem { LSPMarkupContent documentation; std::string sortText; std::string insertText; + LSPInsertTextFormat insertTextFormat{ LSPInsertTextFormat::PlainText }; std::string filterText; LSPTextEdit textEdit; std::vector additionalTextEdits;