diff --git a/bin/assets/plugins/formatters.json b/bin/assets/plugins/formatters.json index da2ff2375..f63bf367a 100644 --- a/bin/assets/plugins/formatters.json +++ b/bin/assets/plugins/formatters.json @@ -20,5 +20,10 @@ { "file_patterns": ["%.json$", "%.cson$"], "command": "jq -M --tab . $FILENAME" + }, + { + "file_patterns": ["%.xml", "%.html?$"], + "command": "xml", + "type": "native" } ] diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index bd918f58e..3b1be3ce7 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -465,7 +465,7 @@ void App::onFileDropped( String file ) { tab = d.first; } } - loadFileFromPath( file, true, codeEditor, [tab]( UICodeEditor*, const std::string& ) { + loadFileFromPath( file, false, codeEditor, [tab]( UICodeEditor*, const std::string& ) { if ( tab ) tab->getTabWidget()->setTabSelected( tab ); } ); diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.cpp b/src/tools/ecode/plugins/formatter/formatterplugin.cpp index 81f21905c..e70992f1d 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.cpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.cpp @@ -7,6 +7,8 @@ #include #include #include +#define PUGIXML_HEADER_ONLY +#include using json = nlohmann::json; @@ -70,7 +72,19 @@ void FormatterPlugin::setAutoFormatOnSave( bool autoFormatOnSave ) { mAutoFormatOnSave = autoFormatOnSave; } +void FormatterPlugin::registerNativeFormatter( + const std::string& cmd, + const std::function& nativeFormatter ) { + mNativeFormatters[cmd] = nativeFormatter; +} + +void FormatterPlugin::unregisterNativeFormatter( const std::string& cmd ) { + mNativeFormatters.erase( cmd ); +} + void FormatterPlugin::load( const std::string& formatterPath ) { + registerNativeFormatters(); + if ( !FileSystem::fileExists( formatterPath ) ) return; try { @@ -91,8 +105,17 @@ void FormatterPlugin::load( const std::string& formatterPath ) { std::string typeStr( obj["type"].get() ); String::toLowerInPlace( typeStr ); String::trimInPlace( typeStr ); - formatter.type = - "inplace" == typeStr ? FormatterType::Inplace : FormatterType::Output; + 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 ) ); @@ -168,6 +191,19 @@ void FormatterPlugin::formatDoc( UICodeEditor* editor ) { void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& formatter, const std::string& path ) { + if ( formatter.type == FormatterType::Native ) { + NativeFormatterResult res = mNativeFormatters[formatter.command]( path ); + if ( !res.success ) + return; + editor->runOnMainThread( [&, res, editor]() { + std::shared_ptr doc = editor->getDocumentRef(); + TextPosition pos = doc->getSelection().start(); + doc->selectAll(); + doc->textInput( res.result ); + doc->setSelection( pos ); + } ); + return; + } std::string cmd( formatter.command ); String::replaceAll( cmd, "$FILENAME", "\"" + path + "\"" ); @@ -233,4 +269,31 @@ FormatterPlugin::Formatter FormatterPlugin::supportsFormatter( std::shared_ptr NativeFormatterResult { + struct xml_string_writer : pugi::xml_writer { + std::string result; + + virtual void write( const void* data, size_t size ) { + result.append( static_cast( data ), size ); + } + }; + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file( file.c_str() ); + + if ( result ) { + xml_string_writer str; + doc.save( str ); + return { true, str.result }; + } else { + Log::error( "Couldn't load: %s", file.c_str() ); + Log::error( "Error description: %s", result.description() ); + Log::error( "Error offset: %d", result.offset ); + return { false, "" }; + } + }; +} + } // namespace ecode diff --git a/src/tools/ecode/plugins/formatter/formatterplugin.hpp b/src/tools/ecode/plugins/formatter/formatterplugin.hpp index fda3a1e3a..11dc613b6 100644 --- a/src/tools/ecode/plugins/formatter/formatterplugin.hpp +++ b/src/tools/ecode/plugins/formatter/formatterplugin.hpp @@ -14,6 +14,11 @@ namespace ecode { class FormatterPlugin : public UICodeEditorPlugin { public: + struct NativeFormatterResult { + bool success; + std::string result; + }; + FormatterPlugin( const std::string& formatterPath, std::shared_ptr pool ); virtual ~FormatterPlugin(); @@ -30,8 +35,13 @@ class FormatterPlugin : public UICodeEditorPlugin { void setAutoFormatOnSave( bool autoFormatOnSave ); + void registerNativeFormatter( + const std::string& cmd, + const std::function& nativeFormatter ); + + void unregisterNativeFormatter( const std::string& cmd ); protected: - enum class FormatterType { Inplace, Output }; + enum class FormatterType { Inplace, Output, Native }; struct Formatter { std::vector files; @@ -44,6 +54,8 @@ class FormatterPlugin : public UICodeEditorPlugin { std::set mEditors; std::mutex mWorkMutex; std::condition_variable mWorkerCondition; + std::map> + mNativeFormatters; Int32 mWorkersCount{ 0 }; bool mAutoFormatOnSave{ false }; @@ -57,6 +69,8 @@ class FormatterPlugin : public UICodeEditorPlugin { void runFormatter( UICodeEditor* editor, const Formatter& formatter, const std::string& path ); FormatterPlugin::Formatter supportsFormatter( std::shared_ptr doc ); + + void registerNativeFormatters(); }; } // namespace ecode