kamchatka-volcano / cmdlime Goto Github PK
View Code? Open in Web Editor NEWPossibly the least verbose command line parsing library for C++
License: Microsoft Public License
Possibly the least verbose command line parsing library for C++
License: Microsoft Public License
std::string_view has no constructor from iterator and size.
Error in line 158 of string_utils.h
Fix: return std::string_view{ str.data(), res };
Error in line 166 of string_utils.h
Fix return std::string_view{ str.data() + static_cast(res + val.size()), str.size() - (res + val.size()) };
If you modify ex05.cpp, line 8 to be
PARAM(name, std::string) << cmdlime::WithoutShortName{};
You get this error with Clang:
$› clang++ -I ../include/ -std=c++17 ex05.cpp
In file included from ex05.cpp:1:
In file included from ../include/cmdlime/config.h:2:
In file included from ../include/cmdlime/gnuconfig.h:3:
In file included from ../include/cmdlime/configreader.h:5:
In file included from ../include/cmdlime/detail/configmacro.h:2:
../include/cmdlime/detail/param.h:126:39: error: 'format' is a private member of 'cmdlime::detail::Config<cmdlime::detail::FormatType::GNU>'
static_assert(Format<TConfig::format>::shortNamesEnabled, "Current command line format doesn't support short names");
^
ex05.cpp:8:37: note: in instantiation of member function 'cmdlime::detail::ParamCreator<std::__1::basic_string<char>, Cfg>::operator<<'
requested here
PARAM(name, std::string) << cmdlime::WithoutShortName{};
^
../include/cmdlime/detail/config.h:142:33: note: declared private here
constexpr static FormatType format = formatType;
^
1 error generated.
$>
Changing the format static member in include/cmdlime/detail/config.h:142:33 from private to public fixes the issue.
This is the GNU format with the ability to register alternative names starting with a forward slash.
All names are in kebab-case
.
Parameters and flags prefix: --
Short names are supported. Short names prefix: -
Parameters usage: --parameter value
, --parameter=value
, -p value
or -pvalue
. /parameter:value
and /parameter value
are also supported, they have to be enabled with << WithSlashForm{}
modifier or <<WithShortNameSlashForm
to add /p:value
or /p value
, or << SlashName{"custom-name"}
and << SlashShortName{"c"}
to override an automatic name generation.
Flags usage: --flag
, -f
. /flag
or /f
are also supported. They have to be enabled with << WithSlashForm{}
or <<WithShortNameSlashForm
modifiers, or << SlashName{"custom-name"}
and << SlashShortName{"c"}
to override an automatic name generation.
Flags in short form (except those that start with a slash) can be "glued" together: -abc
or with one parameter: -fp value
.
Default help flag: -h
, --help
, -?
, or /?
.
Unknown parameters, flags and arguments errors should be emitted with a default unregistered options handler. The user should be able to override it by adding a custom handler to ignore or filter unregistered data. It should be possible to register a handler globally or for a specified Config type.
Thank you for the great CLI parser! When I include cmdlime in my project, the build fails. The flags that I have added for my project are:
The error is:
In file included from main.cpp:2:
In file included from _deps/cmdlime-src/include/cmdlime/config.h:2:
In file included from _deps/cmdlime-src/include/cmdlime/gnuconfig.h:3:
In file included from _deps/cmdlime-src/include/cmdlime/configreader.h:4:
In file included from _deps/cmdlime-src/include/cmdlime/detail/config.h:3:
_deps/cmdlime-src/include/cmdlime/detail/usageinfocreator.h:321:16: error: implicit conversion loses integer precision: 'unsigned long' to 'int' [-Werror,-Wshorten-64-to-32]
return size;
~~~~~~ ^~~~
_deps/cmdlime-src/include/cmdlime/detail/usageinfocreator.h:101:26: note: in instantiation of member function 'cmdlime::detail::UsageInfoCreator<cmdlime::detail::FormatType::GNU>::maxOptionNameSize' requested here
, maxOptionNameSize_(maxOptionNameSize() + outputSettings.columnsSpacing)
^
_deps/cmdlime-src/include/cmdlime/detail/config.h:69:16: note: in instantiation of member function 'cmdlime::detail::UsageInfoCreator<cmdlime::detail::FormatType::GNU>::UsageInfoCreator' requested here
return UsageInfoCreator<formatType>{name, UsageInfoFormat{}, params, paramLists, flags, args, argList_.get()}.create();
^
main.cpp:18:22: note: in instantiation of member function 'cmdlime::detail::Config<cmdlime::detail::FormatType::GNU>::usageInfo' requested here
std::cout << cfg.usageInfo("project");
Here's my main.cpp for reference:
#include <project/version.h>
#include <cmdlime/config.h>
#include <iostream>
auto main(int argc, char** argv) -> int {
struct Cfg : public cmdlime::Config {
PARAM(t1, std::string);
PARAM(t2, int);
EXITFLAG(help);
EXITFLAG(version);
} cfg;
try {
cfg.readCommandLine(argc, argv);
} catch (const cmdlime::Error& e) {
std::cerr << e.what();
std::cout << cfg.usageInfo("project");
return -1;
}
if (cfg.help) {
std::cout << cfg.usageInfoDetailed("project");
return 0;
}
if (cfg.version) {
std::cout << PROJECT_VERSION;
return 0;
}
return 0;
}
This was tested on macOS 11.3 (Intel architecture) with AppleClang 12.0.5 and cmake 3.20.2.
Hi,
would it be possible to create release version or tag. I use this lib, but I would like to link my app to a specific release.
Thanks
I tried to build the examples, but I got stuck at the first one.
The current build script does not build them, but I added the following to CMakeLists.txt
:
add_executable(ex01 examples/ex01.cpp)
target_link_libraries(ex01 PRIVATE cmdlime)
Trying to build with g++ 9.3.0 on Ubuntu 20.04.2 LTS gives the following errors:
In file included from /src/cmdlime/include/cmdlime/configreader.h:5,
from /src/cmdlime/include/cmdlime/gnuconfig.h:3,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/examples/ex01.cpp: In function ‘int main(int, char**)’:
/src/cmdlime/include/cmdlime/detail/configmacro.h:12:105: error: invalid use of ‘this’ in non-member function
12 | #define ARG(name, type) type name = cmdlime::detail::ArgCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~~~
/src/cmdlime/examples/ex01.cpp:7:9: note: in expansion of macro ‘ARG’
7 | ARG(zipCode, int);
| ^~~
/src/cmdlime/include/cmdlime/detail/configmacro.h:12:95: error: template argument 1 is invalid
12 | #define ARG(name, type) type name = cmdlime::detail::ArgCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~~~~~~~
/src/cmdlime/examples/ex01.cpp:7:9: note: in expansion of macro ‘ARG’
7 | ARG(zipCode, int);
| ^~~
In file included from /src/cmdlime/include/cmdlime/configreader.h:5,
from /src/cmdlime/include/cmdlime/gnuconfig.h:3,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/include/cmdlime/detail/configmacro.h:8:109: error: invalid use of ‘this’ in non-member function
8 | #define PARAM(name, type) type name = cmdlime::detail::ParamCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~~~
/src/cmdlime/examples/ex01.cpp:8:9: note: in expansion of macro ‘PARAM’
8 | PARAM(name, std::string);
| ^~~~~
/src/cmdlime/include/cmdlime/detail/configmacro.h:8:99: error: template argument 1 is invalid
8 | #define PARAM(name, type) type name = cmdlime::detail::ParamCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~~~~~~~
/src/cmdlime/examples/ex01.cpp:8:9: note: in expansion of macro ‘PARAM’
8 | PARAM(name, std::string);
| ^~~~~
In file included from /src/cmdlime/include/cmdlime/configreader.h:5,
from /src/cmdlime/include/cmdlime/gnuconfig.h:3,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/include/cmdlime/detail/configmacro.h:12:110: error: template argument 2 is invalid
12 | #define ARG(name, type) type name = cmdlime::detail::ArgCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~
/src/cmdlime/examples/ex01.cpp:7:9: note: in expansion of macro ‘ARG’
7 | ARG(zipCode, int);
| ^~~
In file included from /src/cmdlime/include/cmdlime/configreader.h:5,
from /src/cmdlime/include/cmdlime/gnuconfig.h:3,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/include/cmdlime/detail/configmacro.h:8:114: error: template argument 2 is invalid
8 | #define PARAM(name, type) type name = cmdlime::detail::ParamCreator<type, std::remove_reference_t<decltype(*this)>>{*this, #name, #type, [this]()->type&{return name;}}
| ^~
/src/cmdlime/examples/ex01.cpp:8:9: note: in expansion of macro ‘PARAM’
8 | PARAM(name, std::string);
| ^~~~~
In file included from /src/cmdlime/include/cmdlime/detail/gnuformat.h:2,
from /src/cmdlime/include/cmdlime/gnuconfig.h:6,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/include/cmdlime/detail/parser.h: In lambda function:
/src/cmdlime/include/cmdlime/detail/parser.h:68:13: warning: control reaches end of non-void function [-Wreturn-type]
68 | [&](auto param){
| ^~~~~~~~~~~~~~~~
69 | switch(mode){
| ~~~~~~~~~~~~~
70 | case FindMode::Name:
| ~~~~~~~~~~~~~~~~~~~~
71 | return param->info().name() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72 | case FindMode::ShortName:
| ~~~~~~~~~~~~~~~~~~~~~~~~~
73 | return param->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74 | case FindMode::All:
| ~~~~~~~~~~~~~~~~~~~
75 | return param->info().name() == name || param->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76 | }
| ~
77 | });
| ~
/src/cmdlime/include/cmdlime/detail/parser.h: In lambda function:
/src/cmdlime/include/cmdlime/detail/parser.h:86:13: warning: control reaches end of non-void function [-Wreturn-type]
86 | [&](auto paramList){
| ^~~~~~~~~~~~~~~~~~~~
87 | switch(mode){
| ~~~~~~~~~~~~~
88 | case FindMode::Name:
| ~~~~~~~~~~~~~~~~~~~~
89 | return paramList->info().name() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90 | case FindMode::ShortName:
| ~~~~~~~~~~~~~~~~~~~~~~~~~
91 | return paramList->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92 | case FindMode::All:
| ~~~~~~~~~~~~~~~~~~~
93 | return paramList->info().name() == name || paramList->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94 | }
| ~
95 | });
| ~
In file included from /src/cmdlime/include/cmdlime/detail/gnuformat.h:2,
from /src/cmdlime/include/cmdlime/gnuconfig.h:6,
from /src/cmdlime/include/cmdlime/config.h:2,
from /src/cmdlime/examples/ex01.cpp:1:
/src/cmdlime/include/cmdlime/detail/parser.h: In lambda function:
/src/cmdlime/include/cmdlime/detail/parser.h:123:13: warning: control reaches end of non-void function [-Wreturn-type]
123 | [&](auto flag){
| ^~~~~~~~~~~~~~~
124 | switch(mode){
| ~~~~~~~~~~~~~
125 | case FindMode::Name:
| ~~~~~~~~~~~~~~~~~~~~
126 | return flag->info().name() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127 | case FindMode::ShortName:
| ~~~~~~~~~~~~~~~~~~~~~~~~~
128 | return flag->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129 | case FindMode::All:
| ~~~~~~~~~~~~~~~~~~~
130 | return flag->info().name() == name || flag->info().shortName() == name;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131 | }
| ~
132 | });
| ~
Building with clang++ 10 on the same system seems to work. Building with MSVC (Visual Studio 2019) on Windows gives just a few warnings, so maybe I'm missing something in the g++ case:
c:\src\cmdlime\include\cmdlime\detail\parser.h(77) : warning C4715: '<lambda_d6bf33724169dfe5569812608f3db3ac>::operator()<gsl::not_null<cmdlime::detail::IParam *> >': not all control paths return a value
c:\src\cmdlime\include\cmdlime\detail\parser.h(132) : warning C4715: '<lambda_027da08a6184456737a8fd32a83f0ee3>::operator()<gsl::not_null<cmdlime::detail::IFlag *> >': not all control paths return a value
c:\src\cmdlime\include\cmdlime\detail\parser.h(95) : warning C4715: '<lambda_1cce2af26feeeaaa5a7e6c0694b00dac>::operator()<gsl::not_null<cmdlime::detail::IParamList *> >': not all control paths return a value
I haven't tried the other examples yet.
A common use case with command line parsing libraries is to load startup configuration parameters that were not passed on the command line from a ".env" file (simple key- value pair file) or similar.
So my feature request would be to provide support for reading parameters that were not given as command line input from a .env file and if that also fails (file not found, cant be read or key doesn't exist in the file) then fall back to the default argument / behavior registered for the argument.
Example of .env file based on Readme parameters:
zipCode=684007
name=John
verbose=true
I like the library a lot and it perfectly embraces the DRY rule for command line parsing. However in my projects I always end up having to repeat myself anyway because I need to read my environment file for every single parameter that I registered.
All names are in PascalCase
Parameters and flags prefix: -
Short names aren't supported
Parameters usage: -Parameter value
or -Parameter:value
Flags usage: -Flag
Flags can't be glued together like in POSIX format.
Default help flag: -?
.
Validators for optional values should take the contained value as an argument and they shouldn't be invoked for empty values as there's nothing to validate in that case.
Possible interface:
struct CommandCfg: public cmdlime::Config{
//FLAG, PARAM, ARG, etc
};
struct Cfg : public cmdlime::Config {
//FLAG, PARAM, ARG, etc
COMMAND(commandName, CommandCfg); //creates std::optional<CommandCfg> commandName;
};
All names are in lowercase, by default short names are used, long name can be enabled with << UseLongName{}
modifier.
Parameters and flags prefix: /
Parameters usage: /parameter value
or /parameter:value
Flags usage: /flag
Flags can't be glued together like in POSIX format.
Default help flag: /?
.
--help
flag implicitly generated with ConfigReader doesn't show the full usage info if any of config fields is invalid.
This has already been tested with https://github.com/vinniefalco/Amalgamate and it seems to work fine.
A change to includes format may be required, and there should be an unit tests configuration using a single header. CI configurations for running amalgamation, testing it, and publishing a single header on each new release should also be created.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.