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

@@ -7,42 +7,51 @@
},
"formatters": [
{
"language": ["javascript", "typescript"],
"file_patterns": ["%.js$", "%.ts$"],
"command": "prettier $FILENAME"
},
{
"language": ["c", "cpp"],
"file_patterns": ["%.inl$", "%.cpp$", "%.hpp$", "%.cc$", "%.cxx$", "%.c++$", "%.hh$", "%.hxx$", "%.h++$", "%.objcpp$"],
"command": "clang-format --style=file $FILENAME"
},
{
"language": "python",
"file_patterns": ["%.py$", "%.pyw$"],
"command": "black $FILENAME",
"type": "inplace"
},
{
"language": "kotlin",
"file_patterns": ["%.kt$"],
"command": "ktlint -F $FILENAME",
"type": "inplace"
},
{
"language": "rust",
"file_patterns": ["%.rs"],
"command": "rustfmt --emit stdout --color never $FILENAME"
},
{
"language": "go",
"file_patterns": ["%.go"],
"command": "gopls format $FILENAME"
},
{
"language": "json",
"file_patterns": ["%.json$", "%.cson$"],
"command": "json",
"type": "native"
},
{
"language": [ "xml", "html" ],
"file_patterns": ["%.xml", "%.html?$"],
"command": "xml",
"type": "native"
},
{
"language": "css",
"file_patterns": ["%.css"],
"command": "css",
"type": "native"

View File

@@ -4,12 +4,14 @@
},
"linters": [
{
"language": "php",
"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"
},
{
"language": "json",
"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 },
@@ -19,46 +21,54 @@
"use_tmp_folder": true
},
{
"language": ["javascript", "typescript"],
"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"
},
{
"language": "lua",
"file_patterns": ["%.lua$"],
"warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)",
"command": "luacheck $FILENAME --formatter=plain -g --no-max-line-length"
},
{
"language": "python",
"file_patterns": ["%.py$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"command": "ruff $FILENAME"
},
{
"language": "bash",
"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"
},
{
"language": "solidity",
"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"
},
{
"language": ["c", "cpp"],
"file_patterns": ["%.inl$", "%.cpp$", "%.hpp$", "%.cc$", "%.cxx$", "%.c++$", "%.hh$", "%.hxx$", "%.h++$", "%.objcpp$"],
"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"
},
{
"language": "kotlin",
"file_patterns": ["%.kt$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([^\n]+)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 3, "type": 4 },
"command": "ktlint $FILENAME"
},
{
"language": "zig",
"file_patterns": ["%.zig$"],
"warning_pattern": "[^%s:]:(%d+):(%d+):[%s]?(%w*):([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
@@ -67,6 +77,7 @@
"expected_exitcodes": [0, 1]
},
{
"language": "nim",
"file_patterns": ["%.nim$", "%.nims$"],
"warning_pattern": "$FILENAME%((%d+), (%d+)%)%s(%w*):%s([^\n]+[^/]*)",
"command": "nim --listfullpaths --stdout check $FILENAME",
@@ -76,12 +87,14 @@
"use_tmp_folder": true
},
{
"language": "nelua",
"file_patterns": ["%.nelua$"],
"warning_pattern": "[^:]:(%d+):(%d+):%s([%w%s]*):%s?([^\n]*)",
"warning_pattern_order": { "line": 1, "col": 2, "message": 4, "type": 3 },
"command": "nelua --lint $FILENAME"
},
{
"language": "teal",
"file_patterns": ["%.tl$"],
"warning_pattern": "[^:]:(%d+):(%d+):[%s]?([^\n]+)",
"command": "tl check $FILENAME",

View File

@@ -53,6 +53,8 @@ class EE_API SyntaxDefinitionManager {
void loadFromFolder( const std::string& folderPath );
const std::vector<SyntaxDefinition>& getDefinitions() const;
protected:
SyntaxDefinitionManager();

View File

@@ -1151,6 +1151,8 @@
../../src/tools/ecode/ecode.hpp
../../src/tools/ecode/docsearchcontroller.cpp
../../src/tools/ecode/docsearchcontroller.hpp
../../src/tools/ecode/featureshealth.cpp
../../src/tools/ecode/featureshealth.hpp
../../src/tools/ecode/filelocator.cpp
../../src/tools/ecode/filelocator.hpp
../../src/tools/ecode/filesystemlistener.cpp

View File

@@ -14,3 +14,4 @@
../../src/modules/maps/src/
../../src/modules/physics/include/
../../src/modules/physics/src/
../../src/tools/ecode

View File

@@ -133,6 +133,10 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() {
addVue();
}
const std::vector<SyntaxDefinition>& SyntaxDefinitionManager::getDefinitions() const {
return mDefinitions;
}
void SyntaxDefinitionManager::addPlainText() {
add( { "Plain Text", { "%.txt$" }, {}, {}, "", {}, "plaintext" } );
}

9248
src/thirdparty/tabulate/tabulate.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ static std::vector<std::string> urlDecode( const std::vector<std::string>& vec )
void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
std::string& initColorScheme, std::vector<std::string>& recentFiles,
std::vector<std::string>& recentFolders, const std::string& resPath,
PluginManager* pluginManager, const Sizei& displaySize ) {
PluginManager* pluginManager, const Sizei& displaySize, bool sync ) {
keybindingsPath = confPath + "keybindings.cfg";
ini.loadFromFile( confPath + "config.cfg" );
iniState.loadFromFile( confPath + "state.cfg" );
@@ -157,7 +157,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
ini.getValueB( "plugins", creator.first,
"autocomplete" == creator.first || "linter" == creator.first ||
"autoformatter" == creator.first || "lspclient" == creator.first );
pluginManager->setPluginsEnabled( pluginsEnabled );
pluginManager->setPluginsEnabled( pluginsEnabled, sync );
iniInfo = FileInfo( ini.path() );
}

View File

@@ -130,7 +130,7 @@ struct AppConfig {
void load( const std::string& confPath, std::string& keybindingsPath,
std::string& initColorScheme, std::vector<std::string>& recentFiles,
std::vector<std::string>& recentFolders, const std::string& resPath,
PluginManager* pluginManager, const Sizei& displaySize );
PluginManager* pluginManager, const Sizei& displaySize, bool sync );
void save( const std::vector<std::string>& recentFiles,
const std::vector<std::string>& recentFolders, const std::string& panelPartition,

View File

@@ -1,4 +1,5 @@
#include "ecode.hpp"
#include "featureshealth.hpp"
#include "plugins/autocomplete/autocompleteplugin.hpp"
#include "plugins/formatter/formatterplugin.hpp"
#include "plugins/linter/linterplugin.hpp"
@@ -393,7 +394,7 @@ void App::initPluginManager() {
mPluginManager->registerPlugin( LSPClientPlugin::Definition() );
}
void App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize ) {
void App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool sync ) {
mConfigPath = Sys::getConfigPath( "ecode" );
if ( !FileSystem::fileExists( mConfigPath ) )
FileSystem::makeDir( mConfigPath );
@@ -425,7 +426,7 @@ void App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize ) {
initPluginManager();
mConfig.load( mConfigPath, mKeybindingsPath, mInitColorScheme, mRecentFiles, mRecentFolders,
mResPath, mPluginManager.get(), displaySize.asInt() );
mResPath, mPluginManager.get(), displaySize.asInt(), sync );
}
void App::saveConfig() {
@@ -2305,7 +2306,7 @@ FontTrueType* App::loadFont( const std::string& name, std::string fontPath,
void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDensity,
const std::string& colorScheme, bool terminal, bool frameBuffer, bool benchmarkMode,
const std::string& css ) {
const std::string& css, bool health ) {
DisplayManager* displayManager = Engine::instance()->getDisplayManager();
Display* currentDisplay = displayManager->getDisplayIndex( 0 );
mDisplayDPI = currentDisplay->getDPI();
@@ -2330,7 +2331,12 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
mResPath += "assets";
FileSystem::dirAddSlashAtEnd( mResPath );
loadConfig( logLevel, currentDisplay->getSize() );
loadConfig( logLevel, currentDisplay->getSize(), health );
if ( health ) {
FeaturesHealth::printHealth( mPluginManager.get() );
return;
}
currentDisplay = displayManager->getDisplayIndex( mConfig.windowState.displayIndex <
displayManager->getDisplayCount()
@@ -3013,6 +3019,8 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
"Sets the number of background jobs that the application will spawn "
"at the start of the application",
{ 'j', "jobs" }, 0 );
args::Flag health( parser, "health", "Checks for potential errors in editor setup.",
{ "health" } );
try {
parser.ParseCLI( Sys::parseArguments( argc, argv ) );
} catch ( const args::Help& ) {
@@ -3040,7 +3048,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
appInstance->init( logLevel.Get(), filePos ? filePos.Get() : file.Get(),
pixelDenstiyConf ? pixelDenstiyConf.Get() : 0.f,
prefersColorScheme ? prefersColorScheme.Get() : "", terminal.Get(), fb.Get(),
benchmarkMode.Get(), css.Get() );
benchmarkMode.Get(), css.Get(), health.Get() );
eeSAFE_DELETE( appInstance );
Engine::destroySingleton();

View File

@@ -32,7 +32,7 @@ class App : public UICodeEditorSplitter::Client {
void init( const LogLevel& logLevel, std::string file, const Float& pidelDensity,
const std::string& colorScheme, bool terminal, bool frameBuffer, bool benchmarkMode,
const std::string& css );
const std::string& css, bool health );
void createWidgetInspector();
@@ -54,7 +54,7 @@ class App : public UICodeEditorSplitter::Client {
void runCommand( const std::string& command );
void loadConfig( const LogLevel& logLevel, const Sizeu& displaySize );
void loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool sync );
void saveConfig();

View File

@@ -0,0 +1,120 @@
#include "featureshealth.hpp"
#include "plugins/formatter/formatterplugin.hpp"
#include "plugins/linter/linterplugin.hpp"
#include "plugins/lsp/lspclientplugin.hpp"
#include "plugins/pluginmanager.hpp"
#include <eepp/system/sys.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <tabulate/tabulate.hpp>
using namespace EE::System;
using namespace EE::UI::Doc;
using namespace tabulate;
namespace ecode {
std::vector<FeaturesHealth::LangHealth> FeaturesHealth::getHealth( PluginManager* pluginManager ) {
std::vector<FeaturesHealth::LangHealth> langs;
const auto& definitions = SyntaxDefinitionManager::instance()->getDefinitions();
LinterPlugin* linter = static_cast<LinterPlugin*>( pluginManager->get( "linter" ) );
FormatterPlugin* formatter =
static_cast<FormatterPlugin*>( pluginManager->get( "autoformatter" ) );
LSPClientPlugin* lsp = static_cast<LSPClientPlugin*>( pluginManager->get( "lspclient" ) );
for ( const auto& def : definitions ) {
FeaturesHealth::LangHealth lang;
lang.lang = def.getLSPName();
lang.syntaxHighlighting = true;
if ( linter ) {
Linter found = linter->getLinterForLang( def.getLSPName(), def.getFiles() );
if ( !found.command.empty() ) {
lang.linter.name = String::split( found.command, ' ' )[0];
lang.linter.path = Sys::which( lang.linter.name );
lang.linter.found = !lang.linter.path.empty();
}
}
if ( formatter ) {
FormatterPlugin::Formatter found =
formatter->getFormatterForLang( def.getLSPName(), def.getFiles() );
if ( !found.command.empty() ) {
lang.formatter.name = found.type == FormatterPlugin::FormatterType::Native
? "native"
: String::split( found.command, ' ' )[0];
lang.formatter.path = Sys::which( lang.formatter.name );
lang.formatter.found = !lang.linter.path.empty() ||
found.type == FormatterPlugin::FormatterType::Native;
}
}
if ( lsp ) {
LSPDefinition found =
lsp->getClientManager().getLSPForLang( def.getLSPName(), def.getFiles() );
if ( !found.command.empty() ) {
lang.lsp.name = String::split( found.command, ' ' )[0];
lang.lsp.path = Sys::which( lang.lsp.name );
lang.lsp.found = !lang.lsp.path.empty();
}
}
langs.emplace_back( std::move( lang ) );
}
return langs;
}
void FeaturesHealth::printHealth( PluginManager* pluginManager ) {
auto status( getHealth( pluginManager ) );
Table table;
table.format().border_top( "" ).border_bottom( "" ).border_left( "" ).border_right( "" ).corner(
"" );
size_t numRows = 5;
table.add_row( { "Language", "Highlight", "LSP", "Linter", "Formatter" } );
for ( size_t i = 0; i < numRows; ++i ) {
table[0][i]
.format()
.font_color( tabulate::Color::white )
.font_align( FontAlign::center )
.font_style( { FontStyle::bold } );
}
for ( const auto& ht : status ) {
table.add_row( { ht.lang, "Found", ht.lsp.name.empty() ? "None" : ht.lsp.name,
ht.linter.name.empty() ? "None" : ht.linter.name,
ht.formatter.name.empty() ? "None" : ht.formatter.name } );
auto& row = table[table.size() - 1];
row[1].format().font_color( tabulate::Color::green );
if ( !ht.lsp.name.empty() ) {
row[2].format().font_color( ht.lsp.found ? tabulate::Color::green
: tabulate::Color::red );
} else {
row[2].format().font_color( tabulate::Color::yellow );
}
if ( !ht.linter.name.empty() ) {
row[3].format().font_color( ht.linter.found ? tabulate::Color::green
: tabulate::Color::red );
} else {
row[3].format().font_color( tabulate::Color::yellow );
}
if ( !ht.formatter.name.empty() ) {
row[4].format().font_color( ht.formatter.found ? tabulate::Color::green
: tabulate::Color::red );
} else {
row[4].format().font_color( tabulate::Color::yellow );
}
}
std::cout << table << "\n";
}
} // namespace ecode

View File

@@ -0,0 +1,33 @@
#ifndef ECODE_FEATURESHEALTH_HPP
#define ECODE_FEATURESHEALTH_HPP
#include <string>
#include <vector>
namespace ecode {
class PluginManager;
class FeaturesHealth {
public:
struct FeatureStatus {
std::string name;
std::string path;
bool found{ false };
};
struct LangHealth {
std::string lang;
bool syntaxHighlighting{ true };
FeatureStatus linter;
FeatureStatus formatter;
FeatureStatus lsp;
};
static std::vector<LangHealth> getHealth( PluginManager* pluginManager );
static void printHealth( PluginManager* pluginManager );
};
} // namespace ecode
#endif // ECODE_FEATURESHEALTH_HPP

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;