mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-01 11:06:30 +03:00
More WIP.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
"run": {
|
||||
"command": "gdb --interpreter=dap"
|
||||
},
|
||||
"languages": [ "cpp", "c", "d", "go", "objectivec", "fortran", "pascal", "rust" ],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "launch binary",
|
||||
@@ -27,6 +28,7 @@
|
||||
"run": {
|
||||
"command": "lldb-dap"
|
||||
},
|
||||
"languages": [ "cpp", "c", "odin", "rust", "zig" ],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "launch binary",
|
||||
|
||||
@@ -118,6 +118,8 @@ class EE_API EventDispatcher {
|
||||
|
||||
void setLastFocusNode( Node* lastFocusNode );
|
||||
|
||||
bool isFirstPress() const;
|
||||
|
||||
protected:
|
||||
EE::Window::Window* mWindow;
|
||||
Input* mInput;
|
||||
@@ -134,7 +136,8 @@ class EE_API EventDispatcher {
|
||||
Vector2i mClickPos;
|
||||
Int32 mCbId;
|
||||
Uint32 mIMECbId;
|
||||
bool mFirstPress;
|
||||
bool mFirstPress{ false };
|
||||
bool mJustPressed{ false };
|
||||
bool mDisableMousePress{ false };
|
||||
bool mJustDisabledMousePress{ false };
|
||||
Node* mNodeWasDragging;
|
||||
|
||||
@@ -107,6 +107,18 @@ class UICodeEditorPlugin {
|
||||
virtual void drawTop( UICodeEditor* /*editor*/, const Vector2f& /*screenStart*/,
|
||||
const Sizef& /*size*/, const Float& /*fontSize*/ ) {};
|
||||
|
||||
virtual void
|
||||
drawLineNumbersBefore( UICodeEditor* /*editor*/, const DocumentLineRange& /*lineRange*/,
|
||||
const Vector2f& /*startScroll*/, const Vector2f& /*screenStart*/,
|
||||
const Float& /*lineHeight*/, const Float& /*lineNumberWidth*/,
|
||||
const int& /*lineNumberDigits*/, const Float& /*fontSize*/ ) {}
|
||||
|
||||
virtual void
|
||||
drawLineNumbersAfter( UICodeEditor* /*editor*/, const DocumentLineRange& /*lineRange*/,
|
||||
const Vector2f& /*startScroll*/, const Vector2f& /*screenStart*/,
|
||||
const Float& /*lineHeight*/, const Float& /*lineNumberWidth*/,
|
||||
const int& /*lineNumberDigits*/, const Float& /*fontSize*/ ) {}
|
||||
|
||||
Uint32 addOnReadyCallback( const OnReadyCb& cb ) {
|
||||
mOnReadyCallbacks[mReadyCbNum++] = cb;
|
||||
return mReadyCbNum;
|
||||
@@ -753,6 +765,14 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
void setTabIndentAlignment( CharacterAlignment alignment );
|
||||
|
||||
const DocumentView& getDocumentView() const { return mDocView; }
|
||||
|
||||
Float getGutterLocalStartOffset( UICodeEditorPlugin* plugin ) const;
|
||||
|
||||
Float getGutterSpace( UICodeEditorPlugin* plugin ) const;
|
||||
|
||||
Float getPluginsGutterSpace() const;
|
||||
|
||||
protected:
|
||||
struct LastXOffset {
|
||||
TextPosition position{ 0, 0 };
|
||||
|
||||
@@ -118,11 +118,14 @@ void EventDispatcher::update( const Time& time ) {
|
||||
if ( NULL != mNodeDragging )
|
||||
mNodeDragging->onCalculateDrag( mMousePos, mInput->getPressTrigger() );
|
||||
|
||||
mJustPressed = false;
|
||||
|
||||
if ( mInput->getPressTrigger() ) {
|
||||
if ( !mFirstPress ) {
|
||||
mDownNode = mOverNode;
|
||||
mMouseDownPos = mMousePosi;
|
||||
mFirstPress = true;
|
||||
mJustPressed = true;
|
||||
}
|
||||
|
||||
if ( NULL != mOverNode ) {
|
||||
@@ -142,6 +145,7 @@ void EventDispatcher::update( const Time& time ) {
|
||||
mDownNode = mOverNode;
|
||||
mMouseDownPos = mMousePosi;
|
||||
mFirstPress = true;
|
||||
mJustPressed = true;
|
||||
}
|
||||
mOverNode->onMouseDown( mMousePosi, mInput->getReleaseTrigger() );
|
||||
sendMsg( mOverNode, NodeMessage::MouseDown, mInput->getReleaseTrigger() );
|
||||
@@ -324,6 +328,10 @@ void EventDispatcher::setLastFocusNode( Node* lastFocusNode ) {
|
||||
mLastFocusNode = lastFocusNode;
|
||||
}
|
||||
|
||||
bool EventDispatcher::isFirstPress() const {
|
||||
return mJustPressed;
|
||||
}
|
||||
|
||||
Node* EventDispatcher::getMouseDownNode() const {
|
||||
return mDownNode;
|
||||
}
|
||||
|
||||
@@ -1398,8 +1398,10 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
|
||||
if ( localPos.y < mPluginsTopSpace )
|
||||
return UIWidget::onMouseDown( position, flags );
|
||||
|
||||
bool downOverGutter = localPos.x < mPaddingPx.Left + getGutterWidth();
|
||||
|
||||
if ( flags & EE_BUTTON_LMASK ) {
|
||||
if ( localPos.x < mPaddingPx.Left + getGutterWidth() ) {
|
||||
if ( localPos.x > mPaddingPx.Left + getLineNumberWidth() && downOverGutter ) {
|
||||
if ( mDoc->getFoldRangeService().isFoldingRegionInLine( textScreenPos.line() ) ) {
|
||||
if ( mDocView.isFolded( textScreenPos.line() ) ) {
|
||||
mDocView.unfoldRegion( textScreenPos.line() );
|
||||
@@ -1407,7 +1409,7 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
|
||||
mDocView.foldRegion( textScreenPos.line() );
|
||||
}
|
||||
}
|
||||
} else if ( input->isModState( KEYMOD_LALT | KEYMOD_SHIFT ) ) {
|
||||
} else if ( !downOverGutter && input->isModState( KEYMOD_LALT | KEYMOD_SHIFT ) ) {
|
||||
TextRange range( mDoc->getSelection().start(), textScreenPos );
|
||||
range = mDoc->sanitizeRange( range );
|
||||
TextRange nrange = range.normalized();
|
||||
@@ -1418,16 +1420,17 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
|
||||
ranges.push_back( TextRange{ pos, pos } );
|
||||
}
|
||||
mDoc->addSelections( std::move( ranges ) );
|
||||
} else if ( input->isModState( KEYMOD_SHIFT ) ) {
|
||||
} else if ( !downOverGutter && input->isModState( KEYMOD_SHIFT ) ) {
|
||||
mDoc->selectTo( textScreenPos );
|
||||
} else if ( input->isModState( KEYMOD_CTRL ) &&
|
||||
} else if ( !downOverGutter && input->isModState( KEYMOD_CTRL ) &&
|
||||
checkMouseOverLink( position ).empty() ) {
|
||||
TextPosition pos( textScreenPos );
|
||||
if ( !mDoc->selectionExists( pos ) )
|
||||
mDoc->addSelection( { pos, pos } );
|
||||
} else if ( mLastDoubleClick.getElapsedTime() < Milliseconds( 300.f ) ) {
|
||||
} else if ( !downOverGutter &&
|
||||
mLastDoubleClick.getElapsedTime() < Milliseconds( 300.f ) ) {
|
||||
mDoc->selectLine();
|
||||
} else {
|
||||
} else if ( !downOverGutter ) {
|
||||
mDoc->setSelection( textScreenPos );
|
||||
}
|
||||
} else if ( !mDoc->hasSelection() ) {
|
||||
@@ -2899,6 +2902,28 @@ bool UICodeEditor::gutterSpaceExists( UICodeEditorPlugin* plugin ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Float UICodeEditor::getGutterLocalStartOffset( UICodeEditorPlugin* plugin ) const {
|
||||
Float offset = 0;
|
||||
for ( const auto& space : mPluginGutterSpaces ) {
|
||||
if ( space.plugin == plugin )
|
||||
return offset;
|
||||
offset += space.space;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
Float UICodeEditor::getGutterSpace( UICodeEditorPlugin* plugin ) const {
|
||||
for ( const auto& space : mPluginGutterSpaces ) {
|
||||
if ( space.plugin == plugin )
|
||||
return space.space;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Float UICodeEditor::getPluginsGutterSpace() const {
|
||||
return mPluginsGutterSpace;
|
||||
}
|
||||
|
||||
bool UICodeEditor::topSpaceExists( UICodeEditorPlugin* plugin ) const {
|
||||
for ( const auto& space : mPluginTopSpaces ) {
|
||||
if ( space.plugin == plugin )
|
||||
@@ -3846,6 +3871,11 @@ void UICodeEditor::drawLineNumbers( const DocumentLineRange& lineRange, const Ve
|
||||
TextRange selection = mDoc->getSelection( true );
|
||||
Float lineOffset = getLineOffset();
|
||||
|
||||
for ( auto plugin : mPlugins ) {
|
||||
plugin->drawLineNumbersBefore( this, lineRange, startScroll, screenStart, lineHeight,
|
||||
lineNumberWidth, lineNumberDigits, fontSize );
|
||||
}
|
||||
|
||||
for ( int i = lineRange.first; i <= lineRange.second; i++ ) {
|
||||
if ( !mDocView.isLineVisible( i ) )
|
||||
continue;
|
||||
@@ -3948,6 +3978,11 @@ void UICodeEditor::drawLineNumbers( const DocumentLineRange& lineRange, const Ve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto plugin : mPlugins ) {
|
||||
plugin->drawLineNumbersAfter( this, lineRange, startScroll, screenStart, lineHeight,
|
||||
lineNumberWidth, lineNumberDigits, fontSize );
|
||||
}
|
||||
}
|
||||
|
||||
void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& lineHeight,
|
||||
|
||||
@@ -23,8 +23,8 @@ bool BusSettings::hasConnection() const {
|
||||
}
|
||||
|
||||
ProtocolSettings::ProtocolSettings( const nlohmann::json& configuration ) :
|
||||
linesStartAt1( true ),
|
||||
columnsStartAt1( true ),
|
||||
linesStartAt1( false ),
|
||||
columnsStartAt1( false ),
|
||||
pathFormatURI( false ),
|
||||
redirectStderr( configuration.value( REDIRECT_STDERR, false ) ),
|
||||
redirectStdout( configuration.value( REDIRECT_STDOUT, false ) ),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <eepp/core/containers.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -169,6 +169,8 @@ struct SourceBreakpoint {
|
||||
SourceBreakpoint( const int line );
|
||||
|
||||
json toJson() const;
|
||||
|
||||
bool operator==( const SourceBreakpoint& other ) const { return line == other.line; }
|
||||
};
|
||||
|
||||
struct Breakpoint {
|
||||
@@ -474,4 +476,16 @@ struct GotoTarget {
|
||||
static std::vector<GotoTarget> parseList( const json& variables );
|
||||
};
|
||||
|
||||
} // namespace dap
|
||||
} // namespace ecode::dap
|
||||
|
||||
template <> struct std::hash<ecode::dap::SourceBreakpoint> {
|
||||
std::size_t operator()( ecode::dap::SourceBreakpoint const& breakpoint ) const noexcept {
|
||||
size_t h1 = std::hash<int>()( breakpoint.line );
|
||||
size_t h2 = breakpoint.column ? std::hash<int>()( *breakpoint.column ) : 0;
|
||||
size_t h3 = breakpoint.condition ? std::hash<std::string>()( *breakpoint.condition ) : 0;
|
||||
size_t h4 =
|
||||
breakpoint.hitCondition ? std::hash<std::string>()( *breakpoint.hitCondition ) : 0;
|
||||
size_t h5 = breakpoint.logMessage ? std::hash<std::string>()( *breakpoint.logMessage ) : 0;
|
||||
return hashCombine( h1, h2, h3, h4, h5 );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "busprocess.hpp"
|
||||
#include "dap/debuggerclientdap.hpp"
|
||||
#include "statusdebuggercontroller.hpp"
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/scopedop.hpp>
|
||||
#include <eepp/ui/uidropdownlist.hpp>
|
||||
@@ -151,6 +152,16 @@ void DebuggerPlugin::loadDAPConfig( const std::string& path, bool updateConfigFi
|
||||
dapTool.configurations.emplace_back( std::move( dapConfig ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dap.contains( "languages" ) && dap["languages"].is_array() ) {
|
||||
auto& languages = dap["languages"];
|
||||
dapTool.languagesSupported.reserve( languages.size() );
|
||||
for ( const auto& lang : languages ) {
|
||||
if ( lang.is_string() )
|
||||
dapTool.languagesSupported.emplace_back( lang.get<std::string>() );
|
||||
}
|
||||
}
|
||||
|
||||
mDaps.emplace_back( std::move( dapTool ) );
|
||||
}
|
||||
}
|
||||
@@ -381,6 +392,101 @@ void DebuggerPlugin::replaceKeysInJson( nlohmann::json& json ) {
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPlugin::onRegisterEditor( UICodeEditor* editor ) {
|
||||
editor->registerGutterSpace( this, PixelDensity::dpToPx( 8 ), 0 );
|
||||
}
|
||||
|
||||
void DebuggerPlugin::onUnregisterEditor( UICodeEditor* editor ) {
|
||||
editor->unregisterGutterSpace( this );
|
||||
}
|
||||
|
||||
void DebuggerPlugin::drawLineNumbersBefore( UICodeEditor* editor,
|
||||
const DocumentLineRange& lineRange,
|
||||
const Vector2f& startScroll,
|
||||
const Vector2f& screenStart, const Float& lineHeight,
|
||||
const Float&, const int&, const Float& ) {
|
||||
if ( !editor->getDocument().hasFilepath() )
|
||||
return;
|
||||
auto docIt = mBreakpoints.find( editor->getDocument().getFilePath() );
|
||||
if ( docIt == mBreakpoints.end() || docIt->second.empty() )
|
||||
return;
|
||||
const auto& breakpoints = docIt->second;
|
||||
Primitives p;
|
||||
Float lineOffset = editor->getLineOffset();
|
||||
p.setColor( Color( editor->getColorScheme().getEditorColor( SyntaxStyleTypes::Error ) )
|
||||
.blendAlpha( editor->getAlpha() ) );
|
||||
Float gutterSpace = editor->getGutterSpace( this );
|
||||
Float radius = PixelDensity::dpToPx( 3 );
|
||||
Float offset = editor->getGutterLocalStartOffset( this );
|
||||
|
||||
for ( const SourceBreakpoint& breakpoint : breakpoints ) {
|
||||
if ( breakpoint.line >= lineRange.first && breakpoint.line <= lineRange.second ) {
|
||||
if ( !editor->getDocumentView().isLineVisible( breakpoint.line ) )
|
||||
continue;
|
||||
|
||||
auto lnPos( Vector2f(
|
||||
screenStart.x - editor->getPluginsGutterSpace() + offset,
|
||||
startScroll.y +
|
||||
editor->getDocumentView().getLineYOffset( breakpoint.line, lineHeight ) +
|
||||
lineOffset ) );
|
||||
|
||||
// p.setColor( Color::Gray );
|
||||
// p.drawRectangle( { lnPos, Sizef{ gutterSpace, lineHeight } } );
|
||||
|
||||
p.setColor( Color( editor->getColorScheme().getEditorColor( SyntaxStyleTypes::Error ) )
|
||||
.blendAlpha( editor->getAlpha() ) );
|
||||
|
||||
p.drawCircle( { lnPos.x + radius + eefloor( ( gutterSpace - radius ) * 0.5f ),
|
||||
lnPos.y + lineHeight * 0.5f },
|
||||
radius );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DebuggerPlugin::onLineNumberClick( UICodeEditor* editor, Uint32 lineNumber ) {
|
||||
if ( !editor->getDocument().hasFilepath() )
|
||||
return false;
|
||||
if ( !isSupportedByAnyDebugger( editor->getDocument().getSyntaxDefinition().getLSPName() ) )
|
||||
return false;
|
||||
Lock l( mBreakpointsMutex );
|
||||
auto& breakpoints = mBreakpoints[editor->getDocument().getFilePath()];
|
||||
auto breakpointIt = breakpoints.find( SourceBreakpoint( lineNumber ) );
|
||||
if ( breakpointIt != breakpoints.end() ) {
|
||||
breakpoints.erase( breakpointIt );
|
||||
} else {
|
||||
breakpoints.insert( SourceBreakpoint( lineNumber ) );
|
||||
}
|
||||
editor->invalidateDraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DebuggerPlugin::onMouseDown( UICodeEditor* editor, const Vector2i& position,
|
||||
const Uint32& flags ) {
|
||||
if ( !( flags & EE_BUTTON_LMASK ) )
|
||||
return false;
|
||||
Float offset = editor->getGutterLocalStartOffset( this );
|
||||
Vector2f localPos( editor->convertToNodeSpace( position.asFloat() ) );
|
||||
if ( localPos.x >= editor->getPixelsPadding().Left + offset &&
|
||||
localPos.x < editor->getPixelsPadding().Left + offset + editor->getGutterSpace( this ) &&
|
||||
localPos.y > editor->getPluginsTopSpace() ) {
|
||||
if ( editor->getUISceneNode()->getEventDispatcher()->isFirstPress() ) {
|
||||
auto cursorPos( editor->resolveScreenPosition( position.asFloat() ) );
|
||||
onLineNumberClick( editor, cursorPos.line() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DebuggerPlugin::isSupportedByAnyDebugger( const std::string& language ) {
|
||||
for ( const auto& dap : mDaps ) {
|
||||
if ( std::any_of( dap.languagesSupported.begin(), dap.languagesSupported.end(),
|
||||
[&language]( const auto& l ) { return l == language; } ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebuggerPlugin::runConfig( const std::string& debugger, const std::string& configuration ) {
|
||||
auto debuggerIt = std::find_if( mDaps.begin(), mDaps.end(), [&debugger]( const DapTool& dap ) {
|
||||
return dap.name == debugger;
|
||||
|
||||
@@ -23,6 +23,7 @@ struct DapConfig {
|
||||
struct DapTool {
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::vector<std::string> languagesSupported;
|
||||
DapRunConfig run;
|
||||
std::vector<DapConfig> configurations;
|
||||
};
|
||||
@@ -63,6 +64,8 @@ class DebuggerPlugin : public PluginBase {
|
||||
UIDropDownList* mUIDebuggerList{ nullptr };
|
||||
UIDropDownList* mUIDebuggerConfList{ nullptr };
|
||||
UIPushButton* mRunButton{ nullptr };
|
||||
UnorderedMap<std::string, UnorderedSet<SourceBreakpoint>> mBreakpoints;
|
||||
Mutex mBreakpointsMutex;
|
||||
|
||||
DebuggerPlugin( PluginManager* pluginManager, bool sync );
|
||||
|
||||
@@ -91,6 +94,21 @@ class DebuggerPlugin : public PluginBase {
|
||||
void exitDebugger();
|
||||
|
||||
void replaceKeysInJson( nlohmann::json& json );
|
||||
|
||||
void onRegisterEditor( UICodeEditor* ) override;
|
||||
|
||||
void onUnregisterEditor( UICodeEditor* ) override;
|
||||
|
||||
void drawLineNumbersBefore( UICodeEditor* editor, const DocumentLineRange& lineRange,
|
||||
const Vector2f& startScroll, const Vector2f& screenStart,
|
||||
const Float& lineHeight, const Float& lineNumberWidth,
|
||||
const int& lineNumberDigits, const Float& fontSize ) override;
|
||||
|
||||
bool onLineNumberClick( UICodeEditor* editor, Uint32 lineNumber );
|
||||
|
||||
bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& flags ) override;
|
||||
|
||||
bool isSupportedByAnyDebugger( const std::string& language );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -170,6 +170,8 @@ void PluginBase::onRegister( UICodeEditor* editor ) {
|
||||
onRegisterDocument( editor->getDocumentRef().get() );
|
||||
}
|
||||
mEditorDocs[editor] = editor->getDocumentRef().get();
|
||||
|
||||
onRegisterEditor( editor );
|
||||
}
|
||||
|
||||
void PluginBase::onUnregister( UICodeEditor* editor ) {
|
||||
|
||||
@@ -104,6 +104,8 @@ class PluginBase : public Plugin {
|
||||
|
||||
virtual void onRegisterDocument( TextDocument* ) {};
|
||||
|
||||
virtual void onRegisterEditor( UICodeEditor* ) {};
|
||||
|
||||
virtual void onUnregisterEditor( UICodeEditor* ) {};
|
||||
|
||||
//! Usually used to unregister commands in a document
|
||||
|
||||
Reference in New Issue
Block a user