Fix for multi-line signature help labels, now labels will be flatten into a single line (SpartanJ/ecode#388).

Fix next signature help position.
Fix signature help and suggestions styles for light color schemes, and some minor improvements for other schemes.
Allow to set extra trigger characters for signature help in LSP configurations (fix zig zls not updating signature position after a "," input).
Plus some other minor fixes.
This commit is contained in:
Martín Lucas Golini
2025-02-02 19:07:41 -03:00
parent 863c0ec1c0
commit d3bc6f2935
18 changed files with 292 additions and 72 deletions
+17 -2
View File
@@ -186,6 +186,8 @@ selection = #b7dce8
line_number = #d0d0d0
line_number2 = #808080
line_highlight = #f2f2f2
suggestion = #404040,#e8e8e8
suggestion_selected = #404040,#f7f7f7
normal = #181818
symbol = #181818
@@ -391,6 +393,9 @@ minimap_highlight = #FF00FFFF
error = #990000FF;
warning = #999900FF;
notice = #8abdff
suggestion = #1d1f27,#e1e1e6
suggestion_selected = #222533,#ffffff
suggestion_scrollbar = #3daee9
[solarized light]
background = #fdf6e3
@@ -401,6 +406,9 @@ selection = #eee8d5
line_number = #93a1a1
line_number2 = #002b36
line_highlight = #eee8d5
suggestion = #657b83,#f7f1de
suggestion_selected = #657b83,#eee8d5
suggestion_scrollbar = #002b36
normal = #657b83
symbol = #657b83
@@ -583,6 +591,9 @@ minimap_highlight = #FF00FFFF
error = #990000FF;
warning = #999900FF;
notice = #8abdff
suggestion = #1d1f27,#e1e1e6
suggestion_selected = #222533,#f7f9f9
suggestion_scrollbar = #ff5971
[solarobj]
background = #fdf6e3
@@ -613,6 +624,10 @@ error = #990000FF;
warning = #999900FF;
notice = #8abdff
suggestion = #3e3c37,#ebe4d2
suggestion_selected = #3e3c37,#fff8e4
suggestion_scrollbar = #6c71c4
[catppuccin macchiato]
background = #24273a
text = #cad3f5
@@ -669,8 +684,8 @@ line_break_column = #54575b99
matching_bracket = #dbdbdb
matching_selection = #ffff00
matching_search = #0000f0
suggestion = #e1e1e6,#1d1f27
suggestion_selected = #ffffff,#222533
suggestion = #1d1f27,#e1e1e6
suggestion_selected = #222533,#ffffff
suggestion_scrollbar = #3daee9
error = #ff3030
warning = yellow
+1 -13
View File
@@ -20,17 +20,6 @@
"env": "${env}"
}
},
{
"name": "Launch binary in Terminal",
"request": "launch",
"arguments": {
"program": "${file}",
"args": "${args}",
"cwd": "${cwd}",
"env": "${env}",
"runInTerminal": true
}
},
{
"name": "Attach to Name",
"request": "attach",
@@ -258,8 +247,7 @@
"request": "launch",
"arguments": {
"program": "${file}",
"args": "${args}",
"stopOnEntry": true
"args": "${args}"
}
}
]
+2 -1
View File
@@ -103,7 +103,8 @@
"name": "zls",
"url": "https://github.com/zigtools/zls",
"command": "zls",
"file_patterns": ["%.zig$"]
"file_patterns": ["%.zig$"],
"extra_trigger_chars": [ "," ]
},
{
"language": "odin",
+5 -3
View File
@@ -302,7 +302,9 @@ ListView::cell {
}
ListBox:hover,
ListView:hover {
ListView:hover,
ListBox:focus,
ListView:focus {
border-color: var(--primary);
}
@@ -383,8 +385,8 @@ SpinBox::input {
}
SpinBox::input,
SpinBox::input::hover,
SpinBox::input::focus {
SpinBox::input:hover,
SpinBox::input:focus {
border-width: 0dp;
border-color: transparent;
}
+3
View File
@@ -437,6 +437,9 @@ class EE_API String {
/** @return The number of codepoints of the utf8 string. */
static size_t utf8Length( const std::string_view& utf8String );
/** Converts a character position from an utf8 string to a code point position */
static size_t utf8ToCodepointPosition( const std::string_view& utf8Text, size_t utf8Pos );
/** @return The next character in a utf8 null terminated string */
static Uint32 utf8Next( char*& utf8String );
+10
View File
@@ -114,6 +114,12 @@ class EE_API TextRange {
bool isNormalized() const { return mStart <= mEnd; }
static TextRange convertToLineColumn( const String::View& text, Int64 startOffset,
Int64 endOffset );
static TextRange convertToLineColumn( const std::string_view& text, Int64 startOffset,
Int64 endOffset );
private:
TextPosition mStart;
TextPosition mEnd;
@@ -121,6 +127,10 @@ class EE_API TextRange {
TextPosition normalizedStart() const { return mStart < mEnd ? mStart : mEnd; }
TextPosition normalizedEnd() const { return mStart < mEnd ? mEnd : mStart; }
template <typename StringType>
static TextRange convertToLineColumn( const StringType& text, Int64 startOffset,
Int64 endOffset );
};
class EE_API TextRanges : public std::vector<TextRange> {
+50 -12
View File
@@ -1261,18 +1261,18 @@ bool String::isAscii() const {
size_t len = mString.size();
size_t i = 0;
// #ifdef EE_STD_SIMD
// using simd_type = simd::native_simd<char32_t>;
// constexpr size_t simd_size = simd_type::size();
// const simd_type ascii_limit = 127;
// for ( ; i + simd_size - 1 < len; i += simd_size ) {
// simd_type chunk;
// chunk.copy_from( &data[i], simd::element_aligned );
// auto mask = chunk > ascii_limit;
// if ( simd::any_of( mask ) )
// return false;
// }
// #endif
// #ifdef EE_STD_SIMD
// using simd_type = simd::native_simd<char32_t>;
// constexpr size_t simd_size = simd_type::size();
// const simd_type ascii_limit = 127;
// for ( ; i + simd_size - 1 < len; i += simd_size ) {
// simd_type chunk;
// chunk.copy_from( &data[i], simd::element_aligned );
// auto mask = chunk > ascii_limit;
// if ( simd::any_of( mask ) )
// return false;
// }
// #endif
for ( ; i < len; ++i )
if ( data[i] > 127 )
@@ -1590,6 +1590,44 @@ Uint32 String::utf8Next( char*& utf8String ) {
return utf8::unchecked::next( utf8String );
}
size_t String::utf8ToCodepointPosition( const std::string_view& utf8Text, size_t utf8Pos ) {
size_t codepointPos = 0;
size_t bytePos = 0;
while ( bytePos < utf8Pos && bytePos < utf8Text.length() ) {
unsigned char c = utf8Text[bytePos];
// Skip continuation bytes (10xxxxxx)
if ( ( c & 0xC0 ) == 0x80 ) {
bytePos++;
continue;
}
// Count this as one codepoint
codepointPos++;
// Move to the next character
if ( c < 0x80 )
bytePos += 1; // ASCII
else if ( c < 0xE0 )
bytePos += 2; // 2-byte sequence
else if ( c < 0xF0 )
bytePos += 3; // 3-byte sequence
else
bytePos += 4; // 4-byte sequence
// Handle potential truncated sequences
if ( bytePos > utf8Text.length() )
break;
}
// If we're in the middle of a character, return the previous complete character position
if ( utf8Pos > bytePos )
codepointPos--;
return codepointPos;
}
String::operator std::string() const {
return toUtf8();
}
+13 -12
View File
@@ -197,6 +197,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
PatternMatcher::Range matches[12];
int start, end;
const std::string_view textv{ text };
size_t numMatches;
size_t i = startIndex;
SyntaxState retState = state;
@@ -228,7 +229,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
( range.first == -1 || rangeSubsyntax.first < range.first ) ) {
if ( !skipSubSyntaxSeparator ) {
pushToken( tokens, curState.subsyntaxInfo->types[0],
text.substr( i, rangeSubsyntax.second - i ) );
textv.substr( i, rangeSubsyntax.second - i ) );
}
popSubsyntax( curState, retState, syntax );
i = rangeSubsyntax.second;
@@ -239,16 +240,16 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
if ( !skip ) {
if ( range.first != -1 ) {
if ( range.second > range.first && pattern.types.size() >= 3 ) {
pushToken( tokens, pattern.types[0], text.substr( i, range.first - i ) );
pushToken( tokens, pattern.types[0], textv.substr( i, range.first - i ) );
pushToken( tokens, pattern.types[pattern.types.size() - 1],
text.substr( range.first, range.second - range.first ) );
textv.substr( range.first, range.second - range.first ) );
} else {
pushToken( tokens, pattern.types[0], text.substr( i, range.second - i ) );
pushToken( tokens, pattern.types[0], textv.substr( i, range.second - i ) );
}
setSubsyntaxPatternIdx( curState, retState, SYNTAX_TOKENIZER_STATE_NONE );
i = range.second;
} else {
pushToken( tokens, pattern.types[0], text.substr( i ) );
pushToken( tokens, pattern.types[0], textv.substr( i ) );
break;
}
}
@@ -264,7 +265,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
if ( rangeSubsyntax.first != -1 ) {
if ( !skipSubSyntaxSeparator ) {
pushToken( tokens, curState.subsyntaxInfo->types[0],
text.substr( i, rangeSubsyntax.second - i ) );
textv.substr( i, rangeSubsyntax.second - i ) );
}
popSubsyntax( curState, retState, syntax );
i = rangeSubsyntax.second;
@@ -292,7 +293,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
int patternMatchStart = matches[0].start;
int patternMatchEnd = matches[0].end;
std::string patternFullText(
text.substr( patternMatchStart, patternMatchEnd - patternMatchStart ) );
textv.substr( patternMatchStart, patternMatchEnd - patternMatchStart ) );
auto patternType = pattern.types[0];
int lastStart = patternMatchStart;
int lastEnd = patternMatchEnd;
@@ -315,13 +316,13 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
if ( curMatch == 1 && start > lastStart ) {
pushToken(
tokens, patternType,
text.substr( patternMatchStart, start - patternMatchStart ) );
textv.substr( patternMatchStart, start - patternMatchStart ) );
} else if ( start > lastEnd ) {
pushToken( tokens, patternType,
text.substr( lastEnd, start - lastEnd ) );
textv.substr( lastEnd, start - lastEnd ) );
}
patternText = text.substr( start, end - start );
patternText = textv.substr( start, end - start );
SyntaxStyleType type = curState.currentSyntax->getSymbol( patternText );
if ( !skipSubSyntaxSeparator || !pattern.hasSyntax() ) {
pushToken( tokens,
@@ -344,7 +345,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
if ( curMatch == numMatches - 1 && end < patternMatchEnd ) {
pushToken( tokens, patternType,
text.substr( end, patternMatchEnd - end ) );
textv.substr( end, patternMatchEnd - end ) );
i = patternMatchEnd;
}
@@ -367,7 +368,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
String::utf8Next( strEnd );
end = start + ( strEnd - strStart );
}
patternText = text.substr( start, end - start );
patternText = textv.substr( start, end - start );
SyntaxStyleType type = curState.currentSyntax->getSymbol( patternText );
if ( !skipSubSyntaxSeparator || !pattern.hasSyntax() ) {
pushToken( tokens,
+62
View File
@@ -101,6 +101,68 @@ TextRange TextRange::fromString( const std::string& range ) {
return {};
}
template <typename StringType>
TextRange TextRange::convertToLineColumn( const StringType& text, Int64 startOffset,
Int64 endOffset ) {
if ( startOffset < 0 || endOffset < 0 || startOffset > static_cast<Int64>( text.length() ) ||
endOffset > static_cast<Int64>( text.length() ) || startOffset > endOffset ) {
return {};
}
TextRange result;
Int64 currentLine = 0;
Int64 currentCol = 0;
Int64 currentPos = 0;
bool foundStart = false;
bool foundEnd = false;
size_t len = text.length();
for ( size_t i = 0; i < len; i++ ) {
if ( currentPos == startOffset ) {
result.setStart( { currentLine, currentCol } );
foundStart = true;
}
if ( currentPos == endOffset ) {
result.setEnd( { currentLine, currentCol } );
foundEnd = true;
}
if ( foundStart && foundEnd )
break;
if ( i == text.length() )
break;
if ( text[i] == '\n' ) {
currentLine++;
currentCol = 0;
} else {
currentCol++;
}
currentPos++;
}
if ( currentPos == startOffset )
result.setStart( { currentLine, currentCol } );
if ( currentPos == endOffset )
result.setEnd( { currentLine, currentCol } );
return result;
}
TextRange TextRange::convertToLineColumn( const String::View& text, Int64 startOffset,
Int64 endOffset ) {
return convertToLineColumn<String>( text, startOffset, endOffset );
}
TextRange TextRange::convertToLineColumn( const std::string_view& text, Int64 startOffset,
Int64 endOffset ) {
return convertToLineColumn<std::string_view>( text, startOffset, endOffset );
}
TextRanges::TextRanges() {}
TextRanges::TextRanges( const std::vector<TextRange>& ranges ) : std::vector<TextRange>( ranges ) {}
@@ -357,10 +357,9 @@ bool AutoCompletePlugin::onKeyDown( UICodeEditor* editor, const KeyEvent& event
}
} else if ( mShortcuts["autocomplete-next-signature-help"] == eventShortcut ) {
if ( mSignatureHelp.signatures.size() > 1 ) {
mSignatureHelpSelected =
mSignatureHelpSelected == (int)mSignatureHelp.signatures.size() - 1
? mSignatureHelp.signatures.size() - 1
: 0;
mSignatureHelpSelected = mSignatureHelpSelected <= 0
? mSignatureHelp.signatures.size()
: mSignatureHelpSelected;
--mSignatureHelpSelected;
mSignatureHelpSelected = mSignatureHelpSelected % mSignatureHelp.signatures.size();
editor->invalidateDraw();
@@ -818,9 +817,68 @@ AutoCompletePlugin::processSignatureHelp( const LSPSignatureHelp& signatureHelp
}
if ( !editor )
return {};
editor->runOnMainThread( [this, editor, signatureHelp] {
// Convert the LSP Signature Help into our own object:
// We will convert the UTF-8 label to UTF-32, then we will remove any new lines and extra spaces
// This guarantees that we always display a single line signature help
SignatureHelp signatures;
signatures.activeSignature = signatureHelp.activeSignature;
signatures.activeParameter = signatureHelp.activeParameter;
signatures.signatures.reserve( signatureHelp.signatures.size() );
TextDocument doc;
for ( const auto& sig : signatureHelp.signatures ) {
String initialLabel( sig.label );
SignatureInformation nsig;
nsig.documentation = sig.documentation;
doc.reset();
doc.textInput( initialLabel );
std::vector<String> parameters;
parameters.reserve( sig.parameters.size() );
for ( size_t i = 0; i < sig.parameters.size(); i++ ) {
auto start = String::utf8ToCodepointPosition( sig.label, sig.parameters[i].start );
auto end = String::utf8ToCodepointPosition( sig.label, sig.parameters[i].end );
auto sel = TextRange::convertToLineColumn( initialLabel.view(), start, end );
if ( i == 0 )
doc.setSelection( i, sel );
else
doc.addSelection( sel );
parameters.emplace_back( doc.getSelectedText( i ) );
}
auto selections( doc.getSelections() );
nsig.parameters.reserve( selections.size() );
if ( 0 != doc.replaceAll( "\n", "" ) ) {
while ( 0 != doc.replaceAll( " ", " " ) )
;
nsig.label = doc.line( 0 ).getTextWithoutNewLine();
for ( const auto& param : parameters ) {
auto res = doc.find( param );
if ( res.isValid() )
nsig.parameters.emplace_back( res.result );
}
} else {
nsig.label = std::move( initialLabel );
if ( !sig.parameters.empty() ) {
for ( auto& sel : selections )
nsig.parameters.emplace_back( sel );
}
}
signatures.signatures.emplace_back( nsig );
}
editor->runOnMainThread( [this, editor, signatures = std::move( signatures )] {
mSignatureHelpVisible = true;
mSignatureHelp = signatureHelp;
mSignatureHelp = signatures;
if ( mSignatureHelp.signatures.empty() )
resetSignatureHelp();
editor->invalidateDraw();
@@ -942,7 +1000,7 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f
primitives.setColor( Color( selectedStyle.background ).blendAlpha( editor->getAlpha() ) );
String str;
if ( mSignatureHelp.signatures.size() > 1 ) {
str = String::format( "%s (%d of %zu)", curSig.label.c_str(),
str = String::format( "%s (%d of %zu)", curSig.label.toUtf8(),
mSignatureHelpSelected == -1 ? 1 : mSignatureHelpSelected + 1,
mSignatureHelp.signatures.size() );
} else {
@@ -962,38 +1020,42 @@ void AutoCompletePlugin::drawSignatureHelp( UICodeEditor* editor, const Vector2f
}
bool hasParams = !curSig.parameters.empty();
LSPParameterInformation curParam =
TextRange curParam =
hasParams ? curSig.parameters[mSignatureHelp.activeParameter % curSig.parameters.size()]
: LSPParameterInformation{ -1, -1 };
: TextRange{};
Rectf curParamRect;
if ( hasParams ) {
curParamRect = Rectf(
{ { boxRect.getPosition().x + mBoxPadding.Left +
curParam.start * editor->getGlyphWidth(),
curParam.start().column() * editor->getGlyphWidth(),
boxRect.getPosition().y },
{ ( curParam.end - curParam.start ) * editor->getGlyphWidth(), mRowHeight } } );
{ ( curParam.end().column() - curParam.start().column() ) * editor->getGlyphWidth(),
mRowHeight } } );
if ( !editor->getScreenRect().contains(
Rectf{ { curParamRect.getPosition().x +
( curParam.end - curParam.start ) * editor->getGlyphWidth(),
( curParam.end().column() - curParam.start().column() ) *
editor->getGlyphWidth(),
curParamRect.getPosition().y },
curParamRect.getSize() } ) ) {
auto offset = editor->getTextPositionOffset( mSignatureHelpPosition );
pos = { static_cast<Float>( startScroll.x - curParam.start * editor->getGlyphWidth() +
pos = { static_cast<Float>( startScroll.x -
curParam.start().column() * editor->getGlyphWidth() +
offset.x ),
static_cast<Float>( startScroll.y + offset.y + vdiff ) };
boxRect.setPosition( pos );
curParamRect.setPosition( { boxRect.getPosition().x + mBoxPadding.Left +
curParam.start * editor->getGlyphWidth(),
curParam.start().column() * editor->getGlyphWidth(),
boxRect.getPosition().y } );
}
}
primitives.drawRoundedRectangle( boxRect, 0.f, Vector2f::One, 6 );
if ( hasParams && curParam.end - curParam.start > 0 && curParam.end < (int)str.size() ) {
if ( hasParams && curParam.end() != curParam.start() &&
curParam.end().column() < (int)str.size() ) {
primitives.setColor( matchingSelection.color );
primitives.drawRoundedRectangle( curParamRect, 0.f, Vector2f::One, 6 );
}
@@ -1112,10 +1174,13 @@ void AutoCompletePlugin::postDraw( UICodeEditor* editor, const Vector2f& startSc
LSPCompletionItemHelper::toIconString( suggestion.kind ), PixelDensity::dpToPxI( 12 ) );
if ( icon ) {
Color iconColor( icon->getColor() );
icon->setColor( mSuggestionIndex == (int)i ? selectedStyle.color : normalStyle.color );
Vector2f padding(
eefloor( ( iconSpace.getWidth() - icon->getSize().getWidth() ) * 0.5f ),
eefloor( ( iconSpace.getHeight() - icon->getSize().getHeight() ) * 0.5f ) );
icon->draw( { cursorPos.x + padding.x, cursorPos.y + mRowHeight * count + padding.y } );
icon->setColor( iconColor );
}
if ( mSuggestionIndex == (int)i && !suggestion.documentation.value.empty() ) {
@@ -63,7 +63,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, 6 },
{ 0, 2, 7 },
AutoCompletePlugin::NewSync };
}
@@ -144,7 +144,20 @@ class AutoCompletePlugin : public Plugin {
Int32 mSuggestionsStartIndex{ 0 };
std::unordered_map<std::string, LSPServerCapabilities> mCapabilities;
Mutex mCapabilitiesMutex;
LSPSignatureHelp mSignatureHelp;
struct SignatureInformation {
String label;
LSPMarkupContent documentation;
std::vector<TextRange> parameters;
};
struct SignatureHelp {
std::vector<SignatureInformation> signatures;
int activeSignature{ 0 };
int activeParameter{ 0 };
};
SignatureHelp mSignatureHelp;
TextPosition mSignatureHelpPosition;
Int32 mSignatureHelpSelected{ -1 };
Mutex mHandlesMutex;
@@ -192,10 +192,6 @@ void DebuggerClientListener::sendBreakpoints() {
Lock l( mPlugin->mBreakpointsMutex );
for ( const auto& fileBps : mPlugin->mBreakpoints ) {
std::string path( fileBps.first );
if ( isRemote() ) {
FileSystem::filePathRemoveBasePath( mPlugin->mProjectPath, path );
path = "/" + path;
}
mClient->setBreakpoints( path, fromSet( fileBps.second ) );
}
}
@@ -330,6 +330,7 @@ static std::initializer_list<std::string> DebuggerCommandList = {
"debugger-breakpoint-enable-toggle",
"debugger-start",
"debugger-stop",
"debugger-start-stop",
"debugger-step-over",
"debugger-step-into",
"debugger-step-out",
@@ -448,7 +449,7 @@ void DebuggerPlugin::loadDAPConfig( const std::string& path, bool updateConfigFi
}
if ( mKeyBindings.empty() ) {
mKeyBindings["debugger-start"] = "mod+f5";
mKeyBindings["debugger-start-stop"] = "mod+f5";
mKeyBindings["debugger-continue-interrupt"] = "f5";
mKeyBindings["debugger-breakpoint-toggle"] = "f9";
mKeyBindings["debugger-breakpoint-enable-toggle"] = "mod+f9";
@@ -1269,6 +1270,13 @@ void DebuggerPlugin::onRegisterDocument( TextDocument* doc ) {
doc->setCommand( "debugger-stop", [this] { exitDebugger( true ); } );
doc->setCommand( "debugger-start-stop", [this] {
if ( mDebugger )
exitDebugger( true );
else
runCurrentConfig();
} );
doc->setCommand( "debugger-breakpoint-toggle", [doc, this] {
if ( setBreakpoint( doc, doc->getSelection().start().line() + 1 ) )
getUISceneNode()->getRoot()->invalidateDraw();
@@ -24,8 +24,11 @@ std::string ThreadsModel::columnName( const size_t& colIdx ) const {
Variant ThreadsModel::data( const ModelIndex& modelIndex, ModelRole role ) const {
if ( role == ModelRole::Display && modelIndex.column() == Columns::ID ) {
return Variant( String::format( "#%d (%s)", mThreads[modelIndex.row()].id,
mThreads[modelIndex.row()].name.c_str() ) );
if ( mThreads[modelIndex.row()].name.empty() )
return Variant( String::format( "#%d", mThreads[modelIndex.row()].id ) );
else
return Variant( String::format( "#%d (%s)", mThreads[modelIndex.row()].id,
mThreads[modelIndex.row()].name.c_str() ) );
} else if ( role == ModelRole::Icon && modelIndex.column() == Columns::ID &&
mThreads[modelIndex.row()].id == mCurrentThreadId ) {
static UIIcon* circleFilled = mSceneNode->findIcon( "circle-filled" );
@@ -1,5 +1,5 @@
#include "lspclientplugin.hpp"
#include "../../version.hpp"
#include "lspclientplugin.hpp"
#include <eepp/graphics/primitives.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/lock.hpp>
@@ -1284,6 +1284,7 @@ void LSPClientPlugin::loadLSPConfig( std::vector<LSPDefinition>& lsps, const std
lsp.host = tlsp.host;
lsp.port = tlsp.port;
lsp.initializationOptions = tlsp.initializationOptions;
lsp.extraTriggerChars = tlsp.extraTriggerChars;
lsp.usesLSP = use;
if ( obj.contains( "share_process" ) && obj["share_process"].is_boolean() ) {
lsp.shareProcessWithOtherDefinition = obj["share_process"].get<bool>();
@@ -1320,13 +1321,22 @@ void LSPClientPlugin::loadLSPConfig( std::vector<LSPDefinition>& lsps, const std
auto& fp = obj["file_patterns"];
for ( auto& pattern : fp )
lsp.filePatterns.push_back( pattern.get<std::string>() );
if ( pattern.is_string() )
lsp.filePatterns.push_back( pattern.get<std::string>() );
if ( obj.contains( "rootIndicationFileNames" ) ) {
lsp.rootIndicationFileNames.clear();
auto& fnms = obj["rootIndicationFileNames"];
for ( auto& fn : fnms )
lsp.rootIndicationFileNames.push_back( fn );
if ( fn.is_string() )
lsp.rootIndicationFileNames.push_back( fn );
}
if ( obj.contains( "extra_trigger_chars" ) && obj["extra_trigger_chars"].is_array() ) {
for ( auto& jch : obj["extra_trigger_chars"] ) {
if ( jch.is_string() )
lsp.extraTriggerChars.push_back( jch );
}
}
sanitizeCommand( lsp.command, mManager->getWorkspaceFolder() );
@@ -1,5 +1,5 @@
#include "lspclientserver.hpp"
#include "lspclientplugin.hpp"
#include "lspclientserver.hpp"
#include "lspclientservermanager.hpp"
#include <algorithm>
#include <eepp/system/filesystem.hpp>
@@ -1201,6 +1201,10 @@ void LSPClientServer::initialize() {
try {
#endif
fromJson( mCapabilities, resp["capabilities"] );
for ( const auto& ch : mLSP.extraTriggerChars )
if ( !ch.empty() )
mCapabilities.signatureHelpProvider.triggerCharacters.push_back( ch[0] );
#ifndef EE_DEBUG
} catch ( const json::exception& e ) {
Log::warning(
@@ -30,6 +30,7 @@ struct LSPDefinition {
std::string usesLSP;
bool shareProcessWithOtherDefinition{ false };
bool disabled{ false };
std::vector<std::string> extraTriggerChars;
bool commandAvailable() const {
auto cmdp( String::split( command, ' ' ) );
+1 -1
View File
@@ -637,7 +637,7 @@ struct LSPPreviousResultId {
using LSPPreviousResultIds = std::vector<LSPPreviousResultId>;
static constexpr auto LSPDocumentDiagnosticReportKindFull = "full";
static constexpr auto LSPDocumentDiagnosticReportKindUnchanged= "unchanged";
static constexpr auto LSPDocumentDiagnosticReportKindUnchanged = "unchanged";
struct LSPFullDocumentDiagnosticReport {
URI uri;