eepp: Added Sys::getEnvironmentVariables. Improved Process class.

ecode: Fixed a bug in StatusBuildOuputController. Improvements when code completion and signature help are present at the same time.
This commit is contained in:
Martín Lucas Golini
2023-12-16 00:21:20 -03:00
parent 9e0ff076f2
commit b41cbfe1ce
7 changed files with 96 additions and 89 deletions

View File

@@ -73,6 +73,16 @@ class EE_API Process {
const std::unordered_map<std::string, std::string>& environment = {},
const std::string& workingDirectory = "" );
/** @brief Create a process.
** @param command Command line to execute for this process.
** @param args Command line arguments to execute for this process.
** @param options A bit field of Options's to pass.
** @return On success true is returned. */
bool create( const std::string& command, const std::vector<std::string>& args,
Uint32 options = getDefaultOptions(),
const std::unordered_map<std::string, std::string>& environment = {},
const std::string& workingDirectory = "" );
/** @brief Starts a new thread to receive all stdout and stderr data */
void startAsyncRead( ReadFn readStdOut = nullptr, ReadFn readStdErr = nullptr );
@@ -149,6 +159,11 @@ class EE_API Process {
** @return The number of bytes actually written into buffer. */
size_t write( const std::string& buffer );
/** @brief Write the standard output from the child process.
** @param buffer The buffer to write into.
** @return The number of bytes actually written into buffer. */
size_t write( const std::string_view& buffer );
/** @brief Wait for a process to finish execution.
** @param returnCodeOut The return code of the returned process (can be nullptr).
** @return On success true is returned.

View File

@@ -3,6 +3,7 @@
#include <eepp/system/time.hpp>
#include <string>
#include <unordered_map>
#include <vector>
namespace EE { namespace System {
@@ -103,6 +104,9 @@ class EE_API Sys {
/** @return True if current running platform / os is a mobile one */
static bool isMobile();
/** @return The process environment variables */
static std::unordered_map<std::string, std::string> getEnvironmentVariables();
};
}} // namespace EE::System

View File

