Project Build WIP.

Fixed scroll jumping when formatting documents.
Minor improvements in syntax definitions.
This commit is contained in:
Martín Lucas Golini
2023-04-07 02:24:48 -03:00
parent c593d2b791
commit 74b271002e
6 changed files with 164 additions and 47 deletions

View File

@@ -1,5 +1,5 @@
{
"ecode-debug": {
"ecode": {
"build": [
{
"args": "--with-mojoal --with-debug-symbols gmake",
@@ -7,30 +7,35 @@
"working_dir": "${project_root}"
},
{
"args": "-j$(nproc) config=debug ecode",
"args": "-j${nproc} config=${build_type} ecode",
"command": "make",
"working_dir": "${build_dir}"
}
],
"build_types": [
"debug",
"release"
],
"clean": [
{
"args": "config=debug clean",
"args": "config=${build_type} clean",
"command": "make",
"working_dir": "${build_dir}"
}
],
"config": {
"clear_sys_env": false
},
"var": {
"build_dir": "${project_root}/make/linux"
"clear_sys_env": false,
"enabled": true
},
"env": {
"SHELL": "fish"
},
"os": [
"linux"
],
"output_parser": {
"config": {
"relative_file_paths": true
"relative_file_paths": true
},
"error": [
{
@@ -43,6 +48,9 @@
}
}
]
},
"var": {
"build_dir": "${project_root}/make/${os}"
}
}
}

View File

@@ -1197,6 +1197,8 @@
../../src/tools/ecode/plugins/lsp/lspprotocol.hpp
../../src/tools/ecode/plugins/pluginmanager.cpp
../../src/tools/ecode/plugins/pluginmanager.hpp
../../src/tools/ecode/projectbuild.cpp
../../src/tools/ecode/projectbuild.hpp
../../src/tools/ecode/projectdirectorytree.cpp
../../src/tools/ecode/projectdirectorytree.hpp
../../src/tools/ecode/projectsearch.cpp

View File

@@ -373,7 +373,7 @@ static void addC() {
{ { "^%s*(#define)%s*" }, { "keyword", "keyword", "literal" } },
{ { "^%s*(#else)%s*" }, { "keyword", "keyword", "literal" } },
{ { "^%s*#", "[^\\]\n" }, "comment" },
{ { "\"", "\"", "\\" }, "string" },
{ { "\"", "[\"\n]", "\\" }, "string" },
{ { "'", "'", "\\" }, "string" },
{ { "-?0x%x+" }, "number" },
{ { "-?%d+[%d%.eE]*f?" }, "number" },
@@ -643,7 +643,7 @@ static void addCPP() {
{ { "R\"%(", "%)\"" }, "string" },
{ { "//.-\n" }, "comment" },
{ { "/%*", "%*/" }, "comment" },
{ { "\"", "\"", "\\" }, "string" },
{ { "\"", "[\"\n]", "\\" }, "string" },
{ { "'", "'", "\\" }, "string" },
{ { "^%s*(#include)%s+([<%\"][%w%d%.%\\%/%_%-]+[>%\"])" },
{ "keyword", "keyword", "literal" } },

View File

@@ -392,9 +392,11 @@ void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& forma
editor->runOnMainThread( [&, res, editor]() {
std::shared_ptr<TextDocument> doc = editor->getDocumentRef();
TextPosition pos = doc->getSelection().start();
auto scroll = editor->getScroll();
doc->selectAll();
doc->textInput( res.result );
doc->setSelection( pos );
editor->setScroll( scroll );
} );
return;
}
@@ -429,9 +431,11 @@ void FormatterPlugin::runFormatter( UICodeEditor* editor, const Formatter& forma
editor->runOnMainThread( [&, data, editor]() {
std::shared_ptr<TextDocument> doc = editor->getDocumentRef();
TextPosition pos = doc->getSelection().start();
auto scroll = editor->getScroll();
doc->selectAll();
doc->textInput( data );
doc->setSelection( pos );
editor->setScroll( scroll );
} );
}
}

View File

