61                                                                                                                {
   62        std::stringstream out;
   63        std::string commentLead;
   64        commentLead.push_back(commentChar);
   65        commentLead.push_back(' ');
   66 
   67        std::vector<std::string> groups = app->get_groups();
   68        bool defaultUsed = false;
   69        groups.insert(groups.begin(), std::string("Options"));
   70        for (const auto& group : groups) {
   71            if (group == "Options" || group.empty()) {
   72                if (defaultUsed) {
   73                    continue;
   74                }
   75                defaultUsed = true;
   76            }
   77            if (write_description && group != "Options" && !group.empty() &&
   78                !app->get_options([group](const Option* opt) -> bool {
   79                        return opt->get_group() == group && opt->get_configurable();
   80                    })
   81                     .empty()) {
   82                out << '\n' << commentChar << commentLead << group << "\n";
   83            }
   84            for (const Option* opt : app->get_options({})) {
   85                
   86                if (opt->get_configurable()) {
   87                    if (opt->get_group() != group) {
   88                        if (!(group == "Options" && opt->get_group().empty())) {
   89                            continue;
   90                        }
   91                    }
   92                    const std::string name = prefix + opt->get_single_name();
   93                    std::string value =
   94                        detail::ini_join(opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, literalQuote);
   95 
   96                    std::string defaultValue{};
   97                    if (default_also) {
   98                        static_assert(std::string::npos + static_cast<std::string::size_type>(1) == 0,
   99                                      "std::string::npos + static_cast<std::string::size_type>(1) != 0");
  100                        if (!value.empty() && detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, literalQuote) == value) {
  101                            value.clear();
  102                        }
  103                        if (!opt->get_default_str().empty()) {
  104                            defaultValue = detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, literalQuote);
  105                            if (defaultValue == "'\"\"'") {
  106                                defaultValue = "";
  107                            }
  108                        } else if (opt->get_run_callback_for_default()) {
  109                            defaultValue = "\"\""; 
  110                        } else if (opt->get_required()) {
  111                            defaultValue = "\"<REQUIRED>\"";
  112                        } else if (opt->get_expected_min() == 0) {
  113                            defaultValue = "false";
  114                        } else {
  115                            defaultValue = "\"\"";
  116                        }
  117                    }
  118                    if (write_description && opt->has_description() && (default_also || !value.empty())) {
  119                        out << commentLead << detail::fix_newlines(commentLead, opt->get_description()) << '\n';
  120                    }
  121                    if (default_also && !defaultValue.empty()) {
  122                        out << commentChar << name << valueDelimiter << defaultValue << "\n";
  123                    }
  124                    if (!value.empty()) {
  125                        if (!opt->get_fnames().empty()) {
  126                            value = opt->get_flag_value(name, value);
  127                        }
  128                        if (value == "\"default\"") {
  129                            value = "default";
  130                        }
  131                        out << name << valueDelimiter << value << "\n\n";
  132                    } else {
  133                        out << '\n';
  134                    }
  135                }
  136            }
  137        }
  138        auto subcommands = app->get_subcommands({});
  139        for (const App* subcom : subcommands) {
  140            if (subcom->get_name().empty()) {
  141                if (write_description && !subcom->get_group().empty()) {
  142                    out << '\n' << commentLead << subcom->get_group() << " Options\n";
  143                }
  144                out << 
to_config(subcom, default_also, write_description, prefix);
 
  145            }
  146        }
  147 
  148        for (const App* subcom : subcommands) {
  149            if (!subcom->get_name().empty()) {
  150                if (subcom->get_configurable() && app->got_subcommand(subcom)) {
  151                    if (!prefix.empty() || app->get_parent() == nullptr) {
  152                        out << '[' << prefix << subcom->get_name() << "]\n";
  153                    } else {
  154                        std::string subname = app->get_name() + parentSeparatorChar + subcom->get_name();
  155                        const auto* p = app->get_parent();
  156                        while (p->get_parent() != nullptr) {
  157                            subname = p->get_name() + parentSeparatorChar + subname;
  158                            p = p->get_parent();
  159                        }
  160                        out << '[' << subname << "]\n";
  161                    }
  162                    out << 
to_config(subcom, default_also, write_description, 
"");
 
  163                } else {
  164                    out << 
to_config(subcom, default_also, write_description, prefix + subcom->get_name() + parentSeparatorChar);
 
  165                }
  166            }
  167        }
  168 
  169        std::string outString;
  170        if (write_description && !out.str().empty()) {
  171            outString =
  172                commentChar + std::string("#") + commentLead + detail::fix_newlines(commentChar + commentLead, app->get_description());
  173        }
  174 
  175        return outString + out.str();
  176    }