#pragma once // Distributed under the 3-Clause BSD License. See accompanying // file LICENSE or https://github.com/CLIUtils/CLI11 for details. #include #include #include #include #include #include "CLI/Error.hpp" #include "CLI/StringTools.hpp" namespace CLI { class App; /// Holds values to load into Options struct ConfigItem { /// This is the list of parents std::vector parents{}; /// This is the name std::string name{}; /// Listing of inputs std::vector inputs{}; /// The list of parents and name joined by "." std::string fullname() const { std::vector tmp = parents; tmp.emplace_back(name); return detail::join(tmp, "."); } }; /// This class provides a converter for configuration files. class Config { protected: std::vector items{}; public: /// Convert an app into a configuration virtual std::string to_config(const App *, bool, bool, std::string) const = 0; /// Convert a configuration into an app virtual std::vector from_config(std::istream &) const = 0; /// Get a flag value virtual std::string to_flag(const ConfigItem &item) const { if(item.inputs.size() == 1) { return item.inputs.at(0); } throw ConversionError::TooManyInputsFlag(item.fullname()); } /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure std::vector from_file(const std::string &name) { std::ifstream input{name}; if(!input.good()) throw FileError::Missing(name); return from_config(input); } /// Virtual destructor virtual ~Config() = default; }; /// This converter works with INI/TOML files; to write proper TOML files use ConfigTOML class ConfigBase : public Config { protected: /// the character used for comments char commentChar = ';'; /// the character used to start an array '\0' is a default to not use char arrayStart = '\0'; /// the character used to end an array '\0' is a default to not use char arrayEnd = '\0'; /// the character used to separate elements in an array char arraySeparator = ' '; /// the character used separate the name from the value char valueDelimiter = '='; public: std::string to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override; std::vector from_config(std::istream &input) const override; /// Specify the configuration for comment characters ConfigBase *comment(char cchar) { commentChar = cchar; return this; } /// Specify the start and end characters for an array ConfigBase *arrayBounds(char aStart, char aEnd) { arrayStart = aStart; arrayEnd = aEnd; return this; } /// Specify the delimiter character for an array ConfigBase *arrayDelimiter(char aSep) { arraySeparator = aSep; return this; } /// Specify the delimiter between a name and value ConfigBase *valueSeparator(char vSep) { valueDelimiter = vSep; return this; } }; /// the default Config is the INI file format using ConfigINI = ConfigBase; /// ConfigTOML generates a TOML compliant output class ConfigTOML : public ConfigINI { public: ConfigTOML() { commentChar = '#'; arrayStart = '['; arrayEnd = ']'; arraySeparator = ','; valueDelimiter = '='; } }; } // namespace CLI