@@ -10,28 +10,39 @@ using namespace EE;
namespace ecode {
static const char* PROJECT_ROOT = "${project_root}";
static const char* VAR_PROJECT_ROOT = "${project_root}";
static const char* VAR_BUILD_TYPE = "${build_type}";
static const char* VAR_OS = "${os}";
static const char* VAR_NPROC = "${nproc}";
static void replaceVar( ProjectBuildStep& s, const std::string& var, const std::string& val ) {
static std::string slashDup = FileSystem::getOSSlash() + FileSystem::getOSSlash();
String::replaceAll( s.workingDir, var, val );
String::replaceAll( s.cmd, var, val );
String::replaceAll( s.args, var, val );
String::replaceAll( s.workingDir, slashDup, FileSystem::getOSSlash() );
}
void ProjectBuild::replaceVars() {
const std::vector<ProjectBuildSteps*> steps{ &mBuild, &mClean };
auto replaceVar = []( ProjectBuildStep& s, const std::string& var, const std::string& val ) {
String::replaceAll( s.workingDir, var, val );
String::replaceAll( s.cmd, var, val );
String::replaceAll( s.args, var, val );
};
for ( auto& step : steps ) {
for ( auto& s : *step ) {
replaceVar( s, PROJECT_ROOT, mProjectRoot );
replaceVar( s, VAR_PROJECT_ROOT, mProjectRoot );
for ( auto& var : mVars ) {
std::string varKey( "${" + var.first + "}" );
String::replaceAll( var.second, PROJECT_ROOT, mProjectRoot );
String::replaceAll( var.second, VAR_PROJECT_ROOT, mProjectRoot );
replaceVar( s, varKey, var.second );
}
}
}
}
bool ProjectBuild::isOSSupported( const std::string& os ) const {
return mOS.empty() || std::any_of( mOS.begin(), mOS.end(), [&]( const auto& oos ) {
return oos == os || oos == "any";
} );
}
ProjectBuildManager::ProjectBuildManager( const std::string& projectRoot,
std::shared_ptr<ThreadPool> pool ) :
mProjectRoot( projectRoot ), mThreadPool( pool ) {
@@ -61,7 +72,7 @@ static ProjectOutputParserTypes outputParserType( const std::string& typeStr ) {
bool ProjectBuildManager::load() {
ScopedOp op( [this]() { mLoading = true; }, [this]() { mLoading = false; } );
mProjectFile = mProjectRoot + ".ecode/project-build.json";
mProjectFile = mProjectRoot + ".ecode/project_build.json";
if ( !FileSystem::fileExists( mProjectFile ) )
return false;
std::string data;
@@ -82,7 +93,20 @@ bool ProjectBuildManager::load() {
ProjectBuild b( build.key(), mProjectRoot );
const auto& buildObj = build.value();
if ( buildObj.contains( "os" ) && buildObj["os"].is_array() ) {
const auto& oss = buildObj["os"];
for ( const auto& os : oss )
b.mOS.emplace( os );
}
if ( buildObj.contains( "build_types" ) && buildObj["build_types"].is_array() ) {
const auto& bts = buildObj["build_types"];
for ( const auto& bt : bts )
b.mBuildTypes.emplace( bt );
}
if ( buildObj.contains( "config" ) && buildObj["config"].is_object() ) {
b.mConfig.enabled = buildObj.value( "enabled", true );
b.mConfig.clearSysEnv = buildObj.value( "clear_sys_env", false );
}
@@ -135,24 +159,28 @@ bool ProjectBuildManager::load() {
if ( !isValidType( typeStr ) )
continue;
const auto& ptrnCfg = op.value();
ProjectBuildOutputParserConfig opc;
opc.type = outputParserType( typeStr );
opc.pattern = ptrnCfg.value( "pattern", "" );
const auto& ptrnCfgs = op.value();
if ( ptrnCfgs.is_array() ) {
for ( const auto& ptrnCfg : ptrnCfgs ) {
ProjectBuildOutputParserConfig opc;
opc.type = outputParserType( typeStr );
opc.pattern = ptrnCfg.value( "pattern", "" );
if ( ptrnCfg.contains( "pattern_order" ) ) {
const auto& po = ptrnCfg["pattern_order"];
if ( po.contains( "line" ) && po["line"].is_number() )
opc.patternOrder.line = po["line"].get<int>();
if ( po.contains( "col" ) && po["col"].is_number() )
opc.patternOrder.col = po["col"].get<int>();
if ( po.contains( "message" ) && po["message"].is_number() )
opc.patternOrder.message = po["message"].get<int>();
if ( po.contains( "file" ) && po["file"].is_number() )
opc.patternOrder.file = po["file"].get<int>();
if ( ptrnCfg.contains( "pattern_order" ) ) {
const auto& po = ptrnCfg["pattern_order"];
if ( po.contains( "line" ) && po["line"].is_number() )
opc.patternOrder.line = po["line"].get<int>();
if ( po.contains( "col" ) && po["col"].is_number() )
opc.patternOrder.col = po["col"].get<int>();
if ( po.contains( "message" ) && po["message"].is_number() )
opc.patternOrder.message = po["message"].get<int>();
if ( po.contains( "file" ) && po["file"].is_number() )
opc.patternOrder.file = po["file"].get<int>();
}
outputParser.mConfig.emplace_back( std::move( opc ) );
}
}
outputParser.mConfig.emplace_back( std::move( opc ) );
}
}
}
@@ -166,9 +194,43 @@ bool ProjectBuildManager::load() {
return true;
}
void ProjectBuildManager::run( const std::string& buildName ) {
ProjectBuildCommandsRes ProjectBuildManager::generateBuildCommands(
const std::string& buildName,
std::function<String( const std::string& /*key*/, const String& /*defaultvalue*/ )> i18n,
const std::string& buildType ) {
if ( !mLoaded )
return;
return { i18n( "project_build_not_loaded", "No project build loaded!" ) };
const auto& buildIt = mBuilds.find( buildName );
if ( buildIt == mBuilds.end() )
return { i18n( "build_name_not_found", "Build name not found!" ) };
const auto& build = buildIt->second;
if ( !build.mBuildTypes.empty() && buildType.empty() )
return { i18n( "build_type_required", "Build type must be set!" ) };
std::string currentOS = String::toLower( Sys::getPlatform() );
if ( !build.isOSSupported( currentOS ) )
return {
i18n( "build_os_not_supported", "Operating System not supported for this build!" ) };
std::string nproc = String::format( "%d", Sys::getCPUCount() );
ProjectBuildCommandsRes res;
for ( const auto& step : build.mBuild ) {
ProjectBuildCommand buildCmd( step, build.mEnvs );
replaceVar( buildCmd, VAR_OS, currentOS );
replaceVar( buildCmd, VAR_NPROC, nproc );
if ( !buildType.empty() )
replaceVar( buildCmd, VAR_BUILD_TYPE, buildType );
res.cmds.emplace_back( std::move( buildCmd ) );
}
return res;
}
} // namespace ecode

View File

@@ -5,44 +5,50 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace EE;
using namespace EE::System;
namespace ecode {
/** reference:
{
"ecode": {
"build": [
{
"args": "--with-mojoal --with-debug-symbols gmake",
"command": "premake4",
"working_dir": "$PROJECT_ROOT"
"working_dir": "${project_root}"
},
{
"args": "-j$(nproc) config=release ecode",
"args": "-j${nproc} config=${build_type} ecode",
"command": "make",
"working_dir": "${build_dir}"
}
],
"build_types": [
"debug",
"release"
],
"clean": [
{
"args": "config=release clean",
"args": "config=${build_type} clean",
"command": "make",
"working_dir": "${build_dir}"
}
],
"config": {
"clear_sys_env": false
},
"var": {
"build_dir": "$PROJECT_ROOT/make/linux"
"clear_sys_env": false,
"enabled": true
},
"env": {
"SHELL": "fish"
},
"os": [
"linux"
],
"output_parser": {
"config": {
"relative_file_paths": true
@@ -58,6 +64,9 @@ namespace ecode {
}
}
]
},
"var": {
"build_dir": "${project_root}/make/${os}"
}
}
}
@@ -73,6 +82,7 @@ using ProjectBuildSteps = std::vector<ProjectBuildStep>;
using ProjectBuildKeyVal = std::unordered_map<std::string, std::string>;
struct ProjectBuildConfig {
bool enabled{ true };
bool clearSysEnv{ false };
};
@@ -102,11 +112,17 @@ class ProjectBuild {
ProjectBuild( const std::string& name, const std::string& projectRoot ) :
mName( name ), mProjectRoot( projectRoot ){};
const ProjectBuildConfig& getConfig() const { return mConfig; }
bool isOSSupported( const std::string& os ) const;
protected:
friend class ProjectBuildManager;
std::string mName;
std::string mProjectRoot;
std::unordered_set<std::string> mOS;
std::unordered_set<std::string> mBuildTypes;
ProjectBuildSteps mBuild;
ProjectBuildSteps mClean;
ProjectBuildKeyVal mEnvs;
@@ -119,11 +135,36 @@ class ProjectBuild {
using ProjectBuildMap = std::unordered_map<std::string, ProjectBuild>;
struct ProjectBuildCommand : public ProjectBuildStep {
ProjectBuildKeyVal envs;
ProjectBuildCommand( const ProjectBuildStep& step, const ProjectBuildKeyVal& envs ) :
ProjectBuildStep( step ), envs( envs ) {}
};
using ProjectBuildCommands = std::vector<ProjectBuildCommand>;
struct ProjectBuildCommandsRes {
String errorMsg;
ProjectBuildCommands cmds;
ProjectBuildCommandsRes() {}
ProjectBuildCommandsRes( const String& errMsg ) : errorMsg( errMsg ) {}
ProjectBuildCommandsRes( ProjectBuildCommands&& cmds ) : cmds( cmds ) {}
bool isValid() { return errorMsg.empty(); }
};
class ProjectBuildManager {
public:
ProjectBuildManager( const std::string& projectRoot, std::shared_ptr<ThreadPool> pool );
void run( const std::string& buildName );
ProjectBuildCommandsRes generateBuildCommands(
const std::string& buildName,
std::function<String( const std::string& /*key*/, const String& /*defaultvalue*/ )> i18n,
const std::string& buildType = "" );
const ProjectBuildMap& getBuilds() const { return mBuilds; }