From 3a12928b8337fb45dc46ce26291b0980e51f6dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 2 Jul 2022 00:44:25 -0300 Subject: [PATCH] UITab: Implemented proper support for max/min width and height. UICodeEditor::getLineHeight() now uses the font height. ecode: Fixes for Formatter and Linter plugins. --- include/eepp/ui/uitabwidget.hpp | 12 +++---- include/eepp/ui/uitextview.hpp | 2 +- include/eepp/ui/uiwidget.hpp | 4 +-- include/eepp/window/engine.hpp | 2 ++ premake4.lua | 2 +- projects/linux/ee.creator.user | 5 +-- projects/linux/ee.files | 1 + src/eepp/ui/uicodeeditor.cpp | 2 +- src/eepp/ui/uisplitter.cpp | 12 +++---- src/eepp/ui/uitab.cpp | 19 +++++++--- src/eepp/ui/uitabwidget.cpp | 16 ++++----- src/eepp/ui/uitextview.cpp | 28 ++++++++++----- src/eepp/ui/uiwidget.cpp | 8 ++--- src/eepp/window/engine.cpp | 4 +++ .../plugins/formatter/formatterplugin.cpp | 35 +++++++++++++----- .../plugins/formatter/formatterplugin.hpp | 7 ++-- .../ecode/plugins/linter/linterplugin.cpp | 36 ++++++++++++++----- .../ecode/plugins/linter/linterplugin.hpp | 8 +++-- src/tools/ecode/scopedop.hpp | 24 +++++++++++++ src/tools/ecode/thirdparty/subprocess.h | 12 +++---- 20 files changed, 169 insertions(+), 70 deletions(-) create mode 100644 src/tools/ecode/scopedop.hpp diff --git a/include/eepp/ui/uitabwidget.hpp b/include/eepp/ui/uitabwidget.hpp index e02838491..4ca120fba 100644 --- a/include/eepp/ui/uitabwidget.hpp +++ b/include/eepp/ui/uitabwidget.hpp @@ -31,8 +31,8 @@ class EE_API UITabWidget : public UIWidget { Uint32 MaxTextLength = 100; Float TabHeight = 0; Uint32 TabTextAlign = ( UI_HALIGN_CENTER | UI_VALIGN_CENTER ); - Float MinTabWidth = 32; - Float MaxTabWidth = 300; + std::string MinTabWidth = "32dp"; + std::string MaxTabWidth = "300dp"; bool TabsClosable = false; bool TabsEdgesDiffSkins = false; //! Indicates if the edge tabs ( the left and right //! border tab ) are different from the central tabs. @@ -91,13 +91,13 @@ class EE_API UITabWidget : public UIWidget { void setMaxTextLength( const Uint32& maxTextLength ); - Float getMinTabWidth() const; + std::string getMinTabWidth() const; - void setMinTabWidth( const Float& minTabWidth ); + void setMinTabWidth( const std::string& minTabWidth ); - Float getMaxTabWidth() const; + std::string getMaxTabWidth() const; - void setMaxTabWidth( const Float& maxTabWidth ); + void setMaxTabWidth( const std::string& maxTabWidth ); bool getTabsClosable() const; diff --git a/include/eepp/ui/uitextview.hpp b/include/eepp/ui/uitextview.hpp index f7fda55e2..ca74f133b 100644 --- a/include/eepp/ui/uitextview.hpp +++ b/include/eepp/ui/uitextview.hpp @@ -119,7 +119,7 @@ class EE_API UITextView : public UIWidget { virtual void onSizeChange(); - virtual void autoShrink(); + virtual void autoWrap(); virtual void onAutoSize(); diff --git a/include/eepp/ui/uiwidget.hpp b/include/eepp/ui/uiwidget.hpp index 7a9850433..867fcff32 100644 --- a/include/eepp/ui/uiwidget.hpp +++ b/include/eepp/ui/uiwidget.hpp @@ -239,9 +239,9 @@ class EE_API UIWidget : public UINode { void createTooltip(); - Sizef getCurrentMinSize(); + Sizef getMinSize(); - Sizef getCurrentMaxSize(); + Sizef getMaxSize(); bool isTabStop() const; diff --git a/include/eepp/window/engine.hpp b/include/eepp/window/engine.hpp index 4adf180b0..89448f6be 100644 --- a/include/eepp/window/engine.hpp +++ b/include/eepp/window/engine.hpp @@ -24,6 +24,8 @@ class EE_API Engine { public: ~Engine(); + static bool isEngineRunning(); + /** Creates a new window. */ EE::Window::Window* createWindow( WindowSettings Settings, ContextSettings Context = ContextSettings() ); diff --git a/premake4.lua b/premake4.lua index 3fd266acb..d5e581808 100644 --- a/premake4.lua +++ b/premake4.lua @@ -1184,7 +1184,7 @@ solution "eepp" set_kind() language "C++" files { "src/tools/eterm/**.cpp" } - if os.is("linux") then + if os.is_real("linux") then links { "util" } end if os.is("haiku") then diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 68086c966..710912c89 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -109,7 +109,7 @@ {388e5431-b31b-42b3-b9ad-9002d279d75d} 10 0 - 20 + 19 ../../make/linux @@ -1203,6 +1203,7 @@ ecode-debug ProjectExplorer.CustomExecutableRunConfiguration + "/home/downloads/Reporte de facturacion de 01-06-2022 a 30-06-2022.csv" true false false diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 19c7e7a3a..a4faac67f 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1125,6 +1125,7 @@ ../../src/tools/ecode/projectdirectorytree.hpp ../../src/tools/ecode/projectsearch.cpp ../../src/tools/ecode/projectsearch.hpp +../../src/tools/ecode/scopedop.hpp ../../src/tools/ecode/uicodeeditorsplitter.cpp ../../src/tools/ecode/uicodeeditorsplitter.hpp ../../src/tools/ecode/uitreeviewglobalsearch.cpp diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index ea9c97999..f70e90299 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -2033,7 +2033,7 @@ Int64 UICodeEditor::getColFromXOffset( Int64 lineNumber, const Float& x ) const } Float UICodeEditor::getLineHeight() const { - return mFont->getLineSpacing( getCharacterSize() ); + return mFont->getFontHeight( getCharacterSize() ); } Float UICodeEditor::getCharacterSize() const { diff --git a/src/eepp/ui/uisplitter.cpp b/src/eepp/ui/uisplitter.cpp index d853efc79..17872f3aa 100644 --- a/src/eepp/ui/uisplitter.cpp +++ b/src/eepp/ui/uisplitter.cpp @@ -188,13 +188,13 @@ void UISplitter::updateFromDrag() { mSplitter->setEnabled( mSplitter->isVisible() ); if ( UIOrientation::Horizontal == mOrientation ) { - Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f; + Float fMinSize = mFirstWidget ? mFirstWidget->getMinSize().getWidth() : 0.f; if ( mSplitter->getPosition().x < mPadding.Left + fMinSize ) { mSplitter->setPosition( mPadding.Left + fMinSize, mSplitter->getPosition().y ); } - Float lMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getWidth() : 0.f; + Float lMinSize = mLastWidget ? mLastWidget->getMinSize().getWidth() : 0.f; if ( mSplitter->getPosition().x + mSplitter->getSize().getWidth() > mDpSize.getWidth() - mPadding.Right - lMinSize ) { @@ -206,13 +206,13 @@ void UISplitter::updateFromDrag() { mSplitter->setPixelsSize( mSplitter->getPixelsSize().getWidth(), mSize.getHeight() - mPaddingPx.Top - mPaddingPx.Bottom ); } else { - Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getHeight() : 0.f; + Float fMinSize = mFirstWidget ? mFirstWidget->getMinSize().getHeight() : 0.f; if ( mSplitter->getPosition().y < mPadding.Top + fMinSize ) { mSplitter->setPosition( mSplitter->getPosition().x, mPadding.Top + fMinSize ); } - Float lMinSize = mLastWidget ? mLastWidget->getCurrentMinSize().getHeight() : 0.f; + Float lMinSize = mLastWidget ? mLastWidget->getMinSize().getHeight() : 0.f; if ( mSplitter->getPosition().y + mSplitter->getSize().getHeight() > mDpSize.getHeight() - mPadding.Bottom - lMinSize ) { @@ -346,7 +346,7 @@ void UISplitter::updateLayout() { mFirstWidget->setPixelsPosition( mPaddingPx.Left, mPaddingPx.Top ); if ( UIOrientation::Horizontal == mOrientation ) { - Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getWidth() : 0.f; + Float fMinSize = mFirstWidget ? mFirstWidget->getMinSize().getWidth() : 0.f; firstSplit = eemax( firstSplit, fMinSize ); secondSplit = totalSpace - firstSplit; @@ -361,7 +361,7 @@ void UISplitter::updateLayout() { mSize.getHeight() - mPaddingPx.Top - mPaddingPx.Bottom ); } else { - Float fMinSize = mFirstWidget ? mFirstWidget->getCurrentMinSize().getHeight() : 0.f; + Float fMinSize = mFirstWidget ? mFirstWidget->getMinSize().getHeight() : 0.f; firstSplit = eemax( firstSplit, fMinSize ); secondSplit = totalSpace - firstSplit; diff --git a/src/eepp/ui/uitab.cpp b/src/eepp/ui/uitab.cpp index 398cbf4b2..904a6a9ba 100644 --- a/src/eepp/ui/uitab.cpp +++ b/src/eepp/ui/uitab.cpp @@ -229,8 +229,7 @@ void UITab::onAutoSize() { } if ( mFlags & UI_AUTO_SIZE ) { - Float w = - mTextBox->getSize().getWidth() + + Float nonTextW = ( NULL != mIcon ? mIcon->getSize().getWidth() + mIcon->getLayoutMargin().Left + mIcon->getLayoutMargin().Right : 0 ) + @@ -239,10 +238,17 @@ void UITab::onAutoSize() { mCloseButton->getLayoutMargin().Right : 0 ) + getSkinSize().getWidth(); + Float textW = mTextBox->getSize().getWidth(); + Float w = textW + nonTextW; if ( NULL != tTabW ) { - w = eemax( w, tTabW->getMinTabWidth() ); - w = eemin( w, tTabW->getMaxTabWidth() ); + if ( !mMinWidthEq.empty() ) + w = eemax( w, getMinSize().getWidth() ); + if ( !mMaxWidthEq.empty() ) + w = eemin( w, getMaxSize().getWidth() ); + + if ( textW > w - nonTextW ) + getTextBox()->setMaxWidthEq( String::format( "%.0fdp", w - nonTextW ) ); } setInternalWidth( w ); @@ -251,6 +257,9 @@ void UITab::onAutoSize() { if ( NULL != getTabWidget() ) getTabWidget()->orderTabs(); } + + if ( getTextBox()->getTextWidth() > getTextBox()->getSize().getWidth() ) + getTextBox()->setHorizontalAlign( UI_HALIGN_LEFT ); } } @@ -346,6 +355,8 @@ void UITab::updateTab() { UITabWidget* tTabW = getTabWidget(); if ( NULL != tTabW ) { + setMinWidthEq( tTabW->getMinTabWidth() ); + setMaxWidthEq( tTabW->getMaxTabWidth() ); if ( mText.size() > tTabW->getMaxTextLength() ) { UIPushButton::setText( mText.substr( 0, tTabW->getMaxTextLength() ) ); } else { diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index 8fc8d22f7..87a268f72 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -149,9 +149,9 @@ std::string UITabWidget::getPropertyString( const PropertyDefinition* propertyDe case PropertyId::MaxTextLength: return String::toString( getMaxTextLength() ); case PropertyId::MinTabWidth: - return String::fromFloat( getMinTabWidth(), "dp" ); + return getMinTabWidth(); case PropertyId::MaxTabWidth: - return String::fromFloat( getMaxTabWidth(), "dp" ); + return getMaxTabWidth(); case PropertyId::TabClosable: return getTabsClosable() ? "true" : "false"; case PropertyId::TabsEdgesDiffSkin: @@ -221,10 +221,10 @@ bool UITabWidget::applyProperty( const StyleSheetProperty& attribute ) { setMaxTextLength( attribute.asUint( 1 ) ); break; case PropertyId::MinTabWidth: - setMinTabWidth( attribute.asDpDimension( this, "1" ) ); + setMinTabWidth( attribute.asString() ); break; case PropertyId::MaxTabWidth: - setMaxTabWidth( attribute.asDpDimension( this ) ); + setMaxTabWidth( attribute.asString() ); break; case PropertyId::TabClosable: setTabsClosable( attribute.asBool() ); @@ -281,11 +281,11 @@ void UITabWidget::setMaxTextLength( const Uint32& maxTextLength ) { } } -Float UITabWidget::getMinTabWidth() const { +std::string UITabWidget::getMinTabWidth() const { return mStyleConfig.MinTabWidth; } -void UITabWidget::setMinTabWidth( const Float& minTabWidth ) { +void UITabWidget::setMinTabWidth( const std::string& minTabWidth ) { if ( minTabWidth != mStyleConfig.MinTabWidth ) { mStyleConfig.MinTabWidth = minTabWidth; updateTabs(); @@ -293,11 +293,11 @@ void UITabWidget::setMinTabWidth( const Float& minTabWidth ) { } } -Float UITabWidget::getMaxTabWidth() const { +std::string UITabWidget::getMaxTabWidth() const { return mStyleConfig.MaxTabWidth; } -void UITabWidget::setMaxTabWidth( const Float& maxTabWidth ) { +void UITabWidget::setMaxTabWidth( const std::string& maxTabWidth ) { if ( maxTabWidth != mStyleConfig.MaxTabWidth ) { mStyleConfig.MaxTabWidth = maxTabWidth; updateTabs(); diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index b6e7509ad..eeb6a09f8 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -265,7 +265,7 @@ UITextView* UITextView::setSelectionBackColor( const Color& color ) { return this; } -void UITextView::autoShrink() { +void UITextView::autoWrap() { if ( mFlags & UI_WORD_WRAP ) { wrapText( mSize.getWidth() ); } @@ -286,13 +286,25 @@ void UITextView::onAutoSize() { } if ( mWidthPolicy == SizePolicy::WrapContent ) { - setInternalPixelsWidth( (int)mTextCache->getTextWidth() + mPaddingPx.Left + - mPaddingPx.Right ); + Float totW = (int)mTextCache->getTextWidth() + mPaddingPx.Left + mPaddingPx.Right; + if ( !getMaxWidthEq().empty() ) { + Float oldW = totW; + totW = eemin( totW, getMaxSize().getWidth() ); + if ( oldW != totW ) + clipEnable(); + } + setInternalPixelsWidth( totW ); } if ( mHeightPolicy == SizePolicy::WrapContent ) { - setInternalPixelsHeight( (int)mTextCache->getTextHeight() + mPaddingPx.Top + - mPaddingPx.Bottom ); + Float totH = (int)mTextCache->getTextHeight() + mPaddingPx.Top + mPaddingPx.Bottom; + if ( !getMaxHeightEq().empty() ) { + Float oldH = totH; + totH = eemin( totH, getMaxSize().getHeight() ); + if ( oldH != totH ) + clipEnable(); + } + setInternalPixelsHeight( totH ); } } @@ -593,7 +605,7 @@ void UITextView::recalculate() { mFontLineCenter = eefloor( (Float)( ( mTextCache->getFont()->getLineSpacing( fontHeight ) - fontHeight ) / 2 ) ); - autoShrink(); + autoWrap(); onAutoSize(); alignFix(); resetSelCache(); @@ -641,7 +653,7 @@ bool UITextView::applyProperty( const StyleSheetProperty& attribute ) { if ( flags & UI_WORD_WRAP ) { mFlags |= UI_WORD_WRAP; flags &= ~UI_WORD_WRAP; - autoShrink(); + autoWrap(); } setFontStyle( flags ); @@ -652,7 +664,7 @@ bool UITextView::applyProperty( const StyleSheetProperty& attribute ) { mFlags |= UI_WORD_WRAP; else mFlags &= ~UI_WORD_WRAP; - autoShrink(); + autoWrap(); break; case PropertyId::TextStrokeWidth: setOutlineThickness( lengthFromValue( attribute ) ); diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 13cf99790..e2260959d 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -415,7 +415,7 @@ Node* UIWidget::setSize( const Sizef& size ) { return UINode::setSize( s ); } -Sizef UIWidget::getCurrentMinSize() { +Sizef UIWidget::getMinSize() { Sizef s; if ( s.x < mMinSize.x ) @@ -438,19 +438,19 @@ Sizef UIWidget::getCurrentMinSize() { return s; } -Sizef UIWidget::getCurrentMaxSize() { +Sizef UIWidget::getMaxSize() { Sizef s; if ( !mMaxWidthEq.empty() ) { Float length = lengthFromValueAsDp( mMaxWidthEq, CSS::PropertyRelativeTarget::ContainingBlockWidth ); - s.x = eemin( s.x, length ); + s.x = eemax( s.x, length ); } if ( !mMaxHeightEq.empty() ) { Float length = lengthFromValueAsDp( mMaxHeightEq, CSS::PropertyRelativeTarget::ContainingBlockHeight ); - s.y = eemin( s.y, length ); + s.y = eemax( s.y, length ); } return s; diff --git a/src/eepp/window/engine.cpp b/src/eepp/window/engine.cpp index 6747b744d..ddc05a08d 100644 --- a/src/eepp/window/engine.cpp +++ b/src/eepp/window/engine.cpp @@ -220,6 +220,10 @@ Uint32 Engine::getWindowCount() const { return mWindows.size(); } +bool Engine::isEngineRunning() { + return existsSingleton() && Engine::instance()->isRunning(); +} + bool Engine::isRunning() const { return NULL != mWindow; } diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index 9b5ab35fe..abab8d205 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -1,8 +1,10 @@ #include "formatterplugin.hpp" +#include "../../scopedop.hpp" #include "../../thirdparty/json.hpp" #include "../../thirdparty/subprocess.h" #include #include +#include #include #include @@ -27,7 +29,13 @@ FormatterPlugin::FormatterPlugin( const std::string& formattersPath, } FormatterPlugin::~FormatterPlugin() { - mClosing = true; + mShuttingDown = true; + + if ( mWorkersCount != 0 ) { + std::unique_lock lock( mWorkMutex ); + mWorkerCondition.wait( lock, [&]() { return mWorkersCount <= 0; } ); + } + for ( auto editor : mEditors ) editor->unregisterPlugin( this ); } @@ -49,7 +57,7 @@ void FormatterPlugin::onRegister( UICodeEditor* editor ) { } void FormatterPlugin::onUnregister( UICodeEditor* editor ) { - if ( mClosing ) + if ( mShuttingDown ) return; mEditors.erase( editor ); } @@ -98,6 +106,16 @@ void FormatterPlugin::load( const std::string& formatterPath ) { } void FormatterPlugin::formatDoc( UICodeEditor* editor ) { + ScopedOp op( + [&]() { + mWorkMutex.lock(); + mWorkersCount++; + }, + [&]() { + mWorkersCount--; + mWorkMutex.unlock(); + mWorkerCondition.notify_all(); + } ); if ( !mReady ) return; @@ -152,8 +170,8 @@ void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& forma const std::string& path ) { std::string cmd( formatter.command ); - String::replaceAll( cmd, "$FILENAME", path ); - std::vector cmdArr = String::split( cmd, ' ' ); + String::replaceAll( cmd, "$FILENAME", "\"" + path + "\"" ); + std::vector cmdArr = String::split( cmd, " " ); std::vector strings; for ( size_t i = 0; i < cmdArr.size(); ++i ) strings.push_back( cmdArr[i].c_str() ); @@ -168,13 +186,14 @@ void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& forma std::string buffer( 1024, '\0' ); std::string data; unsigned bytesRead = 0; + int returnCode; do { bytesRead = subprocess_read_stdout( &subprocess, &buffer[0], buffer.size() ); data += buffer.substr( 0, bytesRead ); - } while ( bytesRead != 0 ); + } while ( bytesRead != 0 && subprocess_alive( &subprocess ) && !mShuttingDown ); - int ret; - subprocess_join( &subprocess, &ret ); + if ( subprocess_alive( &subprocess ) && !mShuttingDown ) + subprocess_join( &subprocess, &returnCode ); subprocess_destroy( &subprocess ); // Log::info( "Formatter result:\n%s", data.c_str() ); @@ -209,4 +228,4 @@ FormatterPlugin::Formatter FormatterPlugin::supportsFormatter( std::shared_ptr mPool; std::vector mFormatters; std::set mEditors; + std::mutex mWorkMutex; + std::condition_variable mWorkerCondition; + Int32 mWorkersCount{ 0 }; bool mAutoFormatOnSave{ false }; - bool mClosing{ false }; + bool mShuttingDown{ false }; bool mReady{ false }; void load( const std::string& formatterPath ); @@ -56,6 +59,6 @@ class FormatterPlugin : public UICodeEditorPlugin { FormatterPlugin::Formatter supportsFormatter( std::shared_ptr doc ); }; -} +} // namespace ecode #endif // ECODE_FORMATTERPLUGIN_HPP diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index fda07e4a9..40cc3e606 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -1,10 +1,12 @@ #include "linterplugin.hpp" +#include "../../scopedop.hpp" #include "../../thirdparty/json.hpp" #include "../../thirdparty/subprocess.h" #include #include #include #include +#include #include #include #include @@ -29,7 +31,13 @@ LinterPlugin::LinterPlugin( const std::string& lintersPath, std::shared_ptr lock( mWorkMutex ); + mWorkerCondition.wait( lock, [&]() { return mWorkersCount <= 0; } ); + } + for ( const auto& editor : mEditors ) { for ( auto listener : editor.second ) editor.first->removeEventListener( listener ); @@ -155,7 +163,7 @@ void LinterPlugin::onRegister( UICodeEditor* editor ) { } void LinterPlugin::onUnregister( UICodeEditor* editor ) { - if ( mClosing ) + if ( mShuttingDown ) return; Lock l( mDocMutex ); TextDocument* doc = mEditorDocs[editor]; @@ -193,11 +201,22 @@ void LinterPlugin::setDelayTime( const Time& delayTime ) { } void LinterPlugin::lintDoc( std::shared_ptr doc ) { + ScopedOp op( + [&]() { + mWorkMutex.lock(); + mWorkersCount++; + }, + [&]() { + mWorkersCount--; + mWorkMutex.unlock(); + mWorkerCondition.notify_all(); + } ); if ( !mReady ) return; auto linter = supportsLinter( doc ); if ( linter.command.empty() ) return; + IOStreamString fileString; if ( doc->isDirty() || !doc->hasFilepath() ) { std::string tmpPath; @@ -230,8 +249,8 @@ void LinterPlugin::runLinter( std::shared_ptr doc, const Linter& l const std::string& path ) { Clock clock; std::string cmd( linter.command ); - String::replaceAll( cmd, "$FILENAME", path ); - std::vector cmdArr = String::split( cmd, ' ' ); + String::replaceAll( cmd, "$FILENAME", "\"" + path + "\"" ); + std::vector cmdArr = String::split( cmd, " " ); std::vector strings; for ( size_t i = 0; i < cmdArr.size(); ++i ) strings.push_back( cmdArr[i].c_str() ); @@ -246,13 +265,14 @@ void LinterPlugin::runLinter( std::shared_ptr doc, const Linter& l std::string buffer( 1024, '\0' ); std::string data; unsigned bytesRead = 0; + int returnCode; do { bytesRead = subprocess_read_stdout( &subprocess, &buffer[0], buffer.size() ); data += buffer.substr( 0, bytesRead ); - } while ( bytesRead != 0 ); + } while ( bytesRead != 0 && subprocess_alive( &subprocess ) && !mShuttingDown ); - int returnCode; - subprocess_join( &subprocess, &returnCode ); + if ( subprocess_alive( &subprocess ) && !mShuttingDown ) + subprocess_join( &subprocess, &returnCode ); subprocess_destroy( &subprocess ); if ( linter.hasNoErrorsExitCode && linter.noErrorsExitCode == returnCode ) { @@ -500,4 +520,4 @@ void LinterPlugin::invalidateEditors( TextDocument* doc ) { } } -} +} // namespace ecode diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index f6f6a05c1..0c2fa1cf7 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include using namespace EE; using namespace EE::System; @@ -81,9 +82,12 @@ class LinterPlugin : public UICodeEditorPlugin { Time mDelayTime{ Seconds( 0.5f ) }; Mutex mDocMutex; Mutex mMatchesMutex; + std::mutex mWorkMutex; + std::condition_variable mWorkerCondition; + Int32 mWorkersCount{ 0 }; bool mReady{ false }; - bool mClosing{ false }; + bool mShuttingDown{ false }; void load( const std::string& lintersPath ); @@ -103,6 +107,6 @@ class LinterPlugin : public UICodeEditorPlugin { std::string getMatchString( const LinterType& type ); }; -} +} // namespace ecode #endif // ECODE_LINTERPLUGIN_HPP diff --git a/src/tools/ecode/scopedop.hpp b/src/tools/ecode/scopedop.hpp new file mode 100644 index 000000000..b1fbf440f --- /dev/null +++ b/src/tools/ecode/scopedop.hpp @@ -0,0 +1,24 @@ +#ifndef ECODE_SCOPEDOP_HPP +#define ECODE_SCOPEDOP_HPP + +#include + +class ScopedOp { + public: + ScopedOp( std::function startOp, + std::function endOp = std::function() ) : + mEndOp( endOp ) { + if ( startOp ) + startOp(); + } + + ~ScopedOp() { + if ( mEndOp ) + mEndOp(); + } + + private: + std::function mEndOp; +}; + +#endif // SCOPEDOP_HPP diff --git a/src/tools/ecode/thirdparty/subprocess.h b/src/tools/ecode/thirdparty/subprocess.h index 696ef0908..6c40b1a04 100644 --- a/src/tools/ecode/thirdparty/subprocess.h +++ b/src/tools/ecode/thirdparty/subprocess.h @@ -432,7 +432,7 @@ int subprocess_create_named_pipe_helper(void **rd, void **wr) { pipeTypeByte | pipeWait, 1, 4096, 4096, SUBPROCESS_NULL, SUBPROCESS_PTR_CAST(LPSECURITY_ATTRIBUTES, &saAttr)); - if (invalidHandleValue == rd) { + if (invalidHandleValue == *rd) { return -1; } @@ -440,7 +440,7 @@ int subprocess_create_named_pipe_helper(void **rd, void **wr) { SUBPROCESS_PTR_CAST(LPSECURITY_ATTRIBUTES, &saAttr), openExisting, fileAttributeNormal, SUBPROCESS_NULL); - if (invalidHandleValue == wr) { + if (invalidHandleValue == *wr) { return -1; } @@ -740,10 +740,7 @@ int subprocess_create_ex(const char *const commandLine[], int options, int stdoutfd[2]; int stderrfd[2]; pid_t child; - extern char **environ; char *const empty_environment[1] = {SUBPROCESS_NULL}; - posix_spawn_file_actions_t actions; - char *const *used_environment; if (subprocess_option_inherit_environment == (options & subprocess_option_inherit_environment)) { @@ -767,9 +764,10 @@ int subprocess_create_ex(const char *const commandLine[], int options, } } - - #if !defined(NO_POSIX_SPAWN) + extern char **environ; + posix_spawn_file_actions_t actions; + char *const *used_environment; if (environment) { #ifdef __clang__