Skip to content

Commit e9078eb

Browse files
committed
Finished fallback for positional arguments.
1 parent e9a22f7 commit e9078eb

File tree

2 files changed

+152
-110
lines changed

2 files changed

+152
-110
lines changed

source/cli/metacallcli/include/metacallcli/application.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ class application
6161
protected:
6262
/* -- Protected Methods -- */
6363

64+
/**
65+
* @brief
66+
* Initialize the REPL
67+
*/
68+
void repl();
69+
70+
/**
71+
* @brief
72+
* Fallback argument parser
73+
*
74+
* @param[in] arguments
75+
* Vector of strings containing all the arguments from argv
76+
*
77+
*/
78+
void arguments_parse_fallback(std::vector<std::string> &arguments);
79+
6480
/**
6581
* @brief
6682
* Load all plugins from a subfolder @path

source/cli/metacallcli/source/application.cpp

Lines changed: 136 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -38,72 +38,51 @@ static bool exit_condition = true;
3838

3939
/* -- Methods -- */
4040

41-
// void application::parameter_iterator::operator()(const char *parameter)
42-
// {
43-
// // TODO: Implement a new plugin for parsing command line options
44-
45-
// std::string script(parameter);
46-
47-
// /* List of file extensions mapped into loader tags */
48-
// static std::unordered_map<std::string, std::string> extension_to_tag = {
49-
// /* Mock Loader */
50-
// { "mock", "mock" },
51-
// /* Python Loader */
52-
// { "py", "py" },
53-
// /* Ruby Loader */
54-
// { "rb", "rb" },
55-
// /* C# Loader */
56-
// { "cs", "cs" },
57-
// { "dll", "cs" },
58-
// { "vb", "cs" },
59-
// /* Cobol Loader */
60-
// { "cob", "cob" },
61-
// { "cbl", "cob" },
62-
// { "cpy", "cob" },
63-
// /* NodeJS Loader */
64-
// { "js", "node" },
65-
// { "node", "node" },
66-
// /* TypeScript Loader */
67-
// { "ts", "ts" },
68-
// { "jsx", "ts" },
69-
// { "tsx", "ts" },
70-
// /* WASM Loader */
71-
// { "wasm", "wasm" },
72-
// { "wat", "wasm" },
73-
// /* Rust Loader */
74-
// { "rs", "rs" },
75-
// /* C Loader */
76-
// { "c", "c" },
77-
// { "h", "c" },
78-
// /* Java Loader */
79-
// { "java", "java" },
80-
// { "jar", "java" },
81-
// /* RPC Loader */
82-
// { "rpc", "rpc" }
83-
84-
// // TODO: Implement handling of duplicated extensions, load the file with all loaders (trial and error)
85-
86-
// // /* Extension Loader */
87-
// // { "so", "ext" },
88-
// // { "dylib", "ext" },
89-
// // { "dll", "ext" },
90-
91-
// /* Note: By default js extension uses NodeJS loader instead of JavaScript V8 */
92-
// /* Probably in the future we can differenciate between them, but it is not trivial */
93-
// };
94-
95-
// const std::string tag = extension_to_tag[script.substr(script.find_last_of(".") + 1)];
96-
// const std::string safe_tag = tag != "" ? tag : "file"; /* Use File Loader if the tag is not found */
97-
98-
// /* Load the script */
99-
// void *args[2] = {
100-
// metacall_value_create_string(safe_tag.c_str(), safe_tag.length()),
101-
// metacall_value_create_string(script.c_str(), script.length())
102-
// };
103-
104-
// app.invoke("load", args, 2);
105-
// exit_condition = true;
106-
// }
41+
void application::repl()
42+
{
43+
/* Initialize CLI plugin */
44+
if (!load_path("cli", &plugin_cli_handle))
45+
{
46+
/* Do not enter into the main loop */
47+
exit_condition = true;
48+
return;
49+
}
50+
51+
/* Register exit function */
52+
auto exit = [](size_t argc, void *args[], void *data) -> void * {
53+
(void)args;
54+
(void)data;
55+
56+
/* Validate function parameters */
57+
if (argc != 0)
58+
{
59+
std::cout << "Invalid number of arguments passed to exit, expected 0, received: " << argc << std::endl;
60+
}
61+
62+
std::cout << "Exiting ..." << std::endl;
63+
64+
/* Exit from main loop */
65+
exit_condition = true;
66+
67+
return NULL;
68+
};
69+
70+
int result = metacall_register_loaderv(metacall_loader("ext"), plugin_cli_handle, "exit", exit, METACALL_INVALID, 0, NULL);
71+
72+
if (result != 0)
73+
{
74+
std::cout << "Exit function was not registered properly, return code: " << result << std::endl;
75+
}
76+
else
77+
{
78+
/* Start the main loop */
79+
exit_condition = false;
80+
}
81+
82+
void *ret = metacallhv_s(plugin_repl_handle, "initialize", metacall_null_args, 0);
83+
84+
check_for_exception(ret);
85+
}
10786

10887
application::application(int argc, char *argv[]) :
10988
plugin_cli_handle(NULL), plugin_repl_handle(NULL)
@@ -121,76 +100,55 @@ application::application(int argc, char *argv[]) :
121100
/* Print MetaCall information */
122101
metacall_print_info();
123102

124-
/* Initialize REPL plugins */
103+
/* Initialize REPL plugin */
125104
if (!load_path("repl", &plugin_repl_handle))
126105
{
127106
/* Do not enter into the main loop */
128107
exit_condition = true;
129-
plugin_repl_handle = NULL;
130108
return;
131109
}
132110

