mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
ecode: Added --health command line parameter to get a health status (like helix editor).
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -53,6 +53,8 @@ class EE_API SyntaxDefinitionManager {
|
||||
|
||||
void loadFromFolder( const std::string& folderPath );
|
||||
|
||||
const std::vector<SyntaxDefinition>& getDefinitions() const;
|
||||
|
||||
protected:
|
||||
SyntaxDefinitionManager();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,3 +14,4 @@
|
||||
../../src/modules/maps/src/
|
||||
../../src/modules/physics/include/
|
||||
../../src/modules/physics/src/
|
||||
../../src/tools/ecode
|
||||
|
||||
@@ -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
9248
src/thirdparty/tabulate/tabulate.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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() );
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
120
src/tools/ecode/featureshealth.cpp
Normal file
120
src/tools/ecode/featureshealth.cpp
Normal 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
|
||||
33
src/tools/ecode/featureshealth.hpp
Normal file
33
src/tools/ecode/featureshealth.hpp
Normal 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
|
||||
@@ -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(
|
||||
[&]() {
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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() ) !=
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user