@@ -51,52 +51,27 @@ Process::~Process() {
bool Process::create( const std::string& command, Uint32 options,
const std::unordered_map<std::string, std::string>& environment,
const std::string& workingDirectory ) {
if ( mProcess )
return false;
std::vector<std::string> cmdArr = String::split( command, " ", "", "\"", true );
std::vector<const char*> strings;
mProcess = eeMalloc( sizeof( subprocess_s ) );
memset( mProcess, 0, sizeof( subprocess_s ) );
if ( !environment.empty() ) {
std::string rcommand;
if ( FileSystem::fileExists( command ) ) {
rcommand = command;
} else {
rcommand = Sys::which( command );
if ( rcommand.empty() )
return false;
}
strings.push_back( rcommand.c_str() );
std::vector<std::string> envArr;
std::vector<const char*> envStrings;
for ( const auto& pair : environment ) {
envArr.push_back( String::format( "%s=%s", pair.first.c_str(), pair.second.c_str() ) );
envStrings.push_back( envArr[envArr.size() - 1].c_str() );
}
envStrings.push_back( NULL );
auto ret = 0 == subprocess_create_ex( strings.data(), options, envStrings.data(),
!workingDirectory.empty() ? workingDirectory.c_str()
: nullptr,
PROCESS_PTR );
return ret;
}
for ( size_t i = 0; i < cmdArr.size(); ++i )
strings.push_back( cmdArr[i].c_str() );
strings.push_back( NULL );
auto ret =
0 == subprocess_create_ex( strings.data(), options, nullptr,
!workingDirectory.empty() ? workingDirectory.c_str() : nullptr,
PROCESS_PTR );
return ret;
if ( cmdArr.empty() )
return false;
std::string cmd( cmdArr[0] );
cmdArr.erase( cmdArr.begin() );
return create( cmd, cmdArr, options, environment, workingDirectory );
}
bool Process::create( const std::string& command, const std::string& args, Uint32 options,
const std::unordered_map<std::string, std::string>& environment,
const std::string& workingDirectory ) {
return create( command, String::split( args, " ", "", "\"", true ), options, environment,
workingDirectory );
}
bool Process::create( const std::string& command, const std::vector<std::string>& cmdArr,
Uint32 options,
const std::unordered_map<std::string, std::string>& environment,
const std::string& workingDirectory ) {
if ( mProcess )
return false;
std::vector<std::string> cmdArr = String::split( args, " ", "", "\"", true );
std::vector<const char*> strings;
mProcess = eeMalloc( sizeof( subprocess_s ) );
memset( mProcess, 0, sizeof( subprocess_s ) );
@@ -109,17 +84,31 @@ bool Process::create( const std::string& command, const std::string& args, Uint3
if ( rcommand.empty() )
return false;
}
std::vector<std::string> envArr;
std::vector<const char*> envStrings;
std::unordered_map<std::string, std::string> envVars;
if ( options & Process::InheritEnvironment ) {
envVars = Sys::getEnvironmentVariables();
options &= ~Process::InheritEnvironment;
}
envArr.reserve( environment.size() + envVars.size() );
strings.reserve( cmdArr.size() + 1 );
envStrings.reserve( envArr.size() + 1 );
strings.push_back( rcommand.c_str() );
for ( size_t i = 0; i < cmdArr.size(); ++i )
strings.push_back( cmdArr[i].c_str() );
strings.push_back( NULL );
std::vector<std::string> envArr;
std::vector<const char*> envStrings;
for ( const auto& pair : environment ) {
// Set / Overwrite our envs
for ( auto& pair : environment )
envVars[pair.first] = std::move( pair.second );
for ( const auto& pair : envVars ) {
envArr.push_back( String::format( "%s=%s", pair.first.c_str(), pair.second.c_str() ) );
envStrings.push_back( envArr[envArr.size() - 1].c_str() );
}
envStrings.push_back( NULL );
auto ret = 0 == subprocess_create_ex( strings.data(), options, envStrings.data(),
@@ -179,6 +168,10 @@ size_t Process::write( const std::string& buffer ) {
return write( buffer.c_str(), buffer.size() );
}
size_t Process::write( const std::string_view& buffer ) {
return write( buffer.data(), buffer.size() );
}
bool Process::join( int* const returnCodeOut ) {
eeASSERT( mProcess != nullptr );
return 0 == subprocess_join( PROCESS_PTR, returnCodeOut );
@@ -312,7 +305,7 @@ void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) {
mBufferSize );
if ( n == 0 )
break;
if ( n < static_cast<long>( mBufferSize - 1 ) )
if ( n < mBufferSize - 1 )
buffer[n] = '\0';
if ( !mShuttingDown )
mReadStdOutFn( buffer.c_str(), static_cast<size_t>( n ) );
@@ -329,7 +322,7 @@ void Process::startAsyncRead( ReadFn readStdOut, ReadFn readStdErr ) {
mBufferSize );
if ( n == 0 )
break;
if ( n < static_cast<long>( mBufferSize - 1 ) )
if ( n < mBufferSize - 1 )
buffer[n] = '\0';
if ( !mShuttingDown )

View File

@@ -77,6 +77,32 @@ using namespace EE::Network;
#define PATH_MAX 4096
#endif
std::unordered_map<std::string, std::string> _getEnvironmentVariables() {
std::unordered_map<std::string, std::string> ret;
char** env;
#if defined( WIN ) && ( _MSC_VER >= 1900 )
env = *__p__environ();
#else
extern char** environ;
env = environ;
#endif
for ( ; *env; ++env ) {
auto var = EE::String::split( *env, "=" );
if ( var.size() == 2 ) {
ret.insert( std::make_pair( var[0], var[1] ) );
} else if ( var.size() > 2 ) {
auto val( var[1] );
for ( size_t i = 2; i < var.size(); ++i )
val += var[i];
ret.insert( std::make_pair( var[0], val ) );
}
}
return ret;
}
namespace EE { namespace System {
#if EE_PLATFORM == EE_PLATFORM_WIN
@@ -1192,6 +1218,10 @@ bool Sys::isMobile() {
#endif
}
std::unordered_map<std::string, std::string> Sys::getEnvironmentVariables() {
return _getEnvironmentVariables();
}
std::string Sys::getProcessFilePath() {
#if EE_PLATFORM != EE_PLATFORM_WIN
char exename[PATH_MAX];

View File

@@ -262,10 +262,12 @@ bool AutoCompletePlugin::onKeyDown( UICodeEditor* editor, const KeyEvent& event
editor->invalidateDraw();
return true;
} else if ( event.getKeyCode() == KEY_ESCAPE ) {
resetSuggestions( editor );
resetSignatureHelp();
editor->invalidateDraw();
return true;
if ( !ret ) {
resetSuggestions( editor );
resetSignatureHelp();
editor->invalidateDraw();
return true;
}
} else if ( event.getKeyCode() == KEY_HOME ) {
mSuggestionIndex = 0;
mSuggestionsStartIndex = 0;

View File

@@ -17,33 +17,6 @@ using json = nlohmann::json;
using namespace EE::Scene;
/** @return The process environment variables */
static ecode::ProjectBuildKeyVal getEnvironmentVariables() {
ecode::ProjectBuildKeyVal ret;
char** env;
#if defined( WIN ) && ( _MSC_VER >= 1900 )
env = *__p__environ();
#else
extern char** environ;
env = environ;
#endif
for ( ; *env; ++env ) {
auto var = String::split( *env, "=" );
if ( var.size() == 2 ) {
ret.push_back( std::make_pair( var[0], var[1] ) );
} else if ( var.size() > 2 ) {
auto val( var[1] );
for ( size_t i = 2; i < var.size(); ++i )
val += var[i];
ret.push_back( std::make_pair( var[0], val ) );
}
}
return ret;
}
namespace ecode {
static const char* VAR_PROJECT_ROOT = "${project_root}";
@@ -764,17 +737,8 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
int progress = c > 0 ? c / (Float)totSteps : 0;
mProcess = std::make_unique<Process>();
auto options = Process::SearchUserPath | Process::NoWindow | Process::CombinedStdoutStderr;
ProjectBuildKeyVal env;
if ( !cmd.config.clearSysEnv ) {
if ( !res.envs.empty() ) {
env = getEnvironmentVariables();
env.insert( env.begin(), res.envs.begin(), res.envs.end() );
} else {
options |= Process::InheritEnvironment;
}
} else {
env = res.envs;
}
if ( !cmd.config.clearSysEnv )
options |= Process::InheritEnvironment;
if ( !cmd.enabled ) {
c++;
@@ -797,7 +761,7 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
nullptr );
}
if ( mProcess->create( cmd.cmd, cmd.args, options, toUnorderedMap( env ),
if ( mProcess->create( cmd.cmd, cmd.args, options, toUnorderedMap( res.envs ),
cmd.workingDir ) ) {
std::string buffer( 1024, '\0' );
unsigned bytesRead = 0;

View File

@@ -568,12 +568,11 @@ void StatusBuildOutputController::createContainer() {
->setId( "copy-error-message" );
menu->add( mApp->i18n( "copy_file_path", "Copy File Path" ), mApp->findIcon( "copy" ) )
->setId( "copy-file-path" );
menu->on( Event::OnItemClicked, [this, model, modelEvent, idx]( const Event* event ) {
menu->on( Event::OnItemClicked, [this, model, idx]( const Event* event ) {
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
std::string id( item->getId() );
if ( id == "copy-error-message" ) {
Variant msg( model->data( model->index( modelEvent->getModelIndex().row(), 0 ),
ModelRole::Display ) );
Variant msg( model->data( model->index( idx.row(), 0 ), ModelRole::Display ) );
mApp->getWindow()->getClipboard()->setText( msg.toString() );
} else if ( id == "copy-file-path" ) {
Variant msg( model->data( idx, ModelRole::Custom ) );