3737#include < string_view>
3838#include < vector>
3939
40- #include " tiny-process-library/process.hpp "
40+ #include " fmt/format.h "
4141#include " libcufetch/common.hh"
4242#include " libcufetch/config.hh"
4343#include " libcufetch/cufetch.hh"
44- #include " fmt/format.h"
4544#include " switch_fnv1a.hpp"
45+ #include " tiny-process-library/process.hpp"
4646#include " util.hpp"
4747
4848class Parser
@@ -194,10 +194,11 @@ EXPORT std::string parse(const std::string& input, parse_args_t& parse_args)
194194 parse_args.config , parse_args.parsingLayout , parse_args.no_more_reset );
195195}
196196
197- std::string get_and_color_percentage (const float n1, const float n2, parse_args_t & parse_args, const bool invert)
197+ EXPORT std::string get_and_color_percentage (const float n1, const float n2, parse_args_t & parse_args, const bool invert)
198198{
199- const std::vector<std::string>& percentage_colors = parse_args.config .getValueArrayStr (" config.percentage-colors" , {" green" , " yellow" , " red" });
200- const float result = n1 / n2 * static_cast <float >(100 );
199+ const std::vector<std::string>& percentage_colors =
200+ parse_args.config .getValueArrayStr (" config.percentage-colors" , { " green" , " yellow" , " red" });
201+ const float result = n1 / n2 * static_cast <float >(100 );
201202
202203 std::string color;
203204 if (!invert)
@@ -222,83 +223,136 @@ std::string get_and_color_percentage(const float n1, const float n2, parse_args_
222223 return parse (fmt::format (" {}{:.2f}%${{0}}" , color, result), _, parse_args);
223224}
224225
225- std::string getInfoFromName (parse_args_t & parse_args, const std::string& moduleName)
226- {
227- std::string name;
228- name.reserve (moduleName.size ());
229-
230- /* true when we find a '(' */
231- bool collecting = false ;
232-
233- /* current position */
234- size_t i = -1 ;
235- size_t stripped_char_count = 0 ; /* amount of chars stripped from `name` */
226+ static std::string parse (Parser& parser, moduleArgs_t* moduleArg, bool collecting = false , const char until = 0 );
236227
237- /* position of start, resets every separator */
238- size_t start_pos = 0 ;
239-
240- moduleArgs_t* moduleArgs = new moduleArgs_t ;
228+ static std::optional<std::string> parse_module (Parser& p)
229+ {
230+ if (!p. try_read ( ' ( ' ))
231+ return {} ;
241232
242- /* argument that's collected from what's between the parenthesis in "module(...).test" */
233+ // collect everything up to the matching ')', allowing '.' inside
243234 std::string arg;
244- arg. reserve (moduleName. size ()) ;
245- for ( const char c : moduleName )
235+ int depth = 1 ;
236+ while (!p. is_eof () && depth > 0 )
246237 {
247- i++;
248- if (c == ' (' && !collecting)
238+ char c = p.read_char ();
239+ if (c == ' \\ ' )
240+ { // escaped char
241+ if (!p.is_eof ())
242+ arg.push_back (p.read_char ());
243+ }
244+ else if (c == ' (' )
249245 {
250- collecting = true ;
251- continue ;
246+ ++depth ;
247+ arg. push_back ( ' ( ' ) ;
252248 }
253-
254- if ((c == ' .' || i + 1 == moduleName.size ()))
249+ else if (c == ' )' )
255250 {
256- if (collecting)
257- {
258- if (arg.back () != ' )' && c != ' )' )
259- die (" Module name `{}` is invalid. Arguments must end with )" , moduleName);
251+ --depth;
252+ if (depth > 0 )
253+ arg.push_back (' )' );
254+ }
255+ else
256+ {
257+ arg.push_back (c);
258+ }
259+ }
260260
261- if (arg.back () == ' )' )
262- arg.pop_back ();
261+ if (depth != 0 )
262+ {
263+ error (_ (" PARSER: Missing closing ')' in string '{}'" ), p.src );
264+ }
265+ return arg;
266+ }
263267
264- moduleArgs_t* moduleArg = moduleArgs;
265- while (moduleArg->next != nullptr )
266- moduleArg = moduleArg->next ;
268+ // Parse module path with optional arguments
269+ static std::string parse (Parser& p, moduleArgs_t* m, bool collecting, char until)
270+ {
271+ std::string token;
267272
268- moduleArg->name = std::string{ name.begin () + start_pos, name.end () };
269- moduleArg->value = arg;
270- moduleArg->next = new moduleArgs_t;
271- moduleArg->next ->prev = moduleArg;
273+ while (until ? !p.try_read (until) : !p.is_eof ())
274+ {
275+ if (until && p.is_eof ())
276+ {
277+ error (_ (" PARSER: Missing closing '{}' in string '{}'" ), until, p.src );
278+ break ;
279+ }
272280
273- if (c == ' .' )
274- {
275- name.push_back (' .' );
276- stripped_char_count++;
277- }
278- }
279- else
281+ if (p.try_read (' \\ ' ))
282+ { // escape
283+ if (!p.is_eof ())
284+ token.push_back (p.read_char ());
285+ }
286+ else if (auto arg = parse_module (p))
287+ { // found (...) argument
288+ m->name = token;
289+ m->value = *arg;
290+ m->next = new moduleArgs_t;
291+ m->next ->prev = m;
292+ m = m->next ;
293+ token.clear ();
294+ }
295+ else if (!collecting && p.try_read (' .' ))
296+ { // separator
297+ if (!token.empty ())
280298 {
281- name.push_back (c);
299+ m->name = token;
300+ m->value = " " ;
301+ m->next = new moduleArgs_t;
302+ m->next ->prev = m;
303+ m = m->next ;
304+ token.clear ();
282305 }
283-
284- start_pos = i + 1 - stripped_char_count;
285- arg = " " ;
286- collecting = false ;
287-
288- continue ;
289306 }
290-
291- if (!collecting)
307+ else
292308 {
293- name .push_back (c );
309+ token .push_back (p. read_char () );
294310 }
295- else
311+ }
312+
313+ if (!collecting && !token.empty ())
314+ {
315+ m->name = token;
316+ m->value = " " ;
317+ m->next = nullptr ; // end of list
318+ }
319+ else if (!collecting)
320+ {
321+ m->next = nullptr ;
322+ }
323+
324+ return token;
325+ }
326+
327+ std::string getInfoFromName (parse_args_t & parse_args, const std::string& moduleName)
328+ {
329+ Parser parser (moduleName, _);
330+ moduleArgs_t* moduleArgs = new moduleArgs_t;
331+ parse (parser, moduleArgs);
332+
333+ if (debug_print)
334+ {
335+ debug (" moduleName = {}" , moduleName);
336+ auto * debug_arg = moduleArgs;
337+ size_t i = 0 ;
338+ while (debug_arg->next )
296339 {
297- stripped_char_count++;
298- arg.push_back (c);
340+ debug (" moduleArg[{}]\t name = '{}' && arg = '{}'" , i, debug_arg->name , debug_arg->value );
341+ debug_arg = debug_arg->next ;
342+ i++;
299343 }
300344 }
301345
346+ std::string name;
347+ moduleArgs_t* moduleArg = moduleArgs;
348+ while (moduleArg->next )
349+ {
350+ name += moduleArg->name + " ." ;
351+ moduleArg = moduleArg->next ;
352+ }
353+ name.pop_back ();
354+ debug (" name = {}" , name);
355+
302356 std::string result = " (unknown/invalid module)" ;
303357 if (const auto & it = parse_args.modulesInfo .find (name); it != parse_args.modulesInfo .end ())
304358 {
@@ -354,8 +408,8 @@ std::optional<std::string> parse_command_tag(Parser& parser, parse_args_t& parse
354408 if (removetag)
355409 command.erase (0 , 1 );
356410
357- std::string cmd_output;
358- TinyProcessLib::Process proc (command, " " , [&](const char * bytes, size_t n){ cmd_output.assign (bytes, n);});
411+ std::string cmd_output;
412+ TinyProcessLib::Process proc (command, " " , [&](const char * bytes, size_t n) { cmd_output.assign (bytes, n); });
359413 if (!parse_args.parsingLayout && !removetag && parser.dollar_pos != std::string::npos)
360414 parse_args.pureOutput .replace (parser.dollar_pos , command.length () + " $()" _len, cmd_output);
361415
@@ -396,7 +450,7 @@ std::optional<std::string> parse_color_tag(Parser& parser, parse_args_t& parse_a
396450 if (output[0 ] == ' $' )
397451 output += ' ' ;
398452#endif
399-
453+
400454 static std::vector<std::string> alias_colors_name, alias_colors_value;
401455 const std::vector<std::string>& alias_colors = config.getValueArrayStr (" config.alias-colors" , {});
402456 if (!alias_colors.empty () && (alias_colors_name.empty () && alias_colors_value.empty ()))
@@ -406,7 +460,8 @@ std::optional<std::string> parse_color_tag(Parser& parser, parse_args_t& parse_a
406460 const size_t pos = str.find (' =' );
407461 if (pos == std::string::npos)
408462 die (_ (" alias color '{}' does NOT have an equal sign '=' for separating color name and value\n "
409- " For more check with --help" ), str);
463+ " For more check with --help" ),
464+ str);
410465
411466 alias_colors_name.push_back (str.substr (0 , pos));
412467 alias_colors_value.push_back (str.substr (pos + 1 ));
@@ -793,10 +848,10 @@ std::string parse(Parser& parser, parse_args_t& parse_args, const bool evaluate,
793848}
794849
795850EXPORT std::string parse (std::string input, const moduleMap_t& modulesInfo, std::string& pureOutput,
796- std::vector<std::string>& layout, std::vector<std::string>& tmp_layout, const ConfigBase& config ,
797- const bool parsingLayout, bool & no_more_reset)
851+ std::vector<std::string>& layout, std::vector<std::string>& tmp_layout,
852+ const ConfigBase& config, const bool parsingLayout, bool & no_more_reset)
798853{
799- const std::string& sep_reset = config.getValue <std::string>(" config.sep-reset" , " :" );
854+ static const std::string& sep_reset = config.getValue <std::string>(" config.sep-reset" , " :" );
800855 if (!sep_reset.empty () && parsingLayout && !no_more_reset)
801856 {
802857 if (config.getValue (" config.sep-reset-after" , false ))
0 commit comments