From 3ffc611712af247fe0d98cba99476278bf0df62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 3 Oct 2022 00:32:39 -0300 Subject: [PATCH] TerminalDisplay: improve middle mouse click paste action. UIAbstractTableView: Improved auto columns width. ecode: Improving plugins structure. New linters and formatters json config format. --- bin/assets/plugins/formatters.json | 71 ++++---- bin/assets/plugins/linters.json | 151 +++++++++--------- .../eepp/ui/abstract/uiabstracttableview.hpp | 6 + include/eepp/ui/doc/textdocument.hpp | 2 + src/eepp/ui/abstract/uiabstracttableview.cpp | 14 +- src/eepp/ui/doc/textdocument.cpp | 4 + .../src/eterm/terminal/terminaldisplay.cpp | 2 +- src/modules/eterm/src/eterm/ui/uiterminal.cpp | 1 - .../autocomplete/autocompleteplugin.hpp | 6 +- .../plugins/formatter/formatterplugin.cpp | 138 +++++++++++----- .../plugins/formatter/formatterplugin.hpp | 16 +- .../ecode/plugins/linter/linterplugin.cpp | 24 ++- .../ecode/plugins/linter/linterplugin.hpp | 6 +- src/tools/ecode/plugins/pluginmanager.cpp | 4 +- src/tools/ecode/plugins/pluginmanager.hpp | 30 +++- 15 files changed, 308 insertions(+), 167 deletions(-) diff --git a/bin/assets/plugins/formatters.json b/bin/assets/plugins/formatters.json index 582e61f9b..7cdcee000 100644 --- a/bin/assets/plugins/formatters.json +++ b/bin/assets/plugins/formatters.json @@ -1,34 +1,39 @@ -[ - { - "file_patterns": ["%.js$", "%.ts$"], - "command": "prettier $FILENAME" +{ + "config": { + "auto_format_on_save": false }, - { - "file_patterns": ["%.cpp$", "%.h$", "%.hpp$"], - "command": "clang-format --style=file $FILENAME" - }, - { - "file_patterns": ["%.py$", "%.pyw$"], - "command": "black $FILENAME", - "type": "inplace" - }, - { - "file_patterns": ["%.kt$"], - "command": "ktlint -F $FILENAME", - "type": "inplace" - }, - { - "file_patterns": ["%.json$", "%.cson$"], - "command": "jq -M --tab . $FILENAME" - }, - { - "file_patterns": ["%.xml", "%.html?$"], - "command": "xml", - "type": "native" - }, - { - "file_patterns": ["%.css"], - "command": "css", - "type": "native" - } -] + "formatters": [ + { + "file_patterns": ["%.js$", "%.ts$"], + "command": "prettier $FILENAME" + }, + { + "file_patterns": ["%.cpp$", "%.h$", "%.hpp$"], + "command": "clang-format --style=file $FILENAME" + }, + { + "file_patterns": ["%.py$", "%.pyw$"], + "command": "black $FILENAME", + "type": "inplace" + }, + { + "file_patterns": ["%.kt$"], + "command": "ktlint -F $FILENAME", + "type": "inplace" + }, + { + "file_patterns": ["%.json$", "%.cson$"], + "command": "jq -M --tab . $FILENAME" + }, + { + "file_patterns": ["%.xml", "%.html?$"], + "command": "xml", + "type": "native" + }, + { + "file_patterns": ["%.css"], + "command": "css", + "type": "native" + } + ] +} \ No newline at end of file diff --git a/bin/assets/plugins/linters.json b/bin/assets/plugins/linters.json index 938fb96e1..455553bd5 100644 --- a/bin/assets/plugins/linters.json +++ b/bin/assets/plugins/linters.json @@ -1,74 +1,79 @@ -[ - { - "file_patterns": ["%.php$"], - "warning_pattern": "[%a ]+:%s+(.*)%s+in%s.*on%sline%s+(%d+)", - "warning_pattern_order": { "line": 2, "col": 0, "message": 1 }, - "command": "php -l $FILENAME" +{ + "config": { + "delay_time": "0.5s" }, - { - "file_patterns": ["%.json$"], - "warning_pattern": "parse%s(%w*):%s(.*)at%sline%s(%d*),%scolumn%s(%d*)", - "warning_pattern_order": { "line": 3, "col": 4, "message": 2, "type": 1 }, - "command": "jq -e . $FILENAME", - "expected_exitcodes": [1, 2, 3, 4], - "no_errors_exit_code": 0, - "use_tmp_folder": true - }, - { - "file_patterns": ["%.js$", "%.ts$"], - "warning_pattern": "[^:]:(%d+):(%d+): ([^%[]+)%[([^\n]+)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 }, - "command": "eslint --no-ignore --format unix $FILENAME" - }, - { - "file_patterns": ["%.lua$"], - "warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)", - "command": "luacheck $FILENAME --formatter=plain -g --no-max-line-length" - }, - { - "file_patterns": ["%.py$"], - "warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)", - "command": "pycodestyle --ignore=E402 $FILENAME" - }, - { - "file_patterns": ["%.sh$"], - "warning_pattern": "[^:]:(%d+):(%d+):%s?([^%s]*)([^\n]*)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, - "command": "shellcheck -f gcc $FILENAME" - }, - { - "file_patterns": ["%.sol$"], - "warning_pattern": "(%d+):(%d+)%s.(%w*)%s.([^\n]*)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, - "command": "solhint $FILENAME" - }, - { - "file_patterns": ["%.cpp$", "%.hpp$", "%.cxx$", "%.hxx$"], - "warning_pattern": "$FILENAME:(%d+):(%d+):%s?([^%s]*)([^\n]*)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, - "command": "cppcheck --language=c++ --enable=all --template=gcc $FILENAME" - }, - { - "file_patterns": ["%.kt$"], - "warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 }, - "command": "ktlint $FILENAME" - }, - { - "file_patterns": ["%.zig$"], - "warning_pattern": "[^%s:]:(%d+):(%d+):[%s]?(%w*):([^\n]*)", - "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, - "command": "zig ast-check $FILENAME", - "deduplicate": true, - "expected_exitcodes": [0, 1] - }, - { - "file_patterns": ["%.nim$", "%.nims$"], - "warning_pattern": "$FILENAME%((%d+), (%d+)%)%s(%w*):%s([^\n]+[^/]*)", - "command": "nim --listfullpaths --stdout check $FILENAME", - "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, - "deduplicate": true, - "expected_exitcodes": [0, 1], - "use_tmp_folder": true - } -] + "linters": [ + { + "file_patterns": ["%.php$"], + "warning_pattern": "[%a ]+:%s+(.*)%s+in%s.*on%sline%s+(%d+)", + "warning_pattern_order": { "line": 2, "col": 0, "message": 1 }, + "command": "php -l $FILENAME" + }, + { + "file_patterns": ["%.json$"], + "warning_pattern": "parse%s(%w*):%s(.*)at%sline%s(%d*),%scolumn%s(%d*)", + "warning_pattern_order": { "line": 3, "col": 4, "message": 2, "type": 1 }, + "command": "jq -e . $FILENAME", + "expected_exitcodes": [1, 2, 3, 4], + "no_errors_exit_code": 0, + "use_tmp_folder": true + }, + { + "file_patterns": ["%.js$", "%.ts$"], + "warning_pattern": "[^:]:(%d+):(%d+): ([^%[]+)%[([^\n]+)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 }, + "command": "eslint --no-ignore --format unix $FILENAME" + }, + { + "file_patterns": ["%.lua$"], + "warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)", + "command": "luacheck $FILENAME --formatter=plain -g --no-max-line-length" + }, + { + "file_patterns": ["%.py$"], + "warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)", + "command": "pycodestyle --ignore=E402 $FILENAME" + }, + { + "file_patterns": ["%.sh$"], + "warning_pattern": "[^:]:(%d+):(%d+):%s?([^%s]*)([^\n]*)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, + "command": "shellcheck -f gcc $FILENAME" + }, + { + "file_patterns": ["%.sol$"], + "warning_pattern": "(%d+):(%d+)%s.(%w*)%s.([^\n]*)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, + "command": "solhint $FILENAME" + }, + { + "file_patterns": ["%.cpp$", "%.hpp$", "%.cxx$", "%.hxx$"], + "warning_pattern": "$FILENAME:(%d+):(%d+):%s?([^%s]*)([^\n]*)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, + "command": "cppcheck --language=c++ --enable=all --template=gcc $FILENAME" + }, + { + "file_patterns": ["%.kt$"], + "warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 }, + "command": "ktlint $FILENAME" + }, + { + "file_patterns": ["%.zig$"], + "warning_pattern": "[^%s:]:(%d+):(%d+):[%s]?(%w*):([^\n]*)", + "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, + "command": "zig ast-check $FILENAME", + "deduplicate": true, + "expected_exitcodes": [0, 1] + }, + { + "file_patterns": ["%.nim$", "%.nims$"], + "warning_pattern": "$FILENAME%((%d+), (%d+)%)%s(%w*):%s([^\n]+[^/]*)", + "command": "nim --listfullpaths --stdout check $FILENAME", + "warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 }, + "deduplicate": true, + "expected_exitcodes": [0, 1], + "use_tmp_folder": true + } + ] +} \ No newline at end of file diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index c5d797bb9..40ff4e522 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -105,6 +105,11 @@ class EE_API UIAbstractTableView : public UIAbstractView { void setSingleClickNavigation( bool singleClickNavigation ); + bool getFitAllColumnsToWidget() const; + + /** Tries to make all columns visible in the widget content. */ + void setFitAllColumnsToWidget( bool fitAllColumnsToWidget ); + protected: friend class EE::UI::UITableHeaderColumn; @@ -129,6 +134,7 @@ class EE_API UIAbstractTableView : public UIAbstractView { bool mAutoColumnsWidth{ false }; bool mRowSearchByName{ true }; bool mSingleClickNavigation{ false }; + bool mFitAllColumnsToWidget{ false }; Action* mSearchTextAction{ nullptr }; std::string mSearchText; size_t mMainColumn{ 0 }; diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index af3889368..5a2aaffad 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -294,6 +294,8 @@ class EE_API TextDocument { bool hasCommand( const std::string& command ); + bool removeCommand( const std::string& command ); + TextRange find( String text, TextPosition from = { 0, 0 }, const bool& caseSensitive = true, const bool& wholeWord = false, const FindReplaceType& type = FindReplaceType::Normal, diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 45c12ac5e..bc236d8e1 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -140,7 +140,7 @@ void UIAbstractTableView::createOrUpdateColumns() { ? contentWidth - usedWidth : mainColMaxWidth; usedWidth += columnData( mMainColumn ).width; - if ( usedWidth > contentWidth ) { + if ( mFitAllColumnsToWidget && usedWidth > contentWidth ) { size_t longestCol = 0; Float longestColWidth = columnData( 0 ).width; for ( size_t col = 1; col < count; col++ ) { @@ -149,7 +149,9 @@ void UIAbstractTableView::createOrUpdateColumns() { longestColWidth = columnData( col ).width; } } - columnData( longestCol ).width = contentWidth - ( usedWidth - longestColWidth ); + longestColWidth = contentWidth - ( usedWidth - longestColWidth ); + if ( longestColWidth > 0 ) + columnData( longestCol ).width = longestColWidth; } } @@ -697,4 +699,12 @@ void UIAbstractTableView::setSingleClickNavigation( bool singleClickNavigation ) } } +bool UIAbstractTableView::getFitAllColumnsToWidget() const { + return mFitAllColumnsToWidget; +} + +void UIAbstractTableView::setFitAllColumnsToWidget( bool fitAllColumnsToWidget ) { + mFitAllColumnsToWidget = fitAllColumnsToWidget; +} + }}} // namespace EE::UI::Abstract diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index e788277e5..1a53511f2 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -1466,6 +1466,10 @@ bool TextDocument::hasCommand( const std::string& command ) { return mCommands.find( command ) != mCommands.end(); } +bool TextDocument::removeCommand( const std::string& command ) { + return mCommands.erase( command ) > 0; +} + static std::pair findType( const String& str, const String& findStr, const TextDocument::FindReplaceType& type ) { switch ( type ) { diff --git a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp index 7d6a384a8..491619aa5 100644 --- a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp +++ b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp @@ -798,7 +798,7 @@ void TerminalDisplay::onMouseDown( const Vector2i& pos, const Uint32& flags ) { if ( !mAlreadyClickedMButton ) { mAlreadyClickedMButton = true; auto selection = mTerminal->getSelection(); - if ( !selection.empty() ) { + if ( !selection.empty() && selection != "\n" ) { for ( auto& chr : selection ) onTextInput( chr ); } else { diff --git a/src/modules/eterm/src/eterm/ui/uiterminal.cpp b/src/modules/eterm/src/eterm/ui/uiterminal.cpp index ddf3f0fcf..ea5ef4646 100644 --- a/src/modules/eterm/src/eterm/ui/uiterminal.cpp +++ b/src/modules/eterm/src/eterm/ui/uiterminal.cpp @@ -92,7 +92,6 @@ UITerminal::UITerminal( const std::shared_ptr& terminalDisplay [&] { mTerm->action( TerminalShortcutAction::FONTSIZE_SHRINK ); } ); setCommand( "terminal-paste", [&] { mTerm->action( TerminalShortcutAction::PASTE ); } ); setCommand( "terminal-copy", [&] { mTerm->action( TerminalShortcutAction::COPY ); } ); - setCommand( "terminal-paste", [&] { mTerm->action( TerminalShortcutAction::PASTE ); } ); setCommand( "terminal-open-link", [&] { Engine::instance()->openURI( mTerm->getTerminal()->getSelection() ); } ); subscribeScheduledUpdate(); diff --git a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp index 2382d1076..7d6d49ac1 100644 --- a/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp +++ b/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp @@ -20,10 +20,12 @@ class AutoCompletePlugin : public UICodeEditorPlugin { typedef std::unordered_set SymbolsList; static PluginDefinition Definition() { - return { "autocomplete", "Auto Complete", + return { "autocomplete", + "Auto Complete", "Auto complete shows the completion popup as you type, so you can fill " "in long words by typing only a few characters.", - AutoCompletePlugin::New }; + AutoCompletePlugin::New, + { 0, 1, 0 } }; } static UICodeEditorPlugin* New( const PluginManager* pluginManager ); diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index 1e486d0ad..a73f10273 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -43,8 +43,10 @@ FormatterPlugin::~FormatterPlugin() { mWorkerCondition.wait( lock, [&]() { return mWorkersCount <= 0; } ); } - for ( auto editor : mEditors ) + for ( auto editor : mEditors ) { + editor->getDocument().removeCommand( "format-doc" ); editor->unregisterPlugin( this ); + } } void FormatterPlugin::onRegister( UICodeEditor* editor ) { @@ -87,53 +89,103 @@ void FormatterPlugin::unregisterNativeFormatter( const std::string& cmd ) { mNativeFormatters.erase( cmd ); } +size_t FormatterPlugin::formatterFilePatternPosition( const std::vector& patterns ) { + for ( size_t i = 0; i < mFormatters.size(); ++i ) { + for ( const std::string& filePattern : mFormatters[i].files ) { + for ( const std::string& pattern : patterns ) { + if ( filePattern == pattern ) { + return i; + } + } + } + } + return std::string::npos; +} + +void FormatterPlugin::loadFormatterConfig( const std::string& path ) { + std::string data; + if ( !FileSystem::fileGet( path, data ) ) + return; + json j = json::parse( data, nullptr, true, true ); + + if ( j.contains( "config" ) ) { + auto& config = j["config"]; + if ( config.contains( "auto_format_on_save" ) ) + setAutoFormatOnSave( config["auto_format_on_save"].get() ); + } + + if ( !j.contains( "formatters" ) ) + return; + + auto& formatters = j["formatters"]; + for ( auto& obj : formatters ) { + Formatter formatter; + auto fp = obj["file_patterns"]; + + for ( auto& pattern : fp ) + formatter.files.push_back( pattern.get() ); + + formatter.command = obj["command"].get(); + + if ( obj.contains( "type" ) ) { + std::string typeStr( obj["type"].get() ); + String::toLowerInPlace( typeStr ); + String::trimInPlace( typeStr ); + if ( "native" == typeStr ) { + formatter.type = FormatterType::Native; + if ( mNativeFormatters.find( formatter.command ) == mNativeFormatters.end() ) { + Log::error( "Requested native formatter: '%s' does not exists.", + formatter.command.c_str() ); + continue; + } + } else { + formatter.type = + "inplace" == typeStr ? FormatterType::Inplace : FormatterType::Output; + } + } + + // If the file pattern is repeated, we will overwrite the previous linter. + // The previous linter should be the "default" linter that comes with ecode. + size_t pos = formatterFilePatternPosition( formatter.files ); + if ( pos != std::string::npos ) { + mFormatters[pos] = formatter; + } else { + mFormatters.emplace_back( std::move( formatter ) ); + } + } +} + void FormatterPlugin::load( const PluginManager* pluginManager ) { registerNativeFormatters(); + std::vector paths; std::string path( pluginManager->getResourcesPath() + "plugins/formatters.json" ); - if ( FileSystem::fileExists( pluginManager->getPluginsPath() + "formatters.json" ) ) - path = pluginManager->getPluginsPath() + "formatter.json"; - if ( !FileSystem::fileExists( path ) ) - return; - try { - std::ifstream stream( path ); - json j; - stream >> j; - - for ( auto& obj : j ) { - Formatter formatter; - auto fp = obj["file_patterns"]; - - for ( auto& pattern : fp ) - formatter.files.push_back( pattern.get() ); - - formatter.command = obj["command"].get(); - - if ( obj.contains( "type" ) ) { - std::string typeStr( obj["type"].get() ); - String::toLowerInPlace( typeStr ); - String::trimInPlace( typeStr ); - if ( "native" == typeStr ) { - formatter.type = FormatterType::Native; - if ( mNativeFormatters.find( formatter.command ) == mNativeFormatters.end() ) { - Log::error( "Requested native formatter: '%s' does not exists.", - formatter.command.c_str() ); - continue; - } - } else { - formatter.type = - "inplace" == typeStr ? FormatterType::Inplace : FormatterType::Output; - } - } - - mFormatters.emplace_back( std::move( formatter ) ); - } - - mReady = true; - } catch ( json::exception& e ) { - mReady = false; - Log::error( "Parsing formatter failed:\n%s", e.what() ); + if ( FileSystem::fileExists( path ) ) + paths.emplace_back( path ); + path = pluginManager->getPluginsPath() + "formatters.json"; + if ( FileSystem::fileExists( path ) || + FileSystem::fileWrite( path, "{\n\"config\":{},\n\"formatters\":[]\n}\n" ) ) { + mConfigPath = path; + paths.emplace_back( path ); } + if ( paths.empty() ) + return; + for ( const auto& path : paths ) { + try { + loadFormatterConfig( path ); + } catch ( json::exception& e ) { + Log::error( "Parsing formatter \"%s\" failed:\n%s", path.c_str(), e.what() ); + } + } + mReady = !mFormatters.empty(); +} + +bool FormatterPlugin::hasFileConfig() { + return !mConfigPath.empty(); +} + +std::string FormatterPlugin::getFileConfigPath() { + return mConfigPath; } void FormatterPlugin::formatDoc( UICodeEditor* editor ) { diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.hpp b/src/tools/ecode/plugins/formatter/formatterplugin.hpp index ae2468bc9..2348c332f 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.hpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.hpp @@ -22,8 +22,11 @@ class FormatterPlugin : public UICodeEditorPlugin { }; static PluginDefinition Definition() { - return { "autoformatter", "Auto Formatter", "Enables the code formatter/prettifier plugin.", - FormatterPlugin::New }; + return { "autoformatter", + "Auto Formatter", + "Enables the code formatter/prettifier plugin.", + FormatterPlugin::New, + { 0, 1, 0 } }; } static UICodeEditorPlugin* New( const PluginManager* pluginManager ); @@ -50,6 +53,10 @@ class FormatterPlugin : public UICodeEditorPlugin { void unregisterNativeFormatter( const std::string& cmd ); + bool hasFileConfig(); + + std::string getFileConfigPath(); + protected: enum class FormatterType { Inplace, Output, Native }; @@ -67,6 +74,7 @@ class FormatterPlugin : public UICodeEditorPlugin { std::map> mNativeFormatters; Int32 mWorkersCount{ 0 }; + std::string mConfigPath; bool mAutoFormatOnSave{ false }; bool mShuttingDown{ false }; @@ -76,10 +84,14 @@ class FormatterPlugin : public UICodeEditorPlugin { void load( const PluginManager* pluginManager ); + void loadFormatterConfig( const std::string& path ); + void formatDoc( UICodeEditor* editor ); void runFormatter( UICodeEditor* editor, const Formatter& formatter, const std::string& path ); + size_t formatterFilePatternPosition( const std::vector& patterns ); + FormatterPlugin::Formatter supportsFormatter( std::shared_ptr doc ); void registerNativeFormatters(); diff --git a/src/tools/ecode/plugins/linter/linterplugin.cpp b/src/tools/ecode/plugins/linter/linterplugin.cpp index 96dcb5b61..0fb45d2ef 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.cpp +++ b/src/tools/ecode/plugins/linter/linterplugin.cpp @@ -72,11 +72,24 @@ size_t LinterPlugin::linterFilePatternPosition( const std::vector& } void LinterPlugin::loadLinterConfig( const std::string& path ) { - std::ifstream stream( path ); - json j; - stream >> j; + std::string data; + if ( !FileSystem::fileGet( path, data ) ) + return; + json j = json::parse( data, nullptr, true, true ); - for ( auto& obj : j ) { + if ( j.contains( "config" ) ) { + auto& config = j["config"]; + if ( config.contains( "delay_time" ) ) { + Time time( Time::fromString( config["delay_time"].get() ) ); + setDelayTime( time ); + } + } + + if ( !j.contains( "linters" ) ) + return; + + auto& linters = j["linters"]; + for ( auto& obj : linters ) { Linter linter; if ( !obj.contains( "file_patterns" ) || !obj.contains( "warning_pattern" ) || !obj.contains( "command" ) ) @@ -153,7 +166,8 @@ void LinterPlugin::load( const PluginManager* pluginManager ) { if ( FileSystem::fileExists( path ) ) paths.emplace_back( path ); path = pluginManager->getPluginsPath() + "linters.json"; - if ( FileSystem::fileExists( path ) || FileSystem::fileWrite( path, "[]\n" ) ) { + if ( FileSystem::fileExists( path ) || + FileSystem::fileWrite( path, "{\n\"config\":{},\n\"linters\":[]\n}\n" ) ) { mConfigPath = path; paths.emplace_back( path ); } diff --git a/src/tools/ecode/plugins/linter/linterplugin.hpp b/src/tools/ecode/plugins/linter/linterplugin.hpp index 40b90b595..c3a681fd4 100644 --- a/src/tools/ecode/plugins/linter/linterplugin.hpp +++ b/src/tools/ecode/plugins/linter/linterplugin.hpp @@ -45,10 +45,12 @@ struct LinterMatch { class LinterPlugin : public UICodeEditorPlugin { public: static PluginDefinition Definition() { - return { "linter", "Linter", + return { "linter", + "Linter", "Use static code analysis tool used to flag programming errors, bugs, " "stylistic errors, and suspicious constructs.", - LinterPlugin::New }; + LinterPlugin::New, + { 0, 1, 0 } }; } static UICodeEditorPlugin* New( const PluginManager* pluginManager ); diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index 15ac7b3d9..38d5c5df2 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -115,7 +115,7 @@ Variant PluginsModel::data( const ModelIndex& index, ModelRole role ) const { return {}; switch ( index.column() ) { case Columns::Version: - return Variant( def->versionString.c_str() ); + return Variant( def->version.getVersionString().c_str() ); case Columns::Description: return Variant( def->description.c_str() ); case Columns::Title: @@ -214,6 +214,8 @@ UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager, tv->setColumnsVisible( { PluginsModel::Title, PluginsModel::Description, PluginsModel::Version } ); tv->setAutoColumnsWidth( true ); + tv->setFitAllColumnsToWidget( true ); + tv->setMainColumn( PluginsModel::Description ); prefs->addEventListener( Event::MouseClick, [tv, manager, loadFileCb]( const Event* event ) { if ( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK && !tv->getSelection().isEmpty() ) { diff --git a/src/tools/ecode/plugins/pluginmanager.hpp b/src/tools/ecode/plugins/pluginmanager.hpp index 13980945c..e0874998b 100644 --- a/src/tools/ecode/plugins/pluginmanager.hpp +++ b/src/tools/ecode/plugins/pluginmanager.hpp @@ -19,17 +19,43 @@ class PluginManager; typedef std::function PluginCreatorFn; +struct PluginVersion { + PluginVersion() {} + + PluginVersion( Uint8 major, Uint8 minor, Uint8 patch ) : + major( major ), + minor( minor ), + patch( patch ), + string( String::format( "%d.%d.%d", major, minor, patch ) ) {} + + Uint8 major; /**< major version */ + Uint8 minor; /**< minor version */ + Uint8 patch; /**< update version */ + std::string string; + + Uint32 getVersion() const { return major * 1000 + minor * 100 + patch; } + + const std::string& getVersionString() const { return string; } +}; + struct PluginDefinition { std::string id; std::string name; std::string description; PluginCreatorFn creatorFn; - int versionNumber{ 0 }; - std::string versionString{ "0" }; + PluginVersion version; }; class PluginManager { public: + static constexpr int versionNumber( int major, int minor, int patch ) { + return ( (major)*1000 + (minor)*100 + ( patch ) ); + } + + static std::string versionString( int major, int minor, int patch ) { + return String::format( "%d.%d.%.d", major, minor, patch ); + } + PluginManager( const std::string& resourcesPath, const std::string& pluginsPath, std::shared_ptr pool );