Commit 967bfe0e0228afa8f49c2c08603c2b6ecc02babf
Committed by
GitHub
1 parent
d8a5bdc2
Set the default configuration file output as TOML (#435)
* Set the default configuration file output as TOML * update formatting
Showing
6 changed files
with
415 additions
and
102 deletions
README.md
| @@ -679,39 +679,39 @@ app.set_config(option_name="", | @@ -679,39 +679,39 @@ app.set_config(option_name="", | ||
| 679 | required=false) | 679 | required=false) |
| 680 | ``` | 680 | ``` |
| 681 | 681 | ||
| 682 | -If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in `ini` format by default, The reader can also accept many files in [TOML] format ๐. (other formats can be added by an adept user, some variations are available through customization points in the default formatter). An example of a file: | 682 | +If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in [TOML] format by default ๐ง, though the default reader can also accept files in INI format as well ๐. It should be noted that CLI11 does not contain a full TOML parser but can read strings from most TOML file and run them through the CLI11 parser. Other formats can be added by an adept user, some variations are available through customization points in the default formatter. An example of a TOML file ๐: |
| 683 | 683 | ||
| 684 | ```ini | 684 | ```ini |
| 685 | -; Comments are supported, using a ; | ||
| 686 | -; The default section is [default], case insensitive | 685 | +# Comments are supported, using a # |
| 686 | +# The default section is [default], case insensitive | ||
| 687 | 687 | ||
| 688 | value = 1 | 688 | value = 1 |
| 689 | str = "A string" | 689 | str = "A string" |
| 690 | -vector = 1 2 3 | ||
| 691 | -str_vector = "one" "two" "and three" | 690 | +vector = [1,2,3] |
| 691 | +str_vector = ["one","two","and three"] | ||
| 692 | 692 | ||
| 693 | -; Sections map to subcommands | 693 | +# Sections map to subcommands |
| 694 | [subcommand] | 694 | [subcommand] |
| 695 | in_subcommand = Wow | 695 | in_subcommand = Wow |
| 696 | sub.subcommand = true | 696 | sub.subcommand = true |
| 697 | ``` | 697 | ``` |
| 698 | - or equivalently in TOML ๐ | ||
| 699 | -```toml | ||
| 700 | -# Comments are supported, using a # | ||
| 701 | -# The default section is [default], case insensitive | 698 | +or equivalently in INI format |
| 699 | +```ini | ||
| 700 | +; Comments are supported, using a ; | ||
| 701 | +; The default section is [default], case insensitive | ||
| 702 | 702 | ||
| 703 | value = 1 | 703 | value = 1 |
| 704 | str = "A string" | 704 | str = "A string" |
| 705 | -vector = [1,2,3] | ||
| 706 | -str_vector = ["one","two","and three"] | 705 | +vector = 1 2 3 |
| 706 | +str_vector = "one" "two" "and three" | ||
| 707 | 707 | ||
| 708 | -# Sections map to subcommands | 708 | +; Sections map to subcommands |
| 709 | [subcommand] | 709 | [subcommand] |
| 710 | in_subcommand = Wow | 710 | in_subcommand = Wow |
| 711 | sub.subcommand = true | 711 | sub.subcommand = true |
| 712 | ``` | 712 | ``` |
| 713 | 713 | ||
| 714 | -Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments. ๐ Subcommands can be triggered from config files if the `configurable` flag was set on the subcommand. Then use `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line. | 714 | +Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments. ๐ Subcommands can be triggered from configuration files if the `configurable` flag was set on the subcommand. Then the use of `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line. |
| 715 | 715 | ||
| 716 | To print a configuration file from the passed | 716 | To print a configuration file from the passed |
| 717 | arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions. See [Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for some additional details. | 717 | arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions. See [Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for some additional details. |
| @@ -744,7 +744,7 @@ The App class was designed allow toolkits to subclass it, to provide preset defa | @@ -744,7 +744,7 @@ The App class was designed allow toolkits to subclass it, to provide preset defa | ||
| 744 | but before run behavior, while | 744 | but before run behavior, while |
| 745 | still giving the user freedom to `callback` on the main app. | 745 | still giving the user freedom to `callback` on the main app. |
| 746 | 746 | ||
| 747 | -The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional bool should be set to true if you are | 747 | +The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional boolean should be set to true if you are |
| 748 | including the program name in the string, and false otherwise. | 748 | including the program name in the string, and false otherwise. |
| 749 | 749 | ||
| 750 | Also, in a related note, the `App` you get a pointer to is stored in the parent `App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main `App` goes out of scope unless the object has another owner. | 750 | Also, in a related note, the `App` you get a pointer to is stored in the parent `App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main `App` goes out of scope unless the object has another owner. |
book/chapters/config.md
| @@ -41,39 +41,39 @@ If it is needed to get the configuration file name used this can be obtained via | @@ -41,39 +41,39 @@ If it is needed to get the configuration file name used this can be obtained via | ||
| 41 | 41 | ||
| 42 | ## Configure file format | 42 | ## Configure file format |
| 43 | 43 | ||
| 44 | -Here is an example configuration file, in INI format: | 44 | +Here is an example configuration file, in [TOML](https://github.com/toml-lang/toml) format: |
| 45 | 45 | ||
| 46 | ```ini | 46 | ```ini |
| 47 | -; Comments are supported, using a ; | ||
| 48 | -; The default section is [default], case insensitive | 47 | +# Comments are supported, using a # |
| 48 | +# The default section is [default], case insensitive | ||
| 49 | 49 | ||
| 50 | value = 1 | 50 | value = 1 |
| 51 | str = "A string" | 51 | str = "A string" |
| 52 | -vector = 1 2 3 | 52 | +vector = [1,2,3] |
| 53 | 53 | ||
| 54 | -; Section map to subcommands | 54 | +# Section map to subcommands |
| 55 | [subcommand] | 55 | [subcommand] |
| 56 | in_subcommand = Wow | 56 | in_subcommand = Wow |
| 57 | -sub.subcommand = true | 57 | +[subcommand.sub] |
| 58 | +subcommand = true # could also be give as sub.subcommand=true | ||
| 58 | ``` | 59 | ``` |
| 59 | 60 | ||
| 60 | Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`, `disable`, (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults". If a subcommand is set to `configurable` then passing the subcommand using `[sub]` in a configuration file will trigger the subcommand.) | 61 | Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`, `disable`, (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults". If a subcommand is set to `configurable` then passing the subcommand using `[sub]` in a configuration file will trigger the subcommand.) |
| 61 | 62 | ||
| 62 | -CLI11 also supports configuration file in [TOML](https://github.com/toml-lang/toml) format. | 63 | +CLI11 also supports configuration file in INI format. |
| 63 | 64 | ||
| 64 | -```toml | ||
| 65 | -# Comments are supported, using a # | ||
| 66 | -# The default section is [default], case insensitive | 65 | +```ini |
| 66 | +; Comments are supported, using a ; | ||
| 67 | +; The default section is [default], case insensitive | ||
| 67 | 68 | ||
| 68 | value = 1 | 69 | value = 1 |
| 69 | str = "A string" | 70 | str = "A string" |
| 70 | -vector = [1,2,3] | 71 | +vector = 1 2 3 |
| 71 | 72 | ||
| 72 | -# Section map to subcommands | 73 | +; Section map to subcommands |
| 73 | [subcommand] | 74 | [subcommand] |
| 74 | in_subcommand = Wow | 75 | in_subcommand = Wow |
| 75 | -[subcommand.sub] | ||
| 76 | -subcommand = true # could also be give as sub.subcommand=true | 76 | +sub.subcommand = true |
| 77 | ``` | 77 | ``` |
| 78 | 78 | ||
| 79 | The main differences are in vector notation and comment character. Note: CLI11 is not a full TOML parser as it just reads values as strings. It is possible (but not recommended) to mix notation. | 79 | The main differences are in vector notation and comment character. Note: CLI11 is not a full TOML parser as it just reads values as strings. It is possible (but not recommended) to mix notation. |
| @@ -83,16 +83,16 @@ The main differences are in vector notation and comment character. Note: CLI11 | @@ -83,16 +83,16 @@ The main differences are in vector notation and comment character. Note: CLI11 | ||
| 83 | To print a configuration file from the passed arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions. | 83 | To print a configuration file from the passed arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions. |
| 84 | 84 | ||
| 85 | ### Customization of configure file output | 85 | ### Customization of configure file output |
| 86 | -The default config parser/generator has some customization points that allow variations on the INI format. The default formatter has a base configuration that matches the INI format. It defines 5 characters that define how different aspects of the configuration are handled | 86 | +The default config parser/generator has some customization points that allow variations on the TOML format. The default formatter has a base configuration that matches the TOML format. It defines 5 characters that define how different aspects of the configuration are handled |
| 87 | ```cpp | 87 | ```cpp |
| 88 | /// the character used for comments | 88 | /// the character used for comments |
| 89 | -char commentChar = ';'; | 89 | +char commentChar = '#'; |
| 90 | /// the character used to start an array '\0' is a default to not use | 90 | /// the character used to start an array '\0' is a default to not use |
| 91 | -char arrayStart = '\0'; | 91 | +char arrayStart = '['; |
| 92 | /// the character used to end an array '\0' is a default to not use | 92 | /// the character used to end an array '\0' is a default to not use |
| 93 | -char arrayEnd = '\0'; | 93 | +char arrayEnd = ']'; |
| 94 | /// the character used to separate elements in an array | 94 | /// the character used to separate elements in an array |
| 95 | -char arraySeparator = ' '; | 95 | +char arraySeparator = ','; |
| 96 | /// the character used separate the name from the value | 96 | /// the character used separate the name from the value |
| 97 | char valueDelimiter = '='; | 97 | char valueDelimiter = '='; |
| 98 | ``` | 98 | ``` |
| @@ -111,11 +111,11 @@ auto config_base=app.get_config_formatter_base(); | @@ -111,11 +111,11 @@ auto config_base=app.get_config_formatter_base(); | ||
| 111 | config_base->valueSeparator(':'); | 111 | config_base->valueSeparator(':'); |
| 112 | ``` | 112 | ``` |
| 113 | 113 | ||
| 114 | -The default configuration file will read TOML files, but will write out files in the INI format. To specify outputting TOML formatted files use | 114 | +The default configuration file will read INI files, but will write out files in the TOML format. To specify outputting INI formatted files use |
| 115 | ```cpp | 115 | ```cpp |
| 116 | -app.config_formatter(std::make_shared<CLI::ConfigTOML>()); | 116 | +app.config_formatter(std::make_shared<CLI::ConfigINI>()); |
| 117 | ``` | 117 | ``` |
| 118 | -which makes use of a predefined modification of the ConfigBase class which INI also uses. | 118 | +which makes use of a predefined modification of the ConfigBase class which TOML also uses. |
| 119 | 119 | ||
| 120 | ## Custom formats | 120 | ## Custom formats |
| 121 | 121 |
include/CLI/App.hpp
| @@ -247,7 +247,7 @@ class App { | @@ -247,7 +247,7 @@ class App { | ||
| 247 | Option *config_ptr_{nullptr}; | 247 | Option *config_ptr_{nullptr}; |
| 248 | 248 | ||
| 249 | /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer) | 249 | /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer) |
| 250 | - std::shared_ptr<Config> config_formatter_{new ConfigINI()}; | 250 | + std::shared_ptr<Config> config_formatter_{new ConfigTOML()}; |
| 251 | 251 | ||
| 252 | ///@} | 252 | ///@} |
| 253 | 253 |
include/CLI/Config.hpp
| @@ -167,10 +167,11 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons | @@ -167,10 +167,11 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons | ||
| 167 | std::string section = "default"; | 167 | std::string section = "default"; |
| 168 | 168 | ||
| 169 | std::vector<ConfigItem> output; | 169 | std::vector<ConfigItem> output; |
| 170 | - bool defaultArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd; | ||
| 171 | - char aStart = (defaultArray) ? '[' : arrayStart; | ||
| 172 | - char aEnd = (defaultArray) ? ']' : arrayEnd; | ||
| 173 | - char aSep = (defaultArray && arraySeparator == ' ') ? ',' : arraySeparator; | 170 | + bool isDefaultArray = (arrayStart == '[' && arrayEnd == ']' && arraySeparator == ','); |
| 171 | + bool isINIArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd; | ||
| 172 | + char aStart = (isINIArray) ? '[' : arrayStart; | ||
| 173 | + char aEnd = (isINIArray) ? ']' : arrayEnd; | ||
| 174 | + char aSep = (isINIArray && arraySeparator == ' ') ? ',' : arraySeparator; | ||
| 174 | 175 | ||
| 175 | while(getline(input, line)) { | 176 | while(getline(input, line)) { |
| 176 | std::vector<std::string> items_buffer; | 177 | std::vector<std::string> items_buffer; |
| @@ -212,9 +213,9 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons | @@ -212,9 +213,9 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons | ||
| 212 | std::string item = detail::trim_copy(line.substr(pos + 1)); | 213 | std::string item = detail::trim_copy(line.substr(pos + 1)); |
| 213 | if(item.size() > 1 && item.front() == aStart && item.back() == aEnd) { | 214 | if(item.size() > 1 && item.front() == aStart && item.back() == aEnd) { |
| 214 | items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep); | 215 | items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep); |
| 215 | - } else if(defaultArray && item.find_first_of(aSep) != std::string::npos) { | 216 | + } else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) { |
| 216 | items_buffer = detail::split_up(item, aSep); | 217 | items_buffer = detail::split_up(item, aSep); |
| 217 | - } else if(defaultArray && item.find_first_of(' ') != std::string::npos) { | 218 | + } else if((isDefaultArray || isINIArray) && item.find_first_of(' ') != std::string::npos) { |
| 218 | items_buffer = detail::split_up(item); | 219 | items_buffer = detail::split_up(item); |
| 219 | } else { | 220 | } else { |
| 220 | items_buffer = {item}; | 221 | items_buffer = {item}; |
include/CLI/ConfigFwd.hpp
| @@ -71,17 +71,17 @@ class Config { | @@ -71,17 +71,17 @@ class Config { | ||
| 71 | virtual ~Config() = default; | 71 | virtual ~Config() = default; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | -/// This converter works with INI/TOML files; to write proper TOML files use ConfigTOML | 74 | +/// This converter works with INI/TOML files; to write INI files use ConfigINI |
| 75 | class ConfigBase : public Config { | 75 | class ConfigBase : public Config { |
| 76 | protected: | 76 | protected: |
| 77 | /// the character used for comments | 77 | /// the character used for comments |
| 78 | - char commentChar = ';'; | 78 | + char commentChar = '#'; |
| 79 | /// the character used to start an array '\0' is a default to not use | 79 | /// the character used to start an array '\0' is a default to not use |
| 80 | - char arrayStart = '\0'; | 80 | + char arrayStart = '['; |
| 81 | /// the character used to end an array '\0' is a default to not use | 81 | /// the character used to end an array '\0' is a default to not use |
| 82 | - char arrayEnd = '\0'; | 82 | + char arrayEnd = ']'; |
| 83 | /// the character used to separate elements in an array | 83 | /// the character used to separate elements in an array |
| 84 | - char arraySeparator = ' '; | 84 | + char arraySeparator = ','; |
| 85 | /// the character used separate the name from the value | 85 | /// the character used separate the name from the value |
| 86 | char valueDelimiter = '='; | 86 | char valueDelimiter = '='; |
| 87 | 87 | ||
| @@ -113,18 +113,18 @@ class ConfigBase : public Config { | @@ -113,18 +113,18 @@ class ConfigBase : public Config { | ||
| 113 | } | 113 | } |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
| 116 | -/// the default Config is the INI file format | ||
| 117 | -using ConfigINI = ConfigBase; | 116 | +/// the default Config is the TOML file format |
| 117 | +using ConfigTOML = ConfigBase; | ||
| 118 | 118 | ||
| 119 | -/// ConfigTOML generates a TOML compliant output | ||
| 120 | -class ConfigTOML : public ConfigINI { | 119 | +/// ConfigINI generates a "standard" INI compliant output |
| 120 | +class ConfigINI : public ConfigTOML { | ||
| 121 | 121 | ||
| 122 | public: | 122 | public: |
| 123 | - ConfigTOML() { | ||
| 124 | - commentChar = '#'; | ||
| 125 | - arrayStart = '['; | ||
| 126 | - arrayEnd = ']'; | ||
| 127 | - arraySeparator = ','; | 123 | + ConfigINI() { |
| 124 | + commentChar = ';'; | ||
| 125 | + arrayStart = '\0'; | ||
| 126 | + arrayEnd = '\0'; | ||
| 127 | + arraySeparator = ' '; | ||
| 128 | valueDelimiter = '='; | 128 | valueDelimiter = '='; |
| 129 | } | 129 | } |
| 130 | }; | 130 | }; |
tests/ConfigFileTest.cpp
| @@ -690,12 +690,12 @@ TEST_F(TApp, IniVector) { | @@ -690,12 +690,12 @@ TEST_F(TApp, IniVector) { | ||
| 690 | } | 690 | } |
| 691 | TEST_F(TApp, TOMLVector) { | 691 | TEST_F(TApp, TOMLVector) { |
| 692 | 692 | ||
| 693 | - TempFile tmpini{"TestIniTmp.ini"}; | 693 | + TempFile tmptoml{"TestTomlTmp.toml"}; |
| 694 | 694 | ||
| 695 | - app.set_config("--config", tmpini); | 695 | + app.set_config("--config", tmptoml); |
| 696 | 696 | ||
| 697 | { | 697 | { |
| 698 | - std::ofstream out{tmpini}; | 698 | + std::ofstream out{tmptoml}; |
| 699 | out << "#this is a comment line\n"; | 699 | out << "#this is a comment line\n"; |
| 700 | out << "[default]\n"; | 700 | out << "[default]\n"; |
| 701 | out << "two=[2,3]\n"; | 701 | out << "two=[2,3]\n"; |
| @@ -1050,12 +1050,12 @@ TEST_F(TApp, IniSubcommandMultipleSections) { | @@ -1050,12 +1050,12 @@ TEST_F(TApp, IniSubcommandMultipleSections) { | ||
| 1050 | 1050 | ||
| 1051 | TEST_F(TApp, DuplicateSubcommandCallbacks) { | 1051 | TEST_F(TApp, DuplicateSubcommandCallbacks) { |
| 1052 | 1052 | ||
| 1053 | - TempFile tmpini{"TestIniTmp.ini"}; | 1053 | + TempFile tmptoml{"TesttomlTmp.toml"}; |
| 1054 | 1054 | ||
| 1055 | - app.set_config("--config", tmpini); | 1055 | + app.set_config("--config", tmptoml); |
| 1056 | 1056 | ||
| 1057 | { | 1057 | { |
| 1058 | - std::ofstream out{tmpini}; | 1058 | + std::ofstream out{tmptoml}; |
| 1059 | out << "[[foo]]" << std::endl; | 1059 | out << "[[foo]]" << std::endl; |
| 1060 | out << "[[foo]]" << std::endl; | 1060 | out << "[[foo]]" << std::endl; |
| 1061 | out << "[[foo]]" << std::endl; | 1061 | out << "[[foo]]" << std::endl; |
| @@ -1195,6 +1195,7 @@ TEST_F(TApp, IniFlagDual) { | @@ -1195,6 +1195,7 @@ TEST_F(TApp, IniFlagDual) { | ||
| 1195 | TempFile tmpini{"TestIniTmp.ini"}; | 1195 | TempFile tmpini{"TestIniTmp.ini"}; |
| 1196 | 1196 | ||
| 1197 | bool boo{false}; | 1197 | bool boo{false}; |
| 1198 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1198 | app.add_flag("--flag", boo); | 1199 | app.add_flag("--flag", boo); |
| 1199 | app.set_config("--config", tmpini); | 1200 | app.set_config("--config", tmpini); |
| 1200 | 1201 | ||
| @@ -1362,7 +1363,7 @@ TEST_F(TApp, IniFalseFlagsDefDisableOverrideSuccess) { | @@ -1362,7 +1363,7 @@ TEST_F(TApp, IniFalseFlagsDefDisableOverrideSuccess) { | ||
| 1362 | EXPECT_EQ(15, val); | 1363 | EXPECT_EQ(15, val); |
| 1363 | } | 1364 | } |
| 1364 | 1365 | ||
| 1365 | -TEST_F(TApp, IniOutputSimple) { | 1366 | +TEST_F(TApp, TomlOutputSimple) { |
| 1366 | 1367 | ||
| 1367 | int v{0}; | 1368 | int v{0}; |
| 1368 | app.add_option("--simple", v); | 1369 | app.add_option("--simple", v); |
| @@ -1375,7 +1376,7 @@ TEST_F(TApp, IniOutputSimple) { | @@ -1375,7 +1376,7 @@ TEST_F(TApp, IniOutputSimple) { | ||
| 1375 | EXPECT_EQ("simple=3\n", str); | 1376 | EXPECT_EQ("simple=3\n", str); |
| 1376 | } | 1377 | } |
| 1377 | 1378 | ||
| 1378 | -TEST_F(TApp, IniOutputNoConfigurable) { | 1379 | +TEST_F(TApp, TomlOutputNoConfigurable) { |
| 1379 | 1380 | ||
| 1380 | int v1{0}, v2{0}; | 1381 | int v1{0}, v2{0}; |
| 1381 | app.add_option("--simple", v1); | 1382 | app.add_option("--simple", v1); |
| @@ -1389,7 +1390,7 @@ TEST_F(TApp, IniOutputNoConfigurable) { | @@ -1389,7 +1390,7 @@ TEST_F(TApp, IniOutputNoConfigurable) { | ||
| 1389 | EXPECT_EQ("simple=3\n", str); | 1390 | EXPECT_EQ("simple=3\n", str); |
| 1390 | } | 1391 | } |
| 1391 | 1392 | ||
| 1392 | -TEST_F(TApp, IniOutputShortSingleDescription) { | 1393 | +TEST_F(TApp, TomlOutputShortSingleDescription) { |
| 1393 | std::string flag = "some_flag"; | 1394 | std::string flag = "some_flag"; |
| 1394 | const std::string description = "Some short description."; | 1395 | const std::string description = "Some short description."; |
| 1395 | app.add_flag("--" + flag, description); | 1396 | app.add_flag("--" + flag, description); |
| @@ -1397,10 +1398,10 @@ TEST_F(TApp, IniOutputShortSingleDescription) { | @@ -1397,10 +1398,10 @@ TEST_F(TApp, IniOutputShortSingleDescription) { | ||
| 1397 | run(); | 1398 | run(); |
| 1398 | 1399 | ||
| 1399 | std::string str = app.config_to_str(true, true); | 1400 | std::string str = app.config_to_str(true, true); |
| 1400 | - EXPECT_THAT(str, HasSubstr("; " + description + "\n" + flag + "=false\n")); | 1401 | + EXPECT_THAT(str, HasSubstr("# " + description + "\n" + flag + "=false\n")); |
| 1401 | } | 1402 | } |
| 1402 | 1403 | ||
| 1403 | -TEST_F(TApp, IniOutputShortDoubleDescription) { | 1404 | +TEST_F(TApp, TomlOutputShortDoubleDescription) { |
| 1404 | std::string flag1 = "flagnr1"; | 1405 | std::string flag1 = "flagnr1"; |
| 1405 | std::string flag2 = "flagnr2"; | 1406 | std::string flag2 = "flagnr2"; |
| 1406 | const std::string description1 = "First description."; | 1407 | const std::string description1 = "First description."; |
| @@ -1412,10 +1413,10 @@ TEST_F(TApp, IniOutputShortDoubleDescription) { | @@ -1412,10 +1413,10 @@ TEST_F(TApp, IniOutputShortDoubleDescription) { | ||
| 1412 | 1413 | ||
| 1413 | std::string str = app.config_to_str(true, true); | 1414 | std::string str = app.config_to_str(true, true); |
| 1414 | EXPECT_THAT( | 1415 | EXPECT_THAT( |
| 1415 | - str, HasSubstr("; " + description1 + "\n" + flag1 + "=false\n\n; " + description2 + "\n" + flag2 + "=false\n")); | 1416 | + str, HasSubstr("# " + description1 + "\n" + flag1 + "=false\n\n# " + description2 + "\n" + flag2 + "=false\n")); |
| 1416 | } | 1417 | } |
| 1417 | 1418 | ||
| 1418 | -TEST_F(TApp, IniOutputGroups) { | 1419 | +TEST_F(TApp, TomlOutputGroups) { |
| 1419 | std::string flag1 = "flagnr1"; | 1420 | std::string flag1 = "flagnr1"; |
| 1420 | std::string flag2 = "flagnr2"; | 1421 | std::string flag2 = "flagnr2"; |
| 1421 | const std::string description1 = "First description."; | 1422 | const std::string description1 = "First description."; |
| @@ -1430,7 +1431,7 @@ TEST_F(TApp, IniOutputGroups) { | @@ -1430,7 +1431,7 @@ TEST_F(TApp, IniOutputGroups) { | ||
| 1430 | EXPECT_THAT(str, HasSubstr("group2")); | 1431 | EXPECT_THAT(str, HasSubstr("group2")); |
| 1431 | } | 1432 | } |
| 1432 | 1433 | ||
| 1433 | -TEST_F(TApp, IniOutputHiddenOptions) { | 1434 | +TEST_F(TApp, TomlOutputHiddenOptions) { |
| 1434 | std::string flag1 = "flagnr1"; | 1435 | std::string flag1 = "flagnr1"; |
| 1435 | std::string flag2 = "flagnr2"; | 1436 | std::string flag2 = "flagnr2"; |
| 1436 | double val{12.7}; | 1437 | double val{12.7}; |
| @@ -1454,7 +1455,7 @@ TEST_F(TApp, IniOutputHiddenOptions) { | @@ -1454,7 +1455,7 @@ TEST_F(TApp, IniOutputHiddenOptions) { | ||
| 1454 | EXPECT_EQ(loc, std::string::npos); | 1455 | EXPECT_EQ(loc, std::string::npos); |
| 1455 | } | 1456 | } |
| 1456 | 1457 | ||
| 1457 | -TEST_F(TApp, IniOutputMultiLineDescription) { | 1458 | +TEST_F(TApp, TomlOutputMultiLineDescription) { |
| 1458 | std::string flag = "some_flag"; | 1459 | std::string flag = "some_flag"; |
| 1459 | const std::string description = "Some short description.\nThat has lines."; | 1460 | const std::string description = "Some short description.\nThat has lines."; |
| 1460 | app.add_flag("--" + flag, description); | 1461 | app.add_flag("--" + flag, description); |
| @@ -1462,12 +1463,12 @@ TEST_F(TApp, IniOutputMultiLineDescription) { | @@ -1462,12 +1463,12 @@ TEST_F(TApp, IniOutputMultiLineDescription) { | ||
| 1462 | run(); | 1463 | run(); |
| 1463 | 1464 | ||
| 1464 | std::string str = app.config_to_str(true, true); | 1465 | std::string str = app.config_to_str(true, true); |
| 1465 | - EXPECT_THAT(str, HasSubstr("; Some short description.\n")); | ||
| 1466 | - EXPECT_THAT(str, HasSubstr("; That has lines.\n")); | 1466 | + EXPECT_THAT(str, HasSubstr("# Some short description.\n")); |
| 1467 | + EXPECT_THAT(str, HasSubstr("# That has lines.\n")); | ||
| 1467 | EXPECT_THAT(str, HasSubstr(flag + "=false\n")); | 1468 | EXPECT_THAT(str, HasSubstr(flag + "=false\n")); |
| 1468 | } | 1469 | } |
| 1469 | 1470 | ||
| 1470 | -TEST_F(TApp, IniOutputOptionGroup) { | 1471 | +TEST_F(TApp, TomlOutputOptionGroup) { |
| 1471 | std::string flag1 = "flagnr1"; | 1472 | std::string flag1 = "flagnr1"; |
| 1472 | std::string flag2 = "flagnr2"; | 1473 | std::string flag2 = "flagnr2"; |
| 1473 | double val{12.7}; | 1474 | double val{12.7}; |
| @@ -1496,20 +1497,7 @@ TEST_F(TApp, IniOutputOptionGroup) { | @@ -1496,20 +1497,7 @@ TEST_F(TApp, IniOutputOptionGroup) { | ||
| 1496 | EXPECT_GT(locg3, locg1); | 1497 | EXPECT_GT(locg3, locg1); |
| 1497 | } | 1498 | } |
| 1498 | 1499 | ||
| 1499 | -TEST_F(TApp, IniOutputVector) { | ||
| 1500 | - | ||
| 1501 | - std::vector<int> v; | ||
| 1502 | - app.add_option("--vector", v); | ||
| 1503 | - | ||
| 1504 | - args = {"--vector", "1", "2", "3"}; | ||
| 1505 | - | ||
| 1506 | - run(); | ||
| 1507 | - | ||
| 1508 | - std::string str = app.config_to_str(); | ||
| 1509 | - EXPECT_EQ("vector=1 2 3\n", str); | ||
| 1510 | -} | ||
| 1511 | - | ||
| 1512 | -TEST_F(TApp, IniOutputVectorTOML) { | 1500 | +TEST_F(TApp, TomlOutputVector) { |
| 1513 | 1501 | ||
| 1514 | std::vector<int> v; | 1502 | std::vector<int> v; |
| 1515 | app.add_option("--vector", v); | 1503 | app.add_option("--vector", v); |
| @@ -1522,7 +1510,7 @@ TEST_F(TApp, IniOutputVectorTOML) { | @@ -1522,7 +1510,7 @@ TEST_F(TApp, IniOutputVectorTOML) { | ||
| 1522 | EXPECT_EQ("vector=[1, 2, 3]\n", str); | 1510 | EXPECT_EQ("vector=[1, 2, 3]\n", str); |
| 1523 | } | 1511 | } |
| 1524 | 1512 | ||
| 1525 | -TEST_F(TApp, IniOutputVectorCustom) { | 1513 | +TEST_F(TApp, ConfigOutputVectorCustom) { |
| 1526 | 1514 | ||
| 1527 | std::vector<int> v; | 1515 | std::vector<int> v; |
| 1528 | app.add_option("--vector", v); | 1516 | app.add_option("--vector", v); |
| @@ -1537,7 +1525,7 @@ TEST_F(TApp, IniOutputVectorCustom) { | @@ -1537,7 +1525,7 @@ TEST_F(TApp, IniOutputVectorCustom) { | ||
| 1537 | EXPECT_EQ("vector:{1; 2; 3}\n", str); | 1525 | EXPECT_EQ("vector:{1; 2; 3}\n", str); |
| 1538 | } | 1526 | } |
| 1539 | 1527 | ||
| 1540 | -TEST_F(TApp, IniOutputFlag) { | 1528 | +TEST_F(TApp, TomlOutputFlag) { |
| 1541 | 1529 | ||
| 1542 | int v{0}, q{0}; | 1530 | int v{0}, q{0}; |
| 1543 | app.add_option("--simple", v); | 1531 | app.add_option("--simple", v); |
| @@ -1553,13 +1541,13 @@ TEST_F(TApp, IniOutputFlag) { | @@ -1553,13 +1541,13 @@ TEST_F(TApp, IniOutputFlag) { | ||
| 1553 | EXPECT_THAT(str, HasSubstr("simple=3")); | 1541 | EXPECT_THAT(str, HasSubstr("simple=3")); |
| 1554 | EXPECT_THAT(str, Not(HasSubstr("nothing"))); | 1542 | EXPECT_THAT(str, Not(HasSubstr("nothing"))); |
| 1555 | EXPECT_THAT(str, HasSubstr("onething=true")); | 1543 | EXPECT_THAT(str, HasSubstr("onething=true")); |
| 1556 | - EXPECT_THAT(str, HasSubstr("something=true true")); | 1544 | + EXPECT_THAT(str, HasSubstr("something=[true, true]")); |
| 1557 | 1545 | ||
| 1558 | str = app.config_to_str(true); | 1546 | str = app.config_to_str(true); |
| 1559 | EXPECT_THAT(str, HasSubstr("nothing")); | 1547 | EXPECT_THAT(str, HasSubstr("nothing")); |
| 1560 | } | 1548 | } |
| 1561 | 1549 | ||
| 1562 | -TEST_F(TApp, IniOutputSet) { | 1550 | +TEST_F(TApp, TomlOutputSet) { |
| 1563 | 1551 | ||
| 1564 | int v{0}; | 1552 | int v{0}; |
| 1565 | app.add_option("--simple", v)->check(CLI::IsMember({1, 2, 3})); | 1553 | app.add_option("--simple", v)->check(CLI::IsMember({1, 2, 3})); |
| @@ -1572,7 +1560,7 @@ TEST_F(TApp, IniOutputSet) { | @@ -1572,7 +1560,7 @@ TEST_F(TApp, IniOutputSet) { | ||
| 1572 | EXPECT_THAT(str, HasSubstr("simple=2")); | 1560 | EXPECT_THAT(str, HasSubstr("simple=2")); |
| 1573 | } | 1561 | } |
| 1574 | 1562 | ||
| 1575 | -TEST_F(TApp, IniOutputDefault) { | 1563 | +TEST_F(TApp, TomlOutputDefault) { |
| 1576 | 1564 | ||
| 1577 | int v{7}; | 1565 | int v{7}; |
| 1578 | app.add_option("--simple", v, "", true); | 1566 | app.add_option("--simple", v, "", true); |
| @@ -1586,7 +1574,7 @@ TEST_F(TApp, IniOutputDefault) { | @@ -1586,7 +1574,7 @@ TEST_F(TApp, IniOutputDefault) { | ||
| 1586 | EXPECT_THAT(str, HasSubstr("simple=7")); | 1574 | EXPECT_THAT(str, HasSubstr("simple=7")); |
| 1587 | } | 1575 | } |
| 1588 | 1576 | ||
| 1589 | -TEST_F(TApp, IniOutputSubcom) { | 1577 | +TEST_F(TApp, TomlOutputSubcom) { |
| 1590 | 1578 | ||
| 1591 | app.add_flag("--simple"); | 1579 | app.add_flag("--simple"); |
| 1592 | auto subcom = app.add_subcommand("other"); | 1580 | auto subcom = app.add_subcommand("other"); |
| @@ -1600,7 +1588,7 @@ TEST_F(TApp, IniOutputSubcom) { | @@ -1600,7 +1588,7 @@ TEST_F(TApp, IniOutputSubcom) { | ||
| 1600 | EXPECT_THAT(str, HasSubstr("other.newer=true")); | 1588 | EXPECT_THAT(str, HasSubstr("other.newer=true")); |
| 1601 | } | 1589 | } |
| 1602 | 1590 | ||
| 1603 | -TEST_F(TApp, IniOutputSubcomConfigurable) { | 1591 | +TEST_F(TApp, TomlOutputSubcomConfigurable) { |
| 1604 | 1592 | ||
| 1605 | app.add_flag("--simple"); | 1593 | app.add_flag("--simple"); |
| 1606 | auto subcom = app.add_subcommand("other")->configurable(); | 1594 | auto subcom = app.add_subcommand("other")->configurable(); |
| @@ -1616,7 +1604,7 @@ TEST_F(TApp, IniOutputSubcomConfigurable) { | @@ -1616,7 +1604,7 @@ TEST_F(TApp, IniOutputSubcomConfigurable) { | ||
| 1616 | EXPECT_EQ(str.find("other.newer=true"), std::string::npos); | 1604 | EXPECT_EQ(str.find("other.newer=true"), std::string::npos); |
| 1617 | } | 1605 | } |
| 1618 | 1606 | ||
| 1619 | -TEST_F(TApp, IniOutputSubsubcom) { | 1607 | +TEST_F(TApp, TomlOutputSubsubcom) { |
| 1620 | 1608 | ||
| 1621 | app.add_flag("--simple"); | 1609 | app.add_flag("--simple"); |
| 1622 | auto subcom = app.add_subcommand("other"); | 1610 | auto subcom = app.add_subcommand("other"); |
| @@ -1633,7 +1621,7 @@ TEST_F(TApp, IniOutputSubsubcom) { | @@ -1633,7 +1621,7 @@ TEST_F(TApp, IniOutputSubsubcom) { | ||
| 1633 | EXPECT_THAT(str, HasSubstr("other.sub2.newest=true")); | 1621 | EXPECT_THAT(str, HasSubstr("other.sub2.newest=true")); |
| 1634 | } | 1622 | } |
| 1635 | 1623 | ||
| 1636 | -TEST_F(TApp, IniOutputSubsubcomConfigurable) { | 1624 | +TEST_F(TApp, TomlOutputSubsubcomConfigurable) { |
| 1637 | 1625 | ||
| 1638 | app.add_flag("--simple"); | 1626 | app.add_flag("--simple"); |
| 1639 | auto subcom = app.add_subcommand("other")->configurable(); | 1627 | auto subcom = app.add_subcommand("other")->configurable(); |
| @@ -1654,7 +1642,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurable) { | @@ -1654,7 +1642,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurable) { | ||
| 1654 | EXPECT_EQ(str.find("sub2.newest=true"), std::string::npos); | 1642 | EXPECT_EQ(str.find("sub2.newest=true"), std::string::npos); |
| 1655 | } | 1643 | } |
| 1656 | 1644 | ||
| 1657 | -TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) { | 1645 | +TEST_F(TApp, TomlOutputSubsubcomConfigurableDeep) { |
| 1658 | 1646 | ||
| 1659 | app.add_flag("--simple"); | 1647 | app.add_flag("--simple"); |
| 1660 | auto subcom = app.add_subcommand("other")->configurable(); | 1648 | auto subcom = app.add_subcommand("other")->configurable(); |
| @@ -1677,7 +1665,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) { | @@ -1677,7 +1665,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) { | ||
| 1677 | EXPECT_EQ(str.find(".absolute_newest=true"), std::string::npos); | 1665 | EXPECT_EQ(str.find(".absolute_newest=true"), std::string::npos); |
| 1678 | } | 1666 | } |
| 1679 | 1667 | ||
| 1680 | -TEST_F(TApp, IniQuotedOutput) { | 1668 | +TEST_F(TApp, TomlOutputQuoted) { |
| 1681 | 1669 | ||
| 1682 | std::string val1; | 1670 | std::string val1; |
| 1683 | app.add_option("--val1", val1); | 1671 | app.add_option("--val1", val1); |
| @@ -1697,7 +1685,7 @@ TEST_F(TApp, IniQuotedOutput) { | @@ -1697,7 +1685,7 @@ TEST_F(TApp, IniQuotedOutput) { | ||
| 1697 | EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'")); | 1685 | EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'")); |
| 1698 | } | 1686 | } |
| 1699 | 1687 | ||
| 1700 | -TEST_F(TApp, DefaultsIniQuotedOutput) { | 1688 | +TEST_F(TApp, DefaultsTomlOutputQuoted) { |
| 1701 | 1689 | ||
| 1702 | std::string val1{"I am a string"}; | 1690 | std::string val1{"I am a string"}; |
| 1703 | app.add_option("--val1", val1, "", true); | 1691 | app.add_option("--val1", val1, "", true); |
| @@ -1755,3 +1743,327 @@ TEST_F(TApp, ConfigWriteReadWrite) { | @@ -1755,3 +1743,327 @@ TEST_F(TApp, ConfigWriteReadWrite) { | ||
| 1755 | 1743 | ||
| 1756 | EXPECT_EQ(config1, config2); | 1744 | EXPECT_EQ(config1, config2); |
| 1757 | } | 1745 | } |
| 1746 | + | ||
| 1747 | +///////INI output tests | ||
| 1748 | + | ||
| 1749 | +TEST_F(TApp, IniOutputSimple) { | ||
| 1750 | + | ||
| 1751 | + int v{0}; | ||
| 1752 | + app.add_option("--simple", v); | ||
| 1753 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1754 | + args = {"--simple=3"}; | ||
| 1755 | + | ||
| 1756 | + run(); | ||
| 1757 | + | ||
| 1758 | + std::string str = app.config_to_str(); | ||
| 1759 | + EXPECT_EQ("simple=3\n", str); | ||
| 1760 | +} | ||
| 1761 | + | ||
| 1762 | +TEST_F(TApp, IniOutputNoConfigurable) { | ||
| 1763 | + | ||
| 1764 | + int v1{0}, v2{0}; | ||
| 1765 | + app.add_option("--simple", v1); | ||
| 1766 | + app.add_option("--noconf", v2)->configurable(false); | ||
| 1767 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1768 | + args = {"--simple=3", "--noconf=2"}; | ||
| 1769 | + | ||
| 1770 | + run(); | ||
| 1771 | + | ||
| 1772 | + std::string str = app.config_to_str(); | ||
| 1773 | + EXPECT_EQ("simple=3\n", str); | ||
| 1774 | +} | ||
| 1775 | + | ||
| 1776 | +TEST_F(TApp, IniOutputShortSingleDescription) { | ||
| 1777 | + std::string flag = "some_flag"; | ||
| 1778 | + const std::string description = "Some short description."; | ||
| 1779 | + app.add_flag("--" + flag, description); | ||
| 1780 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1781 | + run(); | ||
| 1782 | + | ||
| 1783 | + std::string str = app.config_to_str(true, true); | ||
| 1784 | + EXPECT_THAT(str, HasSubstr("; " + description + "\n" + flag + "=false\n")); | ||
| 1785 | +} | ||
| 1786 | + | ||
| 1787 | +TEST_F(TApp, IniOutputShortDoubleDescription) { | ||
| 1788 | + std::string flag1 = "flagnr1"; | ||
| 1789 | + std::string flag2 = "flagnr2"; | ||
| 1790 | + const std::string description1 = "First description."; | ||
| 1791 | + const std::string description2 = "Second description."; | ||
| 1792 | + app.add_flag("--" + flag1, description1); | ||
| 1793 | + app.add_flag("--" + flag2, description2); | ||
| 1794 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1795 | + run(); | ||
| 1796 | + | ||
| 1797 | + std::string str = app.config_to_str(true, true); | ||
| 1798 | + EXPECT_THAT( | ||
| 1799 | + str, HasSubstr("; " + description1 + "\n" + flag1 + "=false\n\n; " + description2 + "\n" + flag2 + "=false\n")); | ||
| 1800 | +} | ||
| 1801 | + | ||
| 1802 | +TEST_F(TApp, IniOutputGroups) { | ||
| 1803 | + std::string flag1 = "flagnr1"; | ||
| 1804 | + std::string flag2 = "flagnr2"; | ||
| 1805 | + const std::string description1 = "First description."; | ||
| 1806 | + const std::string description2 = "Second description."; | ||
| 1807 | + app.add_flag("--" + flag1, description1)->group("group1"); | ||
| 1808 | + app.add_flag("--" + flag2, description2)->group("group2"); | ||
| 1809 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1810 | + run(); | ||
| 1811 | + | ||
| 1812 | + std::string str = app.config_to_str(true, true); | ||
| 1813 | + EXPECT_THAT(str, HasSubstr("group1")); | ||
| 1814 | + EXPECT_THAT(str, HasSubstr("group2")); | ||
| 1815 | +} | ||
| 1816 | + | ||
| 1817 | +TEST_F(TApp, IniOutputHiddenOptions) { | ||
| 1818 | + std::string flag1 = "flagnr1"; | ||
| 1819 | + std::string flag2 = "flagnr2"; | ||
| 1820 | + double val{12.7}; | ||
| 1821 | + const std::string description1 = "First description."; | ||
| 1822 | + const std::string description2 = "Second description."; | ||
| 1823 | + app.add_flag("--" + flag1, description1)->group("group1"); | ||
| 1824 | + app.add_flag("--" + flag2, description2)->group("group2"); | ||
| 1825 | + app.add_option("--dval", val, "", true)->group(""); | ||
| 1826 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1827 | + run(); | ||
| 1828 | + | ||
| 1829 | + std::string str = app.config_to_str(true, true); | ||
| 1830 | + EXPECT_THAT(str, HasSubstr("group1")); | ||
| 1831 | + EXPECT_THAT(str, HasSubstr("group2")); | ||
| 1832 | + EXPECT_THAT(str, HasSubstr("dval=12.7")); | ||
| 1833 | + auto loc = str.find("dval=12.7"); | ||
| 1834 | + auto locg1 = str.find("group1"); | ||
| 1835 | + EXPECT_GT(locg1, loc); | ||
| 1836 | + // make sure it doesn't come twice | ||
| 1837 | + loc = str.find("dval=12.7", loc + 4); | ||
| 1838 | + EXPECT_EQ(loc, std::string::npos); | ||
| 1839 | +} | ||
| 1840 | + | ||
| 1841 | +TEST_F(TApp, IniOutputMultiLineDescription) { | ||
| 1842 | + std::string flag = "some_flag"; | ||
| 1843 | + const std::string description = "Some short description.\nThat has lines."; | ||
| 1844 | + app.add_flag("--" + flag, description); | ||
| 1845 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1846 | + run(); | ||
| 1847 | + | ||
| 1848 | + std::string str = app.config_to_str(true, true); | ||
| 1849 | + EXPECT_THAT(str, HasSubstr("; Some short description.\n")); | ||
| 1850 | + EXPECT_THAT(str, HasSubstr("; That has lines.\n")); | ||
| 1851 | + EXPECT_THAT(str, HasSubstr(flag + "=false\n")); | ||
| 1852 | +} | ||
| 1853 | + | ||
| 1854 | +TEST_F(TApp, IniOutputOptionGroup) { | ||
| 1855 | + std::string flag1 = "flagnr1"; | ||
| 1856 | + std::string flag2 = "flagnr2"; | ||
| 1857 | + double val{12.7}; | ||
| 1858 | + const std::string description1 = "First description."; | ||
| 1859 | + const std::string description2 = "Second description."; | ||
| 1860 | + app.add_flag("--" + flag1, description1)->group("group1"); | ||
| 1861 | + app.add_flag("--" + flag2, description2)->group("group2"); | ||
| 1862 | + auto og = app.add_option_group("group3", "g3 desc"); | ||
| 1863 | + og->add_option("--dval", val, "", true)->group(""); | ||
| 1864 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1865 | + run(); | ||
| 1866 | + | ||
| 1867 | + std::string str = app.config_to_str(true, true); | ||
| 1868 | + EXPECT_THAT(str, HasSubstr("group1")); | ||
| 1869 | + EXPECT_THAT(str, HasSubstr("group2")); | ||
| 1870 | + EXPECT_THAT(str, HasSubstr("dval=12.7")); | ||
| 1871 | + EXPECT_THAT(str, HasSubstr("group3")); | ||
| 1872 | + EXPECT_THAT(str, HasSubstr("g3 desc")); | ||
| 1873 | + auto loc = str.find("dval=12.7"); | ||
| 1874 | + auto locg1 = str.find("group1"); | ||
| 1875 | + auto locg3 = str.find("group3"); | ||
| 1876 | + EXPECT_LT(locg1, loc); | ||
| 1877 | + // make sure it doesn't come twice | ||
| 1878 | + loc = str.find("dval=12.7", loc + 4); | ||
| 1879 | + EXPECT_EQ(loc, std::string::npos); | ||
| 1880 | + EXPECT_GT(locg3, locg1); | ||
| 1881 | +} | ||
| 1882 | + | ||
| 1883 | +TEST_F(TApp, IniOutputVector) { | ||
| 1884 | + | ||
| 1885 | + std::vector<int> v; | ||
| 1886 | + app.add_option("--vector", v); | ||
| 1887 | + | ||
| 1888 | + args = {"--vector", "1", "2", "3"}; | ||
| 1889 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1890 | + run(); | ||
| 1891 | + | ||
| 1892 | + std::string str = app.config_to_str(); | ||
| 1893 | + EXPECT_EQ("vector=1 2 3\n", str); | ||
| 1894 | +} | ||
| 1895 | + | ||
| 1896 | +TEST_F(TApp, IniOutputFlag) { | ||
| 1897 | + | ||
| 1898 | + int v{0}, q{0}; | ||
| 1899 | + app.add_option("--simple", v); | ||
| 1900 | + app.add_flag("--nothing"); | ||
| 1901 | + app.add_flag("--onething"); | ||
| 1902 | + app.add_flag("--something", q); | ||
| 1903 | + | ||
| 1904 | + args = {"--simple=3", "--onething", "--something", "--something"}; | ||
| 1905 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1906 | + run(); | ||
| 1907 | + | ||
| 1908 | + std::string str = app.config_to_str(); | ||
| 1909 | + EXPECT_THAT(str, HasSubstr("simple=3")); | ||
| 1910 | + EXPECT_THAT(str, Not(HasSubstr("nothing"))); | ||
| 1911 | + EXPECT_THAT(str, HasSubstr("onething=true")); | ||
| 1912 | + EXPECT_THAT(str, HasSubstr("something=true true")); | ||
| 1913 | + | ||
| 1914 | + str = app.config_to_str(true); | ||
| 1915 | + EXPECT_THAT(str, HasSubstr("nothing")); | ||
| 1916 | +} | ||
| 1917 | + | ||
| 1918 | +TEST_F(TApp, IniOutputSet) { | ||
| 1919 | + | ||
| 1920 | + int v{0}; | ||
| 1921 | + app.add_option("--simple", v)->check(CLI::IsMember({1, 2, 3})); | ||
| 1922 | + | ||
| 1923 | + args = {"--simple=2"}; | ||
| 1924 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1925 | + run(); | ||
| 1926 | + | ||
| 1927 | + std::string str = app.config_to_str(); | ||
| 1928 | + EXPECT_THAT(str, HasSubstr("simple=2")); | ||
| 1929 | +} | ||
| 1930 | + | ||
| 1931 | +TEST_F(TApp, IniOutputDefault) { | ||
| 1932 | + | ||
| 1933 | + int v{7}; | ||
| 1934 | + app.add_option("--simple", v, "", true); | ||
| 1935 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1936 | + run(); | ||
| 1937 | + | ||
| 1938 | + std::string str = app.config_to_str(); | ||
| 1939 | + EXPECT_THAT(str, Not(HasSubstr("simple=7"))); | ||
| 1940 | + | ||
| 1941 | + str = app.config_to_str(true); | ||
| 1942 | + EXPECT_THAT(str, HasSubstr("simple=7")); | ||
| 1943 | +} | ||
| 1944 | + | ||
| 1945 | +TEST_F(TApp, IniOutputSubcom) { | ||
| 1946 | + | ||
| 1947 | + app.add_flag("--simple"); | ||
| 1948 | + auto subcom = app.add_subcommand("other"); | ||
| 1949 | + subcom->add_flag("--newer"); | ||
| 1950 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1951 | + args = {"--simple", "other", "--newer"}; | ||
| 1952 | + run(); | ||
| 1953 | + | ||
| 1954 | + std::string str = app.config_to_str(); | ||
| 1955 | + EXPECT_THAT(str, HasSubstr("simple=true")); | ||
| 1956 | + EXPECT_THAT(str, HasSubstr("other.newer=true")); | ||
| 1957 | +} | ||
| 1958 | + | ||
| 1959 | +TEST_F(TApp, IniOutputSubcomConfigurable) { | ||
| 1960 | + | ||
| 1961 | + app.add_flag("--simple"); | ||
| 1962 | + auto subcom = app.add_subcommand("other")->configurable(); | ||
| 1963 | + subcom->add_flag("--newer"); | ||
| 1964 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1965 | + args = {"--simple", "other", "--newer"}; | ||
| 1966 | + run(); | ||
| 1967 | + | ||
| 1968 | + std::string str = app.config_to_str(); | ||
| 1969 | + EXPECT_THAT(str, HasSubstr("simple=true")); | ||
| 1970 | + EXPECT_THAT(str, HasSubstr("[other]")); | ||
| 1971 | + EXPECT_THAT(str, HasSubstr("newer=true")); | ||
| 1972 | + EXPECT_EQ(str.find("other.newer=true"), std::string::npos); | ||
| 1973 | +} | ||
| 1974 | + | ||
| 1975 | +TEST_F(TApp, IniOutputSubsubcom) { | ||
| 1976 | + | ||
| 1977 | + app.add_flag("--simple"); | ||
| 1978 | + auto subcom = app.add_subcommand("other"); | ||
| 1979 | + subcom->add_flag("--newer"); | ||
| 1980 | + auto subsubcom = subcom->add_subcommand("sub2"); | ||
| 1981 | + subsubcom->add_flag("--newest"); | ||
| 1982 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 1983 | + args = {"--simple", "other", "--newer", "sub2", "--newest"}; | ||
| 1984 | + run(); | ||
| 1985 | + | ||
| 1986 | + std::string str = app.config_to_str(); | ||
| 1987 | + EXPECT_THAT(str, HasSubstr("simple=true")); | ||
| 1988 | + EXPECT_THAT(str, HasSubstr("other.newer=true")); | ||
| 1989 | + EXPECT_THAT(str, HasSubstr("other.sub2.newest=true")); | ||
| 1990 | +} | ||
| 1991 | + | ||
| 1992 | +TEST_F(TApp, IniOutputSubsubcomConfigurable) { | ||
| 1993 | + | ||
| 1994 | + app.add_flag("--simple"); | ||
| 1995 | + auto subcom = app.add_subcommand("other")->configurable(); | ||
| 1996 | + subcom->add_flag("--newer"); | ||
| 1997 | + | ||
| 1998 | + auto subsubcom = subcom->add_subcommand("sub2"); | ||
| 1999 | + subsubcom->add_flag("--newest"); | ||
| 2000 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 2001 | + args = {"--simple", "other", "--newer", "sub2", "--newest"}; | ||
| 2002 | + run(); | ||
| 2003 | + | ||
| 2004 | + std::string str = app.config_to_str(); | ||
| 2005 | + EXPECT_THAT(str, HasSubstr("simple=true")); | ||
| 2006 | + EXPECT_THAT(str, HasSubstr("[other]")); | ||
| 2007 | + EXPECT_THAT(str, HasSubstr("newer=true")); | ||
| 2008 | + EXPECT_THAT(str, HasSubstr("[other.sub2]")); | ||
| 2009 | + EXPECT_THAT(str, HasSubstr("newest=true")); | ||
| 2010 | + EXPECT_EQ(str.find("sub2.newest=true"), std::string::npos); | ||
| 2011 | +} | ||
| 2012 | + | ||
| 2013 | +TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) { | ||
| 2014 | + | ||
| 2015 | + app.add_flag("--simple"); | ||
| 2016 | + auto subcom = app.add_subcommand("other")->configurable(); | ||
| 2017 | + subcom->add_flag("--newer"); | ||
| 2018 | + | ||
| 2019 | + auto subsubcom = subcom->add_subcommand("sub2"); | ||
| 2020 | + subsubcom->add_flag("--newest"); | ||
| 2021 | + auto sssscom = subsubcom->add_subcommand("sub-level2"); | ||
| 2022 | + subsubcom->add_flag("--still_newer"); | ||
| 2023 | + auto s5com = sssscom->add_subcommand("sub-level3"); | ||
| 2024 | + s5com->add_flag("--absolute_newest"); | ||
| 2025 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 2026 | + args = {"--simple", "other", "sub2", "sub-level2", "sub-level3", "--absolute_newest"}; | ||
| 2027 | + run(); | ||
| 2028 | + | ||
| 2029 | + std::string str = app.config_to_str(); | ||
| 2030 | + EXPECT_THAT(str, HasSubstr("simple=true")); | ||
| 2031 | + EXPECT_THAT(str, HasSubstr("[other.sub2.sub-level2.sub-level3]")); | ||
| 2032 | + EXPECT_THAT(str, HasSubstr("absolute_newest=true")); | ||
| 2033 | + EXPECT_EQ(str.find(".absolute_newest=true"), std::string::npos); | ||
| 2034 | +} | ||
| 2035 | + | ||
| 2036 | +TEST_F(TApp, IniOutputQuoted) { | ||
| 2037 | + | ||
| 2038 | + std::string val1; | ||
| 2039 | + app.add_option("--val1", val1); | ||
| 2040 | + | ||
| 2041 | + std::string val2; | ||
| 2042 | + app.add_option("--val2", val2); | ||
| 2043 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 2044 | + args = {"--val1", "I am a string", "--val2", R"(I am a "confusing" string)"}; | ||
| 2045 | + | ||
| 2046 | + run(); | ||
| 2047 | + | ||
| 2048 | + EXPECT_EQ("I am a string", val1); | ||
| 2049 | + EXPECT_EQ("I am a \"confusing\" string", val2); | ||
| 2050 | + | ||
| 2051 | + std::string str = app.config_to_str(); | ||
| 2052 | + EXPECT_THAT(str, HasSubstr("val1=\"I am a string\"")); | ||
| 2053 | + EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'")); | ||
| 2054 | +} | ||
| 2055 | + | ||
| 2056 | +TEST_F(TApp, DefaultsIniOutputQuoted) { | ||
| 2057 | + | ||
| 2058 | + std::string val1{"I am a string"}; | ||
| 2059 | + app.add_option("--val1", val1, "", true); | ||
| 2060 | + | ||
| 2061 | + std::string val2{R"(I am a "confusing" string)"}; | ||
| 2062 | + app.add_option("--val2", val2, "", true); | ||
| 2063 | + app.config_formatter(std::make_shared<CLI::ConfigINI>()); | ||
| 2064 | + run(); | ||
| 2065 | + | ||
| 2066 | + std::string str = app.config_to_str(true); | ||
| 2067 | + EXPECT_THAT(str, HasSubstr("val1=\"I am a string\"")); | ||
| 2068 | + EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'")); | ||
| 2069 | +} |