133111
if (argc == 1)
134112
{
135-
void *ret = metacallhv_s(plugin_repl_handle, "initialize", metacall_null_args, 0);
136-
137-
check_for_exception(ret);
113+
/* Launch the REPL */
114+
repl();
138115
}
139116
else
140117
{
141118
void *arguments_parse_func = metacall_handle_function(plugin_repl_handle, "arguments_parse");
142119

143120
if (arguments_parse_func == NULL)
144121
{
122+
std::cout << "Warning: CLI Arguments Parser was not loaded, "
123+
"using fallback argument parser with positional arguments only. "
124+
<< std::endl
125+
<< "Any command line option like '--help' will result into error. "
126+
"Only files are allowed: $ metacall a.py b.js c.rb"
127+
<< std::endl;
128+
145129
/* Use fallback parser, it can execute files but does not support command line arguments as options (i.e: -h, --help) */
146130
/* Parse program arguments if any (e.g metacall (0) a.py (1) b.js (2) c.rb (3)) */
131+
std::vector<std::string> arguments(argv + 1, argv + argc);
147132

148-
// TODO
149-
exit_condition = true;
150-
return;
133+
arguments_parse_fallback(arguments);
151134
}
152135
else
153136
{
154137
/* TODO: Implement a new plugin for parsing command line options */
155138
std::cout << "TODO: CLI Arguments Parser Plugin is not implemented yet" << std::endl;
156-
exit_condition = true;
157-
return;
158-
}
159-
}
160-
161-
/* Initialize CLI plugins */
162-
if (load_path("cli", &plugin_cli_handle))
163-
{
164-
/* Register exit function */
165-
auto exit = [](size_t argc, void *args[], void *data) -> void * {
166-
(void)args;
167-
(void)data;
168-
169-
/* Validate function parameters */
170-
if (argc != 0)
171-
{
172-
std::cout << "Invalid number of arguments passed to exit, expected 0, received: " << argc << std::endl;
173-
}
174-
175-
std::cout << "Exiting ..." << std::endl;
176139

177-
/* Exit from main loop */
178-
exit_condition = true;
179-
180-
return NULL;
181-
};
182-
183-
int result = metacall_register_loaderv(metacall_loader("ext"), plugin_cli_handle, "exit", exit, METACALL_INVALID, 0, NULL);
184-
185-
if (result != 0)
186-
{
187-
std::cout << "Exit function was not registered properly, return code: " << result << std::endl;
188-
}
189-
else
190-
{
191-
/* Start the main loop */
192-
exit_condition = false;
140+
/* Note: If it has zero positional arguments, we should also run the repl, for example:
141+
* $ metacall --some-option --another-option --yeet
142+
*/
143+
// TODO:
144+
// if (positional_arguments_size == 0)
145+
// {
146+
// /* Initialize the REPL */
147+
// repl();
148+
// }
193149
}
150+
151+
exit_condition = true;
194152
}
195153
}
196154

@@ -204,6 +162,74 @@ application::~application()
204162
}
205163
}
206164

165+
void application::arguments_parse_fallback(std::vector<std::string> &arguments)
166+
{
167+
/* List of file extensions mapped into loader tags */
168+
static std::unordered_map<std::string, std::string> extension_to_tag = {
169+
/* Mock Loader */
170+
{ "mock", "mock" },
171+
/* Python Loader */
172+
{ "py", "py" },
173+
/* Ruby Loader */
174+
{ "rb", "rb" },
175+
/* C# Loader */
176+
{ "cs", "cs" },
177+
{ "dll", "cs" },
178+
{ "vb", "cs" },
179+
/* Cobol Loader */
180+
{ "cob", "cob" },
181+
{ "cbl", "cob" },
182+
{ "cpy", "cob" },
183+
/* NodeJS Loader */
184+
{ "js", "node" },
185+
{ "node", "node" },
186+
/* TypeScript Loader */
187+
{ "ts", "ts" },
188+
{ "jsx", "ts" },
189+
{ "tsx", "ts" },
190+
/* WASM Loader */
191+
{ "wasm", "wasm" },
192+
{ "wat", "wasm" },
193+
/* Rust Loader */
194+
{ "rs", "rs" },
195+
/* C Loader */
196+
{ "c", "c" },
197+
{ "h", "c" },
198+
/* Java Loader */
199+
{ "java", "java" },
200+
{ "jar", "java" },
201+
/* RPC Loader */
202+
{ "rpc", "rpc" }
203+
204+
// TODO: Implement handling of duplicated extensions, load the file with all loaders (trial and error)
205+
206+
// /* Extension Loader */
207+
// { "so", "ext" },
208+
// { "dylib", "ext" },
209+
// { "dll", "ext" },
210+
211+
/* Note: By default js extension uses NodeJS loader instead of JavaScript V8 */
212+
/* Probably in the future we can differenciate between them, but it is not trivial */
213+
};
214+
215+
for (std::string script : arguments)
216+
{
217+
const std::string tag = extension_to_tag[script.substr(script.find_last_of(".") + 1)];
218+
const std::string safe_tag = tag != "" ? tag : "file"; /* Use File Loader if the tag is not found */
219+
220+
/* Load the script */
221+
const char *scripts[1] = {
222+
script.c_str()
223+
};
224+
225+
if (metacall_load_from_file(safe_tag.c_str(), scripts, 1, NULL) != 0)
226+
{
227+
/* Stop loading more scripts */
228+
return;
229+
}
230+
}
231+
}
232+
207233
bool application::load_path(const char *path, void **handle)
208234
{
209235
/* Get core plugin path and handle in order to load cli plugins */

0 commit comments

Comments
 (0)