LCOV - code coverage report
Current view: top level - advgetopt - advgetopt_usage.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 293 298 98.3 %
Date: 2024-10-05 13:34:54 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2006-2024  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/advgetopt
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : /** \file
      21             :  * \brief Advanced getopt usage() implementation.
      22             :  *
      23             :  * The advgetopt class usage() and helper functions are grouped in this
      24             :  * file.
      25             :  */
      26             : 
      27             : // self
      28             : //
      29             : #include    "advgetopt/advgetopt.h"
      30             : 
      31             : #include    "advgetopt/exception.h"
      32             : 
      33             : 
      34             : // snapdev
      35             : //
      36             : #include    <snapdev/join_strings.h>
      37             : #include    <snapdev/tokenize_format.h>
      38             : 
      39             : 
      40             : // C++
      41             : //
      42             : #include    <iomanip>
      43             : #include    <iostream>
      44             : 
      45             : 
      46             : // last include
      47             : //
      48             : #include    <snapdev/poison.h>
      49             : 
      50             : 
      51             : 
      52             : 
      53             : namespace advgetopt
      54             : {
      55             : 
      56             : 
      57             : 
      58             : /** \brief Transform group names in --\<name>-help commands.
      59             :  *
      60             :  * This function allows for the group names to be transformed into help
      61             :  * command line options.
      62             :  */
      63         355 : void getopt::parse_options_from_group_names()
      64             : {
      65             :     // add the --long-help if at least one option uses the GROUP1, GROUP2,
      66             :     // or SYSTEM
      67             :     //
      68             :     // add the --system-help if at least one option uses SYSTEM
      69             :     //
      70         355 :     bool add_long_help(false);
      71         355 :     bool add_system_help(false);
      72             : 
      73         355 :     for(auto it(f_options_by_name.begin())
      74        1999 :       ; it != f_options_by_name.end()
      75        1644 :       ; ++it)
      76             :     {
      77        1644 :         if(it->second->has_flag(GETOPT_FLAG_SHOW_GROUP1 | GETOPT_FLAG_SHOW_GROUP2 | GETOPT_FLAG_SHOW_SYSTEM))
      78             :         {
      79         790 :             add_long_help = true;
      80             :         }
      81             : 
      82        1644 :         if(it->second->has_flag(GETOPT_FLAG_SHOW_SYSTEM))
      83             :         {
      84         760 :             add_system_help = true;
      85             :         }
      86             :     }
      87             : 
      88         355 :     if(add_long_help)
      89             :     {
      90          99 :         option_info::pointer_t opt(std::make_shared<option_info>("long-help"));
      91          99 :         opt->add_flag(GETOPT_FLAG_COMMAND_LINE
      92             :                     | GETOPT_FLAG_FLAG
      93             :                     | GETOPT_FLAG_GROUP_COMMANDS);
      94          99 :         opt->set_help("show all the help from all the available options.");
      95          99 :         f_options_by_name["long-help"] = opt;
      96          99 :         if(f_options_by_short_name.find(L'?') == f_options_by_short_name.end())
      97             :         {
      98          99 :             opt->set_short_name(L'?');
      99          99 :             f_options_by_short_name[L'?'] = opt;
     100             :         }
     101          99 :     }
     102             : 
     103         355 :     if(add_system_help)
     104             :     {
     105          95 :         option_info::pointer_t opt(std::make_shared<option_info>("system-help"));
     106          95 :         opt->add_flag(GETOPT_FLAG_COMMAND_LINE
     107             :                     | GETOPT_FLAG_FLAG
     108             :                     | GETOPT_FLAG_GROUP_COMMANDS);
     109          95 :         opt->set_help("show commands and options added by libraries.");
     110          95 :         f_options_by_name["system-help"] = opt;
     111          95 :         if(f_options_by_short_name.find(L'S') == f_options_by_short_name.end())
     112             :         {
     113          91 :             opt->set_short_name(L'S');
     114          91 :             f_options_by_short_name[L'S'] = opt;
     115             :         }
     116          95 :     }
     117             : 
     118         355 :     if(f_options_environment.f_groups == nullptr)
     119             :     {
     120             :         // no groups, ignore following loop
     121             :         //
     122         321 :         return;
     123             :     }
     124             : 
     125         102 :     for(group_description const * grp = f_options_environment.f_groups
     126         102 :       ; grp->f_group != GETOPT_FLAG_GROUP_NONE
     127             :       ; ++grp)
     128             :     {
     129             :         // the name is not mandatory, without it you do not get the command
     130             :         // line option but still get the group description
     131             :         //
     132          68 :         if(grp->f_name != nullptr
     133           6 :         && *grp->f_name != '\0')
     134             :         {
     135          12 :             std::string const name(grp->f_name);
     136           6 :             std::string const option_name(name + "-help");
     137           6 :             option_info::pointer_t opt(std::make_shared<option_info>(option_name));
     138           6 :             opt->add_flag(GETOPT_FLAG_COMMAND_LINE
     139             :                         | GETOPT_FLAG_FLAG
     140             :                         | GETOPT_FLAG_GROUP_COMMANDS);
     141          12 :             opt->set_help("show help from the \""
     142          12 :                         + name
     143          18 :                         + "\" group of options.");
     144           6 :             f_options_by_name[option_name] = opt;
     145           6 :         }
     146             :     }
     147             : }
     148             : 
     149             : 
     150             : /** \brief Search for \p group in the list of group names.
     151             :  *
     152             :  * This function is used to search for the name of a group.
     153             :  *
     154             :  * Groups are used by the usage() function to list options by some user
     155             :  * selected group.
     156             :  *
     157             :  * For example, it is often that a tool has a set of commands such as
     158             :  * `--delete` and a set of options such as `--verbose`. These can represent
     159             :  * to clear groups of commands and options.
     160             :  *
     161             :  * \param[in] group  The group to look for (i.e. GETOPT_FLAG_GROUP_ONE).
     162             :  *
     163             :  * \return The group structure or nullptr when not found.
     164             :  */
     165          45 : group_description const * getopt::find_group(flag_t group) const
     166             : {
     167          45 :     if(f_options_environment.f_groups == nullptr)
     168             :     {
     169           2 :         return nullptr;
     170             :     }
     171             : 
     172          43 :     if((group & ~GETOPT_FLAG_GROUP_MASK) != 0)
     173             :     {
     174          29 :         throw getopt_logic_error("group parameter must represent a valid group.");
     175             :     }
     176          14 :     if(group == GETOPT_FLAG_GROUP_NONE)
     177             :     {
     178           1 :         throw getopt_logic_error("group NONE cannot be assigned a name so you cannot search for it.");
     179             :     }
     180             : 
     181          21 :     for(group_description const * grp(f_options_environment.f_groups)
     182          21 :       ; grp->f_group != GETOPT_FLAG_GROUP_NONE
     183             :       ; ++grp)
     184             :     {
     185          20 :         if(group == grp->f_group)
     186             :         {
     187          12 :             if((grp->f_name == nullptr || *grp->f_name == '\0')
     188           2 :             && (grp->f_description == nullptr || *grp->f_description == '\0'))
     189             :             {
     190           2 :                 throw getopt_logic_error("at least one of a group name or description must be defined (a non-empty string).");
     191             :             }
     192          10 :             return grp;
     193             :         }
     194             :     }
     195             : 
     196             :     // group not defined
     197             :     //
     198           1 :     return nullptr;
     199             : }
     200             : 
     201             : 
     202             : /** \brief Create a string of the command line arguments.
     203             :  *
     204             :  * This function assembles the command line arguments in a string and
     205             :  * returns that string.
     206             :  *
     207             :  * The function has the ability to wrap strings around for better formatting.
     208             :  *
     209             :  * The list of arguments to show is defined by the \p show parameter. When
     210             :  * \p show is 0, then only the regular and error arguments are shown.
     211             :  * Otherwise only the argumenst with the specified flags are show. Only
     212             :  * the `..._SHOW_...` flags are valid here.
     213             :  *
     214             :  * When an error occurs, it is customary to set \p show to
     215             :  * GETOPT_FLAG_SHOW_USAGE_ON_ERROR so only a limited set of arguments
     216             :  * are shown.
     217             :  *
     218             :  * The library offers two groups in case you have a command line tools
     219             :  * with a large number of options, those two can be used to only show
     220             :  * those specific set of options with using a specific `--help` argument.
     221             :  *
     222             :  * \note
     223             :  * This function does NOT print anything in the output. This is your
     224             :  * responsibility. We do it this way because you may be using a logger
     225             :  * and not want to print the usage in the \em wrong destination.
     226             :  *
     227             :  * \bug
     228             :  * The options are written from our map. This means the order will be
     229             :  * alphabetical and not the order in which you defined the options.
     230             :  * We are not looking into fixing this problem. That's just something
     231             :  * you want to keep in mind.
     232             :  *
     233             :  * \param[in] show  Selection of the options to show.
     234             :  *
     235             :  * \return The assembled command line arguments.
     236             :  */
     237          80 : std::string getopt::usage(flag_t show) const
     238             : {
     239          80 :     std::stringstream ss;
     240             : 
     241          80 :     flag_t specific_group(show & GETOPT_FLAG_GROUP_MASK);
     242             : 
     243             :     // ignore all the non-show flags
     244             :     //
     245          80 :     show &= GETOPT_FLAG_SHOW_USAGE_ON_ERROR
     246             :           | GETOPT_FLAG_SHOW_ALL
     247             :           | GETOPT_FLAG_SHOW_GROUP1
     248             :           | GETOPT_FLAG_SHOW_GROUP2
     249             :           | GETOPT_FLAG_SHOW_SYSTEM;
     250             : 
     251          80 :     size_t const line_width(get_screen_width());
     252          80 :     ss << breakup_line(process_help_string(f_options_environment.f_help_header), 0, line_width);
     253             : 
     254          80 :     std::string save_default;
     255          80 :     std::string save_help;
     256             : 
     257          80 :     flag_t pos(GETOPT_FLAG_GROUP_MINIMUM);
     258          80 :     flag_t group_max(GETOPT_FLAG_GROUP_MAXIMUM);
     259          80 :     if(f_options_environment.f_groups == nullptr)
     260             :     {
     261          73 :         group_max = GETOPT_FLAG_GROUP_MINIMUM;
     262          73 :         specific_group = GETOPT_FLAG_GROUP_NONE;
     263             :     }
     264           7 :     else if(specific_group != GETOPT_FLAG_GROUP_NONE)
     265             :     {
     266             :         // only display that specific group if asked to do so
     267             :         //
     268           2 :         pos = specific_group >> GETOPT_FLAG_GROUP_SHIFT;
     269           2 :         group_max = pos;
     270             :     }
     271             : 
     272          80 :     std::multimap<advgetopt::option_info::pointer_t, advgetopt::option_info::pointer_t> alias_reverse_references;
     273         372 :     for(auto const & opt : f_options_by_name)
     274             :     {
     275         292 :         if(!opt.second->has_flag(GETOPT_FLAG_ALIAS))
     276             :         {
     277         280 :             continue;
     278             :         }
     279          12 :         alias_reverse_references.insert(std::make_pair(opt.second->get_alias_destination(), opt.second));
     280             :     }
     281             : 
     282         195 :     for(; pos <= group_max; ++pos)
     283             :     {
     284         115 :         bool group_name_shown(false);
     285         115 :         flag_t const group(pos << GETOPT_FLAG_GROUP_SHIFT);
     286         897 :         for(auto const & opt : f_options_by_name)
     287             :         {
     288         782 :             if((opt.second->get_flags() & GETOPT_FLAG_GROUP_MASK) != group
     289         782 :             && f_options_environment.f_groups != nullptr)
     290             :             {
     291             :                 // this could be optimized but we'd probably not see much
     292             :                 // difference overall and it's just for the usage() call
     293             :                 //
     294         509 :                 continue;
     295             :             }
     296             : 
     297         273 :             std::string const help(opt.second->get_help());
     298         273 :             if(help.empty())
     299             :             {
     300             :                 // ignore entries without help
     301             :                 //
     302          10 :                 continue;
     303             :             }
     304             : 
     305         263 :             if(opt.second->has_flag(GETOPT_FLAG_ALIAS))
     306             :             {
     307             :                 // ignore entries representing an alias
     308             :                 //
     309          12 :                 continue;
     310             :             }
     311             : 
     312         251 :             if((show & GETOPT_FLAG_SHOW_ALL) == 0)
     313             :             {
     314         189 :                 if(show != 0)
     315             :                 {
     316          66 :                     if(!opt.second->has_flag(show))
     317             :                     {
     318             :                         // usage selected group is not present in this option, ignore
     319             :                         //
     320          58 :                         continue;
     321             :                     }
     322             :                 }
     323         123 :                 else if(opt.second->has_flag(GETOPT_FLAG_SHOW_GROUP1
     324             :                                            | GETOPT_FLAG_SHOW_GROUP2
     325             :                                            | GETOPT_FLAG_SHOW_SYSTEM))
     326             :                 {
     327             :                     // do not show specialized groups
     328             :                     //
     329          22 :                     continue;
     330             :                 }
     331             :             }
     332             : 
     333         171 :             if(!group_name_shown)
     334             :             {
     335          85 :                 group_name_shown = true;
     336             : 
     337          85 :                 if(group != GETOPT_FLAG_GROUP_NONE)
     338             :                 {
     339           8 :                     group_description const * grp(find_group(group));
     340           8 :                     if(grp != nullptr)
     341             :                     {
     342           8 :                         ss << std::endl
     343           8 :                            << breakup_line(process_help_string(grp->f_description), 0, line_width);
     344             :                     }
     345             :                 }
     346             :             }
     347             : 
     348         171 :             std::stringstream argument;
     349             : 
     350         171 :             if(opt.second->is_default_option())
     351             :             {
     352           6 :                 switch(opt.second->get_flags() & (GETOPT_FLAG_REQUIRED | GETOPT_FLAG_MULTIPLE))
     353             :                 {
     354           1 :                 case 0:
     355           1 :                     argument << "[default argument]";
     356           1 :                     break;
     357             : 
     358           1 :                 case GETOPT_FLAG_REQUIRED:
     359           1 :                     argument << "<default argument>";
     360           1 :                     break;
     361             : 
     362           2 :                 case GETOPT_FLAG_MULTIPLE:
     363           2 :                     argument << "[default arguments]";
     364           2 :                     break;
     365             : 
     366           2 :                 case GETOPT_FLAG_REQUIRED | GETOPT_FLAG_MULTIPLE:
     367           2 :                     argument << "<default arguments>";
     368           2 :                     break;
     369             : 
     370             :                 }
     371             :             }
     372             :             else
     373             :             {
     374         165 :                 argument << "--" << opt.second->get_name();
     375         165 :                 auto aliases(alias_reverse_references.lower_bound(opt.second));
     376         165 :                 if(aliases->first == opt.second)
     377             :                 {
     378           6 :                     auto end(alias_reverse_references.upper_bound(opt.second));
     379          12 :                     for(auto a(aliases); a != end; ++a)
     380             :                     {
     381           6 :                         argument << " or --" << a->second->get_name();
     382             :                     }
     383             :                 }
     384         165 :                 if(opt.second->get_short_name() != NO_SHORT_NAME)
     385             :                 {
     386          50 :                     argument << " or -" << short_name_to_string(opt.second->get_short_name());
     387             :                 }
     388         165 :                 if(aliases->first == opt.second)
     389             :                 {
     390           6 :                     auto end(alias_reverse_references.upper_bound(opt.second));
     391          12 :                     for(; aliases != end; ++aliases)
     392             :                     {
     393           6 :                         if(aliases->second->get_short_name() != NO_SHORT_NAME)
     394             :                         {
     395           0 :                             argument << " or -" << short_name_to_string(aliases->second->get_short_name());
     396             :                         }
     397             :                     }
     398             :                 }
     399             : 
     400         165 :                 switch(opt.second->get_flags() & (GETOPT_FLAG_FLAG | GETOPT_FLAG_REQUIRED | GETOPT_FLAG_MULTIPLE))
     401             :                 {
     402           1 :                 case 0:
     403           1 :                     argument << " [<arg>]";
     404           1 :                     break;
     405             : 
     406          34 :                 case GETOPT_FLAG_REQUIRED:
     407          34 :                     argument << " <arg>";
     408          34 :                     break;
     409             : 
     410           8 :                 case GETOPT_FLAG_MULTIPLE:
     411           8 :                     argument << " {<arg>}";
     412           8 :                     break;
     413             : 
     414           6 :                 case GETOPT_FLAG_REQUIRED | GETOPT_FLAG_MULTIPLE:
     415           6 :                     argument << " <arg> {<arg>}";
     416           6 :                     break;
     417             : 
     418             :                 }
     419             :             }
     420             : 
     421         171 :             if(opt.second->has_flag(GETOPT_FLAG_DYNAMIC_CONFIGURATION))
     422             :             {
     423           0 :                 argument << "*";
     424             :             }
     425             : 
     426         171 :             if(opt.second->has_default())
     427             :             {
     428             :                 argument << " (default is \""
     429           9 :                          << opt.second->get_default()
     430          18 :                          << "\")";
     431             :             }
     432             : 
     433             :             // Output argument string with help
     434             :             //
     435         171 :             if(opt.second->is_default_option())
     436             :             {
     437           6 :                 save_default = argument.str();
     438           6 :                 save_help = help;
     439             :             }
     440             :             else
     441             :             {
     442         165 :                 std::string variable_name;
     443         165 :                 if(!opt.second->get_environment_variable_name().empty())
     444             :                 {
     445           2 :                     variable_name += "\nEnvironment Variable Name: \"";
     446           2 :                     if(f_options_environment.f_environment_variable_intro != nullptr)
     447             :                     {
     448           2 :                         variable_name += f_options_environment.f_environment_variable_intro;
     449             :                     }
     450           2 :                     variable_name += opt.second->get_environment_variable_name();
     451           2 :                     variable_name += '"';
     452             :                 }
     453         495 :                 ss << format_usage_string(argument.str()
     454         330 :                                         , process_help_string((help + variable_name).c_str())
     455             :                                         , 30
     456         165 :                                         , line_width);
     457         165 :             }
     458         273 :         }
     459             :     }
     460             : 
     461          80 :     if(!save_default.empty())
     462             :     {
     463          18 :         ss << format_usage_string(save_default
     464          12 :                                 , process_help_string(save_help.c_str())
     465             :                                 , 30
     466           6 :                                 , line_width);
     467             :     }
     468             : 
     469          80 :     if(f_options_environment.f_help_footer != nullptr
     470          78 :     && f_options_environment.f_help_footer[0] != '\0')
     471             :     {
     472          78 :         ss << std::endl;
     473          78 :         ss << breakup_line(process_help_string(f_options_environment.f_help_footer), 0, line_width);
     474             :     }
     475             : 
     476         160 :     return ss.str();
     477          80 : }
     478             : 
     479             : 
     480             : class usage_flag_traits
     481             : {
     482             : public:
     483             :     static constexpr snapdev::format_flag_t const       FORMAT_FLAG_EXTENDED    = 0x01; // '*'
     484             : 
     485         514 :     static bool is_flag(char c, snapdev::format_item<char> & f)
     486             :     {
     487         514 :         switch(c)
     488             :         {
     489          98 :         case '*':
     490          98 :             if(f.has_flags(FORMAT_FLAG_EXTENDED))
     491             :             {
     492           0 :                 f.add_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE);
     493             :             }
     494          98 :             f.add_flags(FORMAT_FLAG_EXTENDED);
     495          98 :             return true;
     496             : 
     497         416 :         default:
     498         416 :             return false;
     499             : 
     500             :         }
     501             :     }
     502             : };
     503             : 
     504             : 
     505             : class usage_letter_traits
     506             : {
     507             : public:
     508         416 :     static std::string::size_type is_format(char const * s, snapdev::format_item<char> & f)
     509             :     {
     510         416 :         switch(s[0])
     511             :         {
     512         416 :         case 'a':
     513             :         case 'b':
     514             :         case 'c':
     515             :         case 'd':
     516             :         case 'e':
     517             :         case 'E':
     518             :         case 'f':
     519             :         case 'g':
     520             :         case 'i':
     521             :         case 'l':
     522             :         case 'm':
     523             :         case 'o':
     524             :         case 'p':
     525             :         case 's':
     526             :         case 't':
     527             :         case 'v':
     528             :         case 'w':
     529         416 :             f.format(s[0]);
     530         416 :             return 1UL;
     531             : 
     532             :         }
     533             : 
     534           0 :         f.add_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN);
     535           0 :         return 0;
     536             :     }
     537             : };
     538             : 
     539             : 
     540             : /** \brief Change the % flags in help strings.
     541             :  *
     542             :  * This function goes through the help string and replaces the `%\<flag>`
     543             :  * with various content available in the getopt object.
     544             :  *
     545             :  * This is helpful for various reasons. For example, you may use the
     546             :  * same set of options in several different programs, in which case the
     547             :  * `%p` is likely useful to print out the name of the program currently
     548             :  * in use.
     549             :  *
     550             :  * Similarly we offer ways to print out lists of configuration files,
     551             :  * the environment variable name & value, etc. The following is the
     552             :  * list of supported flags:
     553             :  *
     554             :  * \li "%%" -- print out a percent
     555             :  * \li "%a" -- print out the project name (a.k.a. application name)
     556             :  * \li "%b" -- print out the build date
     557             :  * \li "%c" -- print out the copyright notice
     558             :  * \li "%d" -- print out the first directory with configuration files.
     559             :  * \li "%*d" -- print out the complete list of directories with configuration
     560             :  * files.
     561             :  * \li "%e" -- print out the name of the environment variable.
     562             :  * \li "%*e" -- print out the name and value of the environment variable.
     563             :  * \li "%f" -- print out the first configuration path and filename.
     564             :  * \li "%*f" -- print out all the configuration full paths.
     565             :  * \li "%g" -- print out the list of existing configuration files.
     566             :  * \li "%*g" -- print out the list of all possible configuration files.
     567             :  * \li "%i" -- print out the directory to option files.
     568             :  * \li "%l" -- print out the license.
     569             :  * \li "%o" -- show the configuration filename where changes get written.
     570             :  * \li "%p" -- print out the program basename.
     571             :  * \li "%*p" -- print out the full program name.
     572             :  * \li "%s" -- print out the group name.
     573             :  * \li "%t" -- print out the build time.
     574             :  * \li "%v" -- print out the version.
     575             :  * \li "%w" -- print out the list of all the writable configuration files.
     576             :  *
     577             :  * Here is an example where the `%p` can be used:
     578             :  *
     579             :  * \code
     580             :  *    "Usage: %p [-opt] filename ..."
     581             :  * \endcode
     582             :  *
     583             :  * The other flags are more often used in places like the copyright notice
     584             :  * the footer, the license notice, etc.
     585             :  *
     586             :  * \param[in] help  A string that may include `%` flags.
     587             :  *
     588             :  * \return The string with any '%\<flag>' replaced.
     589             :  *
     590             :  * \sa parse_program_name()
     591             :  */
     592         338 : std::string getopt::process_help_string(char const * help) const
     593             : {
     594         338 :     if(help == nullptr)
     595             :     {
     596           1 :         return std::string();
     597             :     }
     598             : 
     599         337 :     snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
     600             :               char
     601             :             , usage_letter_traits
     602        1011 :             , usage_flag_traits>(help));
     603             : 
     604        1404 :     for(auto it(items.begin()); it != items.end(); ++it)
     605             :     {
     606        1067 :         switch(it->format())
     607             :         {
     608          19 :         case 'a':
     609          19 :             if(f_options_environment.f_project_name != nullptr)
     610             :             {
     611          16 :                 it->string(f_options_environment.f_project_name);
     612             :             }
     613          19 :             break;
     614             : 
     615          19 :         case 'b':
     616          19 :             if(f_options_environment.f_build_date != nullptr)
     617             :             {
     618          16 :                 it->string(f_options_environment.f_build_date);
     619             :             }
     620          19 :             break;
     621             : 
     622          19 :         case 'c':
     623          19 :             if(f_options_environment.f_copyright != nullptr)
     624             :             {
     625          16 :                 it->string(f_options_environment.f_copyright);
     626             :             }
     627          19 :             break;
     628             : 
     629          38 :         case 'd':
     630          38 :             if(f_options_environment.f_configuration_directories != nullptr
     631          32 :             && *f_options_environment.f_configuration_directories != nullptr)
     632             :             {
     633          26 :                 if(it->has_flags(usage_flag_traits::FORMAT_FLAG_EXTENDED))
     634             :                 {
     635          13 :                     std::string joined;
     636          65 :                     for(char const * const * directories(f_options_environment.f_configuration_directories);
     637          65 :                         *directories != nullptr;
     638             :                         ++directories)
     639             :                     {
     640          52 :                         if(!joined.empty())
     641             :                         {
     642          39 :                             joined += ", ";
     643             :                         }
     644          52 :                         joined += *directories;
     645             :                     }
     646          13 :                     it->string(joined);
     647          13 :                 }
     648             :                 else
     649             :                 {
     650          13 :                     it->string(*f_options_environment.f_configuration_directories);
     651             :                 }
     652             :             }
     653          38 :             break;
     654             : 
     655          56 :         case 'e':
     656          56 :             if(f_options_environment.f_environment_variable_name != nullptr
     657          44 :             && *f_options_environment.f_environment_variable_name != '\0')
     658             :             {
     659          32 :                 if(it->has_flags(usage_flag_traits::FORMAT_FLAG_EXTENDED))
     660             :                 {
     661          32 :                     std::string var(f_options_environment.f_environment_variable_name);
     662          16 :                     char const * env(getenv(f_options_environment.f_environment_variable_name));
     663          16 :                     if(env != nullptr)
     664             :                     {
     665           8 :                         var += '=';
     666           8 :                         var += env;
     667             :                     }
     668             :                     else
     669             :                     {
     670           8 :                         var += " (not set)";
     671             :                     }
     672          16 :                     it->string(var);
     673          16 :                 }
     674             :                 else
     675             :                 {
     676          16 :                     it->string(f_options_environment.f_environment_variable_name);
     677             :                 }
     678             :             }
     679          56 :             break;
     680             : 
     681          13 :         case 'E':
     682          13 :             if(f_options_environment.f_environment_variable_intro != nullptr)
     683             :             {
     684          10 :                 it->string(f_options_environment.f_environment_variable_intro);
     685             :             }
     686          13 :             break;
     687             : 
     688          38 :         case 'f':
     689          38 :             if(f_options_environment.f_configuration_files != nullptr
     690          32 :             && *f_options_environment.f_configuration_files != nullptr)
     691             :             {
     692          26 :                 if(it->has_flags(usage_flag_traits::FORMAT_FLAG_EXTENDED))
     693             :                 {
     694          13 :                     std::string joined;
     695          65 :                     for(char const * const * filenames(f_options_environment.f_configuration_files);
     696          65 :                         *filenames != nullptr;
     697             :                         ++filenames)
     698             :                     {
     699          52 :                         if(!joined.empty())
     700             :                         {
     701          39 :                             joined += ", ";
     702             :                         }
     703          52 :                         joined += *filenames;
     704             :                     }
     705          13 :                     it->string(joined);
     706          13 :                 }
     707             :                 else
     708             :                 {
     709          13 :                     it->string(*f_options_environment.f_configuration_files);
     710             :                 }
     711             :             }
     712          38 :             break;
     713             : 
     714          41 :         case 'g':
     715             :             {
     716          41 :                 string_list_t const list(get_configuration_filenames(!it->has_flags(usage_flag_traits::FORMAT_FLAG_EXTENDED), false));
     717          41 :                 it->string(snapdev::join_strings(list, ", "));
     718          41 :             }
     719             :             break;
     720             : 
     721          19 :         case 'i':
     722             :             // in the advgetopt_options.cpp, we clearly add a final "/"
     723             :             // so we want to add it here too, to be consistent
     724          19 :             it->string(get_options_filename());
     725          19 :             break;
     726             : 
     727          19 :         case 'l':
     728          19 :             if(f_options_environment.f_license != nullptr)
     729             :             {
     730          16 :                 it->string(f_options_environment.f_license);
     731             :             }
     732          19 :             break;
     733             : 
     734          10 :         case 'm':
     735          10 :             if(f_options_environment.f_section_variables_name != nullptr)
     736             :             {
     737           5 :                 it->string(f_options_environment.f_section_variables_name);
     738             :             }
     739          10 :             break;
     740             : 
     741          19 :         case 'o':
     742          19 :             it->string(get_output_filename());
     743          19 :             break;
     744             : 
     745          41 :         case 'p':
     746          41 :             if(it->has_flags(usage_flag_traits::FORMAT_FLAG_EXTENDED))
     747             :             {
     748          13 :                 it->string(f_program_fullname);
     749             :             }
     750             :             else
     751             :             {
     752          28 :                 it->string(f_program_name);
     753             :             }
     754          41 :             break;
     755             : 
     756           5 :         case 's':
     757           5 :             if(f_options_environment.f_group_name != nullptr)
     758             :             {
     759           5 :                 it->string(f_options_environment.f_group_name);
     760             :             }
     761           5 :             break;
     762             : 
     763          19 :         case 't':
     764          19 :             if(f_options_environment.f_build_time != nullptr)
     765             :             {
     766          16 :                 it->string(f_options_environment.f_build_time);
     767             :             }
     768          19 :             break;
     769             : 
     770          19 :         case 'v':
     771          19 :             if(f_options_environment.f_version != nullptr)
     772             :             {
     773          16 :                 it->string(f_options_environment.f_version);
     774             :             }
     775          19 :             break;
     776             : 
     777          22 :         case 'w':
     778             :             {
     779          22 :                 string_list_t const list(get_configuration_filenames(true, true));
     780          22 :                 it->string(snapdev::join_strings(list, ", "));
     781          22 :             }
     782             :             break;
     783             : 
     784             :         }
     785             :     }
     786             : 
     787         674 :     snapdev::format_item<char> empty_item;
     788         674 :     return snapdev::join_strings(items, empty_item);
     789         337 : }
     790             : 
     791             : 
     792             : 
     793             : 
     794             : } // namespace advgetopt
     795             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions