ecode: Added --health command line parameter to get a health status (like helix editor).

This commit is contained in:
Martín Lucas Golini
2023-02-15 21:47:42 -03:00
parent 004fda780c
commit ee64d434f7
23 changed files with 9638 additions and 49 deletions

View File

@@ -24,16 +24,24 @@ namespace ecode {
#endif
UICodeEditorPlugin* FormatterPlugin::New( PluginManager* pluginManager ) {
return eeNew( FormatterPlugin, ( pluginManager ) );
return eeNew( FormatterPlugin, ( pluginManager, false ) );
}
FormatterPlugin::FormatterPlugin( PluginManager* pluginManager ) :
UICodeEditorPlugin* FormatterPlugin::NewSync( PluginManager* pluginManager ) {
return eeNew( FormatterPlugin, ( pluginManager, true ) );
}
FormatterPlugin::FormatterPlugin( PluginManager* pluginManager, bool sync ) :
mManager( pluginManager ), mPool( pluginManager->getThreadPool() ) {
if ( sync ) {
load( pluginManager );
} else {
#if FORMATTER_THREADED
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
#else
load( pluginManager );
load( pluginManager );
#endif
}
mManager->subscribeMessages( this, [&]( const PluginMessage& msg ) -> PluginRequestHandle {
return processResponse( msg );
} );
@@ -180,6 +188,18 @@ void FormatterPlugin::loadFormatterConfig( const std::string& path, bool updateC
Formatter formatter;
auto fp = obj["file_patterns"];
if ( obj.contains( "language" ) ) {
if ( obj["language"].is_array() ) {
const auto& langs = obj["language"];
for ( const auto& lang : langs ) {
if ( lang.is_string() )
formatter.languages.push_back( lang.get<std::string>() );
}
} else if ( obj["language"].is_string() ) {
formatter.languages.push_back( obj["language"].get<std::string>() );
}
}
for ( auto& pattern : fp )
formatter.files.push_back( pattern.get<std::string>() );
@@ -263,6 +283,33 @@ bool FormatterPlugin::onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* me
return false;
}
const std::vector<FormatterPlugin::Formatter>& FormatterPlugin::getFormatters() const {
return mFormatters;
}
FormatterPlugin::Formatter
FormatterPlugin::getFormatterForLang( const std::string& lang,
const std::vector<std::string>& extensions ) {
for ( const auto& formatter : mFormatters ) {
for ( const auto& clang : formatter.languages ) {
if ( clang == lang ) {
return formatter;
}
}
if ( !formatter.files.empty() ) {
for ( const auto& file : formatter.files ) {
for ( const auto& ext : extensions ) {
if ( ext == file ) {
return formatter;
}
}
}
}
}
return {};
}
void FormatterPlugin::formatDoc( UICodeEditor* editor ) {
ScopedOp op(
[&]() {

View File

@@ -15,22 +15,31 @@ namespace ecode {
class FormatterPlugin : public UICodeEditorPlugin {
public:
enum class FormatterType { Inplace, Output, Native };
struct NativeFormatterResult {
bool success;
std::string result;
std::string err;
};
struct Formatter {
std::vector<std::string> files;
std::string command;
FormatterType type{ FormatterType::Output };
std::vector<std::string> languages{};
};
static PluginDefinition Definition() {
return { "autoformatter",
"Auto Formatter",
"Enables the code formatter/prettifier plugin.",
FormatterPlugin::New,
{ 0, 1, 0 } };
return {
"autoformatter", "Auto Formatter", "Enables the code formatter/prettifier plugin.",
FormatterPlugin::New, { 0, 1, 0 }, FormatterPlugin::NewSync };
}
static UICodeEditorPlugin* New( PluginManager* pluginManager );
static UICodeEditorPlugin* NewSync( PluginManager* pluginManager );
virtual ~FormatterPlugin();
std::string getId() { return Definition().id; }
@@ -62,15 +71,11 @@ class FormatterPlugin : public UICodeEditorPlugin {
virtual bool onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* menu,
const Vector2i& position, const Uint32& flags );
const std::vector<Formatter>& getFormatters() const;
Formatter getFormatterForLang( const std::string& lang, const std::vector<std::string>& ext );
protected:
enum class FormatterType { Inplace, Output, Native };
struct Formatter {
std::vector<std::string> files;
std::string command;
FormatterType type{ FormatterType::Output };
};
PluginManager* mManager{ nullptr };
std::shared_ptr<ThreadPool> mPool;
std::vector<Formatter> mFormatters;
@@ -90,7 +95,7 @@ class FormatterPlugin : public UICodeEditorPlugin {
bool mShuttingDown{ false };
bool mReady{ false };
FormatterPlugin( PluginManager* pluginManager );
FormatterPlugin( PluginManager* pluginManager, bool sync );
void load( PluginManager* pluginManager );

View File

@@ -23,16 +23,24 @@ namespace ecode {
#endif
UICodeEditorPlugin* LinterPlugin::New( PluginManager* pluginManager ) {
return eeNew( LinterPlugin, ( pluginManager ) );
return eeNew( LinterPlugin, ( pluginManager, false ) );
}
LinterPlugin::LinterPlugin( PluginManager* pluginManager ) :
UICodeEditorPlugin* LinterPlugin::NewSync( PluginManager* pluginManager ) {
return eeNew( LinterPlugin, ( pluginManager, true ) );
}
LinterPlugin::LinterPlugin( PluginManager* pluginManager, bool sync ) :
mManager( pluginManager ), mPool( pluginManager->getThreadPool() ) {
if ( sync ) {
load( pluginManager );
} else {
#if LINTER_THREADED
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
#else
load( pluginManager );
load( pluginManager );
#endif
}
}
LinterPlugin::~LinterPlugin() {
@@ -159,6 +167,19 @@ void LinterPlugin::loadLinterConfig( const std::string& path, bool updateConfigF
continue;
Linter linter;
if ( obj.contains( "language" ) ) {
if ( obj["language"].is_array() ) {
const auto& langs = obj["language"];
for ( const auto& lang : langs ) {
if ( lang.is_string() )
linter.languages.push_back( lang.get<std::string>() );
}
} else if ( obj["language"].is_string() ) {
linter.languages.push_back( obj["language"].get<std::string>() );
}
}
auto fp = obj["file_patterns"];
for ( auto& pattern : fp )
@@ -448,6 +469,32 @@ void LinterPlugin::setErrorLens( bool errorLens ) {
mErrorLens = errorLens;
}
const std::vector<Linter>& LinterPlugin::getLinters() const {
return mLinters;
}
Linter LinterPlugin::getLinterForLang( const std::string& lang,
const std::vector<std::string>& extensions ) {
for ( const auto& linter : mLinters ) {
for ( const auto& clang : linter.languages ) {
if ( clang == lang ) {
return linter;
}
}
if ( !linter.files.empty() ) {
for ( const auto& file : linter.files ) {
for ( const auto& ext : extensions ) {
if ( ext == file ) {
return linter;
}
}
}
}
}
return {};
}
void LinterPlugin::lintDoc( std::shared_ptr<TextDocument> doc ) {
if ( !mLanguagesDisabled.empty() &&
mLanguagesDisabled.find( doc->getSyntaxDefinition().getLSPName() ) !=

View File

@@ -19,6 +19,7 @@ enum class LinterType { Notice, Warning, Error };
enum class MatchOrigin { Linter, Diagnostics };
struct Linter {
std::vector<std::string> languages;
std::vector<std::string> files;
std::vector<std::string> warningPattern;
bool columnsStartAtZero{ false };
@@ -53,10 +54,14 @@ class LinterPlugin : public UICodeEditorPlugin {
"Use static code analysis tool used to flag programming errors, bugs, "
"stylistic errors, and suspicious constructs.",
LinterPlugin::New,
{ 0, 1, 0 } };
{ 0, 1, 0 },
LinterPlugin::NewSync };
}
static UICodeEditorPlugin* New( PluginManager* pluginManager );
static UICodeEditorPlugin* NewSync( PluginManager* pluginManager );
virtual ~LinterPlugin();
std::string getId() { return Definition().id; }
@@ -99,6 +104,10 @@ class LinterPlugin : public UICodeEditorPlugin {
void setErrorLens( bool errorLens );
const std::vector<Linter>& getLinters() const;
Linter getLinterForLang( const std::string& lang, const std::vector<std::string>& extensions );
protected:
PluginManager* mManager{ nullptr };
std::shared_ptr<ThreadPool> mPool;
@@ -124,7 +133,7 @@ class LinterPlugin : public UICodeEditorPlugin {
std::set<std::string> mLanguagesDisabled;
std::set<std::string> mLSPLanguagesDisabled;
LinterPlugin( PluginManager* pluginManager );
LinterPlugin( PluginManager* pluginManager, bool sync );
void load( PluginManager* pluginManager );

View File

@@ -15,12 +15,20 @@ using json = nlohmann::json;
namespace ecode {
UICodeEditorPlugin* LSPClientPlugin::New( PluginManager* pluginManager ) {
return eeNew( LSPClientPlugin, ( pluginManager ) );
return eeNew( LSPClientPlugin, ( pluginManager, false ) );
}
LSPClientPlugin::LSPClientPlugin( PluginManager* pluginManager ) :
UICodeEditorPlugin* LSPClientPlugin::NewSync( PluginManager* pluginManager ) {
return eeNew( LSPClientPlugin, ( pluginManager, true ) );
}
LSPClientPlugin::LSPClientPlugin( PluginManager* pluginManager, bool sync ) :
mManager( pluginManager ), mThreadPool( pluginManager->getThreadPool() ) {
mThreadPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
if ( sync ) {
load( pluginManager );
} else {
mThreadPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
}
}
LSPClientPlugin::~LSPClientPlugin() {

View File

@@ -22,15 +22,14 @@ namespace ecode {
class LSPClientPlugin : public UICodeEditorPlugin {
public:
static PluginDefinition Definition() {
return { "lspclient",
"LSP Client",
"Language Server Protocol Client.",
LSPClientPlugin::New,
{ 0, 0, 1 } };
return { "lspclient", "LSP Client", "Language Server Protocol Client.",
LSPClientPlugin::New, { 0, 0, 1 }, LSPClientPlugin::NewSync };
}
static UICodeEditorPlugin* New( PluginManager* pluginManager );
static UICodeEditorPlugin* NewSync( PluginManager* pluginManager );
virtual ~LSPClientPlugin();
virtual void update( UICodeEditor* );
@@ -94,7 +93,7 @@ class LSPClientPlugin : public UICodeEditorPlugin {
Uint32 mOldTextStyle{ 0 };
Uint32 mOldTextAlign{ 0 };
LSPClientPlugin( PluginManager* pluginManager );
LSPClientPlugin( PluginManager* pluginManager, bool sync );
void load( PluginManager* pluginManager );

View File

@@ -287,6 +287,31 @@ void LSPClientServerManager::memoryUsage( std::shared_ptr<TextDocument> doc ) {
server->memoryUsage();
}
const std::vector<LSPDefinition>& LSPClientServerManager::getLSPs() const {
return mLSPs;
}
LSPDefinition
LSPClientServerManager::getLSPForLang( const std::string& lang,
const std::vector<std::string>& extensions ) const {
for ( const auto& lsp : mLSPs ) {
if ( lsp.language == lang ) {
return lsp;
}
if ( !lsp.filePatterns.empty() ) {
for ( const auto& file : lsp.filePatterns ) {
for ( const auto& ext : extensions ) {
if ( ext == file ) {
return lsp;
}
}
}
}
}
return {};
}
void LSPClientServerManager::didChangeWorkspaceFolders( const std::string& folder ) {
mLSPWorkspaceFolder = { "file://" + folder, FileSystem::fileNameFromPath( folder ) };
Lock l( mClientsMutex );

View File

@@ -68,6 +68,11 @@ class LSPClientServerManager {
void memoryUsage( std::shared_ptr<TextDocument> doc );
const std::vector<LSPDefinition>& getLSPs() const;
LSPDefinition getLSPForLang( const std::string& lang,
const std::vector<std::string>& extensions ) const;
protected:
friend class LSPClientServer;
PluginManager* mPluginManager{ nullptr };

View File

@@ -29,11 +29,13 @@ UICodeEditorPlugin* ecode::PluginManager::get( const std::string& id ) {
return nullptr;
}
bool PluginManager::setEnabled( const std::string& id, bool enable ) {
bool PluginManager::setEnabled( const std::string& id, bool enable, bool sync ) {
mPluginsEnabled[id] = enable;
UICodeEditorPlugin* plugin = get( id );
if ( enable && plugin == nullptr && hasDefinition( id ) ) {
UICodeEditorPlugin* newPlugin = mDefinitions[id].creatorFn( this );
UICodeEditorPlugin* newPlugin = sync && mDefinitions[id].creatorSyncFn
? mDefinitions[id].creatorSyncFn( this )
: mDefinitions[id].creatorFn( this );
mPlugins.insert( std::pair<std::string, UICodeEditorPlugin*>( id, newPlugin ) );
if ( onPluginEnabled )
onPluginEnabled( newPlugin );
@@ -71,11 +73,12 @@ void PluginManager::onNewEditor( UICodeEditor* editor ) {
editor->registerPlugin( plugin.second );
}
void PluginManager::setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled ) {
void PluginManager::setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled,
bool sync ) {
mPluginsEnabled = pluginsEnabled;
for ( const auto& plugin : pluginsEnabled ) {
if ( plugin.second && get( plugin.first ) == nullptr )
setEnabled( plugin.first, true );
setEnabled( plugin.first, true, sync );
}
}

View File

@@ -56,6 +56,7 @@ struct PluginDefinition {
std::string description;
PluginCreatorFn creatorFn;
PluginVersion version;
PluginCreatorFn creatorSyncFn{ nullptr };
};
enum class PluginMessageType {
@@ -218,7 +219,7 @@ class PluginManager {
UICodeEditorPlugin* get( const std::string& id );
bool setEnabled( const std::string& id, bool enable );
bool setEnabled( const std::string& id, bool enable, bool sync = false );
bool isEnabled( const std::string& id ) const;
@@ -230,7 +231,7 @@ class PluginManager {
void onNewEditor( UICodeEditor* editor );
void setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled );
void setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled, bool sync );
const std::shared_ptr<ThreadPool>& getThreadPool() const;