Skip to content

Commit 89d7e5e

Browse files
committed
Implement support for install command in metacallcli.
1 parent 3beb6ac commit 89d7e5e

File tree

4 files changed

+132
-27
lines changed

4 files changed

+132
-27
lines changed

source/examples/metacallcli/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ install(TARGETS ${target}
125125
# Define test
126126
#
127127

128-
set(TEST_COMMAND_LINE_ARGS "mock test.mock")
129-
128+
#set(TEST_COMMAND_LINE_ARGS "load mock test.mock")
129+
set(TEST_COMMAND_LINE_ARGS "install py numpy")
130130

131131
if(WIN32)
132132
set(TEST_COMMAND cmd /c)

source/examples/metacallcli/application.cpp

Lines changed: 110 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ bool command_cb_help(application & /*app*/, tokenizer & /*t*/)
3838
{
3939
std::cout << "MetaCall Command Line Interface by Parra Studios" << std::endl;
4040
std::cout << "Copyright (C) 2016 - 2019 Vicente Eduardo Ferrer Garcia <[email protected]>" << std::endl;
41-
std::cout << std::endl << "A command line interface example as MetaCall wrapper" << std::endl;
41+
std::cout << std::endl << "A command line interface for MetaCall Core" << std::endl;
4242

4343
/* Command list */
4444
std::cout << std::endl << "Command list:" << std::endl << std::endl;
@@ -315,8 +315,8 @@ bool command_cb_exit(application & app, tokenizer & /*t*/)
315315

316316
/* -- Methods -- */
317317

318-
application::parameter_iterator::parameter_iterator(application & app, const std::string & tag, application::script_list & scripts) :
319-
app(app), tag(tag), scripts(scripts)
318+
application::parameter_iterator::parameter_iterator(application & app, const char * command, const char * tag, application::arg_list & arguments) :
319+
app(app), command(command), tag(tag), arguments(arguments)
320320
{
321321

322322
}
@@ -328,22 +328,113 @@ application::parameter_iterator::~parameter_iterator()
328328

329329
void application::parameter_iterator::operator()(const char * parameter)
330330
{
331-
std::string script(parameter);
331+
arguments.push_back(parameter);
332+
}
333+
334+
void application::parameter_iterator::evaluate()
335+
{
336+
typedef std::function<void(application &, const std::string &, const std::string &, application::arg_list &)> parameter_callback;
337+
338+
/* List of scripts that run pip/npm/gem */
339+
static std::unordered_map<std::string, std::string> install_scripts =
340+
{
341+
{
342+
"py",
343+
"#!/usr/bin/env python3\n"
344+
"\n"
345+
"try:\n"
346+
" from pip import main as pipmain\n"
347+
"except ImportError:\n"
348+
" from pip._internal import main as pipmain\n"
349+
"\n"
350+
"def package_manager(args):\n"
351+
" return pipmain(args);\n"
352+
}
353+
};
354+
355+
/* List of available commands when installing */
356+
static std::unordered_map<std::string, parameter_callback> parameter_commands =
357+
{
358+
{
359+
"load", [](application & app, const std::string & tag, const std::string &, application::arg_list & args)
360+
{
361+
std::for_each(args.begin(), args.end(), [&app, &tag](const std::string & script)
362+
{
363+
app.load(tag, script);
364+
});
365+
}
366+
},
367+
{
368+
"install", [](application & app, const std::string & tag, const std::string & command, application::arg_list & args)
369+
{
370+
const std::string & script = install_scripts[tag];
371+
372+
if (script == "")
373+
{
374+
std::cout << "Package manager script not available for tag (" << tag << ")" << std::endl;
375+
376+
app.shutdown();
377+
378+
return;
379+
}
380+
381+
if (metacall_load_from_memory(tag.c_str(), script.c_str(), script.size(), NULL) != 0)
382+
{
383+
std::cout << "Error when loading (" << tag << ") package manager script" << std::endl;
332384

333-
if (app.load(tag, script) == false)
385+
app.shutdown();
386+
387+
return;
388+
}
389+
390+
void * args_values[1] =
391+
{
392+
metacall_value_create_array(NULL, args.size() + 1)
393+
};
394+
395+
void ** array_value = static_cast<void **>(metacall_value_to_array(args_values[0]));
396+
397+
size_t iterator = 0;
398+
399+
array_value[iterator++] = metacall_value_create_string(command.c_str(), command.length());
400+
401+
std::for_each(args.begin(), args.end(), [&array_value, &iterator](const std::string & arg)
402+
{
403+
array_value[iterator++] = metacall_value_create_string(arg.c_str(), arg.length());
404+
});
405+
406+
void * result = metacallv("package_manager", args_values);
407+
408+
metacall_value_destroy(args_values[0]);
409+
410+
/* TODO: Do something with result */
411+
412+
if (result != NULL)
413+
{
414+
metacall_value_destroy(result);
415+
}
416+
417+
app.shutdown();
418+
}
419+
}
420+
};
421+
422+
const parameter_callback cb = parameter_commands[command];
423+
424+
if (cb != nullptr)
334425
{
335-
std::cout << "Invalid parameter (" << parameter << ")" << std::endl;
426+
cb(app, tag, command, arguments);
336427
}
337428
}
338429

339430
bool application::load(const std::string & tag, const std::string & script)
340431
{
341-
const char * script_list[] =
432+
const char * load_scripts[] =
342433
{
343434
script.c_str()
344435
};
345436

346-
if (metacall_load_from_file(tag.c_str(), script_list, sizeof(script_list) / sizeof(script_list[0]), NULL) != 0)
437+
if (metacall_load_from_file(tag.c_str(), load_scripts, sizeof(load_scripts) / sizeof(load_scripts[0]), NULL) != 0)
347438
{
348439
std::cout << "Script (" << script << ") load error in loader (" << tag << ")" << std::endl;
349440

@@ -444,13 +535,16 @@ application::application(int argc, char * argv[]) : exit_condition(false), log_p
444535
/* Print MetaCall information */
445536
metacall_print_info();
446537

447-
/* Parse program arguments if any */
448-
if (argc > 1)
538+
/* Parse program arguments if any (e.g metacall (0) load (1) py (2) asd.py (3)) */
539+
if (argc > 3)
449540
{
450-
parameter_iterator param_it(*this, argv[1], scripts);
541+
parameter_iterator param_it(*this, argv[1], argv[2], arguments);
451542

452543
/* Parse program parameters */
453-
std::for_each(&argv[2], argv + argc, param_it);
544+
std::for_each(&argv[3], argv + argc, param_it);
545+
546+
/* Execute the action */
547+
param_it.evaluate();
454548
}
455549

456550
/* Define available commands */
@@ -480,7 +574,10 @@ application::~application()
480574
void application::run()
481575
{
482576
/* Show welcome message */
483-
std::cout << "Welcome to Tijuana, tequila, sexo & marijuana." << std::endl;
577+
if (exit_condition != true)
578+
{
579+
std::cout << "Welcome to Tijuana, tequila, sexo & marijuana." << std::endl;
580+
}
484581

485582
while (exit_condition != true)
486583
{

source/examples/metacallcli/application.hpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ class application
214214

215215
/* -- Private Type Definitions -- */
216216

217+
typedef std::vector<std::string> arg_list;
218+
217219
typedef std::vector<std::string> script_list;
218220

219221
typedef std::unordered_map<std::string, command_callback> command_table;
@@ -233,13 +235,16 @@ class application
233235
* @param[in] app
234236
* Reference to the application
235237
*
238+
* @param[in] command
239+
* Command to be executed
240+
*
236241
* @param[in] tag
237242
* Loader tag reference
238243
*
239-
* @param[in] scripts
240-
* Reference to list of scripts to be iterated
244+
* @param[in] arguments
245+
* Reference to list of arguments to be iterated
241246
*/
242-
parameter_iterator(application & app, const std::string & tag, script_list & scripts);
247+
parameter_iterator(application & app, const char * command, const char * tag, arg_list & arguments);
243248

244249
/**
245250
* @brief
@@ -256,6 +261,12 @@ class application
256261
*/
257262
void operator()(const char * parameter);
258263

264+
/**
265+
* @brief
266+
* Execute the action parsed by parameters
267+
*/
268+
void evaluate();
269+
259270
/**
260271
* @brief
261272
* Assignement operator for parameter iterator
@@ -269,21 +280,18 @@ class application
269280

270281
/* -- Private Member Data -- */
271282

272-
application & app; /**< Reference to the application */
273-
274-
std::string tag; /**< Loader tag reference */
275-
276-
script_list & scripts; /**< Reference to the script list */
283+
application & app; /**< Reference to the application */
284+
std::string command; /**< Command to be executed */
285+
std::string tag; /**< Loader tag reference */
286+
arg_list & arguments; /**< Reference to the argument list */
277287
};
278288

279289
/* -- Private Member Data -- */
280290

281291
bool exit_condition; /**< Condition for main loop */
282-
292+
arg_list arguments; /**< Vector containing a list of arguments */
283293
script_list scripts; /**< Vector containing a list of script names */
284-
285294
command_table commands; /**< Hash table from command strings to command handlers */
286-
287295
std::string log_path; /**< Path where logs are located */
288296
};
289297

source/examples/metacallcli/tokenizer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class tokenizer
187187

188188
/* -- Private Member Data -- */
189189

190-
const tokenizer & t; /**< Reference to tokenizer */
190+
const tokenizer & t; /**< Reference to tokenizer */
191191

192192
size_t offset; /**< Current position over iteration */
193193

0 commit comments

Comments
 (0)