diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 0e1930a85..1927d5981 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -436,9 +436,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual Int64 getColFromXOffset( Int64 line, const Float& x ) const; - virtual Float getColXOffset( TextPosition position ); + virtual Float getXOffsetCol( const TextPosition& position ) const; - virtual Float getXOffsetCol( const TextPosition& position ); + Float getXOffsetColSanitized( TextPosition position ) const; virtual Float getLineWidth( const Int64& lineIndex ); @@ -541,6 +541,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { TextPosition resolveScreenPosition( const Vector2f& position, bool clamp = true ) const; + Rectf getScreenPosition( const TextPosition& position ) const; + protected: struct LastXOffset { TextPosition position; diff --git a/premake4.lua b/premake4.lua index 197843c27..6ed419e3a 100644 --- a/premake4.lua +++ b/premake4.lua @@ -443,6 +443,8 @@ function build_link_configuration( package_name, use_ee_icon ) if not is_vs() then buildoptions{ "-std=c++17" } + else + buildoptions{ "/std:c++17" } end if package_name ~= "eepp" and package_name ~= "eepp-static" then @@ -824,6 +826,8 @@ function build_eepp( build_name ) if not is_vs() then buildoptions{ "-std=c++17" } + else + buildoptions{ "/std:c++17" } end if os.is_real("mingw32") or os.is_real("mingw64") or os.is_real("windows") then @@ -1030,6 +1034,8 @@ solution "eepp" defines { "EFSW_USE_CXX11" } if not is_vs() then buildoptions{ "-std=c++17" } + else + buildoptions{ "/std:c++17" } end if os.is("windows") then @@ -1086,6 +1092,8 @@ solution "eepp" files { "src/modules/eterm/src/**.cpp" } if not is_vs() then buildoptions{ "-std=c++17" } + else + buildoptions{ "/std:c++17" } end build_base_cpp_configuration( "eterm" ) diff --git a/premake5.lua b/premake5.lua index 3312fc4ee..0564ce753 100644 --- a/premake5.lua +++ b/premake5.lua @@ -249,6 +249,7 @@ function build_link_configuration( package_name, use_ee_icon ) end end + cppdialect "C++17" set_ios_config() set_xcode_config() build_arch_configuration() @@ -268,7 +269,6 @@ function build_link_configuration( package_name, use_ee_icon ) vpaths { ['Resources/*'] = { "ee.rc", "ee.ico" } } filter "action:not vs*" - cppdialect "C++17" buildoptions { "-Wall" } filter { "configurations:debug*", "action:not vs*" } @@ -589,6 +589,8 @@ function build_eepp( build_name ) table.insert( link_list, get_backend_link_name( "freetype" ) ) end + cppdialect "C++17" + filter "options:use-frameworks" defines { "EE_USE_FRAMEWORKS" } @@ -618,9 +620,6 @@ function build_eepp( build_name ) filter "action:vs*" incdirs { "src/thirdparty/libzip/vs" } - - filter "action:not vs*" - cppdialect "C++17" end workspace "eepp" @@ -785,8 +784,7 @@ workspace "eepp" files { "src/thirdparty/efsw/src/efsw/*.cpp" } build_base_cpp_configuration( "efsw" ) defines { "EFSW_USE_CXX11" } - filter "action:not vs*" - cppdialect "C++17" + cppdialect "C++17" filter "system:windows" files { "src/thirdparty/efsw/src/efsw/platform/win/*.cpp" } excludes { @@ -832,8 +830,8 @@ workspace "eepp" incdirs { "include", "src/modules/eterm/include/","src/modules/eterm/src/" } files { "src/modules/eterm/src/**.cpp" } build_base_cpp_configuration( "eterm" ) + cppdialect "C++17" filter "action:not vs*" - cppdialect "C++17" buildoptions { "-Wall" } -- Library diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index ecb7f951b..53cce69e2 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -871,6 +871,16 @@ TextPosition UICodeEditor::resolveScreenPosition( const Vector2f& position, bool return TextPosition( line, getColFromXOffset( line, localPos.x ) ); } +Rectf UICodeEditor::getScreenPosition( const TextPosition& position ) const { + Float lineHeight = getLineHeight(); + Vector2f screenStart( getScreenStart() ); + Vector2f start( screenStart.x + getGutterWidth(), screenStart.y ); + Vector2f startScroll( start - mScroll ); + return { { startScroll.x + getXOffsetColSanitized( position ), + startScroll.y + lineHeight * position.line() }, + { getGlyphWidth(), lineHeight } }; +} + Vector2f UICodeEditor::getViewPortLineCount() const { return Vector2f( eefloor( getViewportWidth() / getGlyphWidth() ), @@ -1608,7 +1618,7 @@ void UICodeEditor::setScrollY( const Float& val, bool emmitEvent ) { } } -Float UICodeEditor::getXOffsetCol( const TextPosition& position ) { +Float UICodeEditor::getXOffsetCol( const TextPosition& position ) const { if ( mFont && !mFont->isMonospace() ) { return getLineText( position.line() ) .findCharacterPos( @@ -1657,14 +1667,12 @@ Float UICodeEditor::getTextWidth( const String& line ) const { return x; } -Float UICodeEditor::getColXOffset( TextPosition position ) { +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() ) ) ); - if ( mFont && !mFont->isMonospace() ) - return getXOffsetCol( position ); - return getTextWidth( mDoc->line( position.line() ).substr( 0, position.column() ) ); + return getXOffsetCol( position ); } const bool& UICodeEditor::isLocked() const { @@ -2175,9 +2183,8 @@ void UICodeEditor::resetCursor() { TextPosition UICodeEditor::moveToLineOffset( const TextPosition& position, int offset ) { auto& xo = mLastXOffset; - if ( xo.position != position ) { - xo.offset = getColXOffset( position ); - } + if ( xo.position != position ) + xo.offset = getXOffsetColSanitized( position ); xo.position.setLine( position.line() + offset ); xo.position.setColumn( getColFromXOffset( position.line() + offset, xo.offset ) ); return xo.position; @@ -3256,5 +3263,4 @@ void UICodeEditor::invalidateLinesCache() { invalidateDraw(); } } - }} // namespace EE::UI diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index ef88cdf8e..b15e62627 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -554,23 +554,21 @@ bool LinterPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& pos, const auto it = mMatches.find( editor->getDocumentRef().get() ); if ( it != mMatches.end() ) { Vector2f localPos( editor->convertToNodeSpace( pos.asFloat() ) ); - auto visibleLineRange = editor->getVisibleLineRange(); - for ( auto& matchIt : it->second ) { - Uint64 matchLine = matchIt.first; - if ( matchLine >= visibleLineRange.first && matchLine <= visibleLineRange.second ) { - auto& matches = matchIt.second; - for ( auto& match : matches ) { - if ( match.box[editor].contains( localPos ) ) { - mHoveringMatch = true; - editor->runOnMainThread( [&, editor] { - editor->setTooltipText( match.text ); - editor->getTooltip()->setDontAutoHideOnMouseMove( true ); - editor->getTooltip()->setPixelsPosition( Vector2f( pos.x, pos.y ) ); - if ( !editor->getTooltip()->isVisible() ) - editor->getTooltip()->show(); - } ); - return true; - } + TextPosition cursorPosition = editor->resolveScreenPosition( pos.asFloat() ); + auto matchIt = it->second.find( cursorPosition.line() ); + if ( matchIt != it->second.end() ) { + auto& matches = matchIt->second; + for ( auto& match : matches ) { + if ( match.box[editor].contains( localPos ) ) { + mHoveringMatch = true; + editor->runOnMainThread( [&, editor] { + editor->setTooltipText( match.text ); + editor->getTooltip()->setDontAutoHideOnMouseMove( true ); + editor->getTooltip()->setPixelsPosition( Vector2f( pos.x, pos.y ) ); + if ( !editor->getTooltip()->isVisible() ) + editor->getTooltip()->show(); + } ); + return true; } } } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp index cf44493fb..63610438e 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.cpp @@ -4,8 +4,11 @@ #include #include #include +#include +#include #include +using namespace EE::Window; using json = nlohmann::json; namespace ecode { @@ -320,32 +323,44 @@ static void hideTooltip( UICodeEditor* editor ) { } } +TextPosition currentMouseTextPosition( UICodeEditor* editor ) { + return editor->resolveScreenPosition( + editor->getUISceneNode()->getWindow()->getInput()->getMousePosf() ); +} + bool LSPClientPlugin::onMouseMove( UICodeEditor* editor, const Vector2i& position, const Uint32& ) { Uint32 tag = String::hash( editor->getDocument().getFilePath() ); editor->removeActionsByTag( tag ); editor->runOnMainThread( [&, editor, position]() { - TextPosition cursorPosition = editor->resolveScreenPosition( position.asFloat() ); - mThreadPool->run( [&, editor, position, cursorPosition]() { + mThreadPool->run( [&, editor, position]() { mClientManager.getOneLSPClientServer( editor )->documentHover( - editor->getDocument().getURI(), cursorPosition, + editor->getDocument().getURI(), currentMouseTextPosition( editor ), [&, editor, position]( const LSPHover& resp ) { - mCurrentHover = resp; if ( resp.range.isValid() && !resp.contents.empty() ) { - editor->runOnMainThread( [editor, resp, position]() { - editor->setTooltipText( resp.contents[0].value ); - editor->getTooltip()->setHorizontalAlign( UI_HALIGN_LEFT ); - editor->getTooltip()->setPixelsPosition( position.asFloat() ); - editor->getTooltip()->setDontAutoHideOnMouseMove( true ); - if ( editor->hasFocus() && !editor->getTooltip()->isVisible() ) - editor->getTooltip()->show(); + editor->runOnMainThread( [editor, resp, position, this]() { + TextPosition startCursorPosition = + editor->resolveScreenPosition( position.asFloat() ); + TextPosition currentMousePosition = + currentMouseTextPosition( editor ); + if ( startCursorPosition != currentMousePosition ) + return; + if ( resp.range.isValid() && !resp.contents.empty() && + resp.range.contains( startCursorPosition ) ) { + mCurrentHover = resp; + editor->setTooltipText( resp.contents[0].value ); + editor->getTooltip()->setHorizontalAlign( UI_HALIGN_LEFT ); + editor->getTooltip()->setPixelsPosition( position.asFloat() ); + editor->getTooltip()->setDontAutoHideOnMouseMove( true ); + if ( editor->hasFocus() && !editor->getTooltip()->isVisible() ) + editor->getTooltip()->show(); + } } ); } } ); } ); }, mHoverDelay, tag ); - TextPosition cursorPosition = editor->resolveScreenPosition( position.asFloat() ); if ( !mCurrentHover.range.isValid() || !mCurrentHover.range.contains( cursorPosition ) ) hideTooltip( editor ); @@ -357,6 +372,15 @@ void LSPClientPlugin::onFocusLoss( UICodeEditor* editor ) { hideTooltip( editor ); } +bool LSPClientPlugin::onKeyDown( UICodeEditor* editor, const KeyEvent& event ) { + if ( event.getSanitizedMod() == 0 && event.getKeyCode() == KEY_ESCAPE && editor->getTooltip() && + editor->getTooltip()->isVisible() ) { + editor->getTooltip()->hide(); + } + + return false; +} + const Time& LSPClientPlugin::getHoverDelay() const { return mHoverDelay; } diff --git a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp index 2420c94cc..e48e99275 100644 --- a/src/tools/ecode/plugins/lsp/lspclientplugin.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientplugin.hpp @@ -58,7 +58,10 @@ class LSPClientPlugin : public UICodeEditorPlugin { virtual void onFocusLoss( UICodeEditor* editor ); + virtual bool onKeyDown( UICodeEditor*, const KeyEvent& ); + const Time& getHoverDelay() const; + void setHoverDelay( const Time& hoverDelay ); protected: diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index 5968444f5..5a5e8f718 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -307,14 +307,6 @@ static bool isPositionValid( const TextPosition& pos ) { } static std::vector parseDocumentSymbols( const json& result ) { - // the reply could be old SymbolInformation[] or new (hierarchical) DocumentSymbol[] - // try to parse it adaptively in any case - // if new style, hierarchy is specified clearly in reply - // if old style, it is assumed the values enter linearly, that is; - // * a parent/container is listed before its children - // * if a name is defined/declared several times and then used as a parent, - // then we try to find such a parent whose range contains current range - // (otherwise fall back to using the last instance as a parent) std::vector ret; std::map index; @@ -325,15 +317,11 @@ static std::vector parseDocumentSymbols( const json& resul : symbol[MEMBER_LOCATION].at( MEMBER_RANGE ); auto range = parseRange( mrange ); std::map::iterator it = index.end(); - // if flat list, try to find parent by name if ( !parent ) { auto container = symbol.value( "containerName", "" ); it = index.find( container ); - // default to last inserted - if ( it != index.end() ) { + if ( it != index.end() ) parent = it->second; - } - // but prefer a containing range while ( it != index.end() && it->first == container ) { if ( it->second->range.contains( range ) ) { parent = it->second; @@ -348,8 +336,7 @@ static std::vector parseDocumentSymbols( const json& resul auto kind = static_cast( symbol.at( MEMBER_KIND ).get() ); auto detail = symbol.value( MEMBER_DETAIL, "" ); list->push_back( { name, kind, range, detail } ); - index.insert( std::pair( name, &list->back() ) ); - // proceed recursively + index.insert( std::make_pair( name, &list->back() ) ); if ( symbol.contains( "children" ) ) { const auto& children = symbol.at( ( "children" ) ); for ( const auto& child : children )