mmahnic / argumentum Goto Github PK
View Code? Open in Web Editor NEWC++ command line parsing library
License: Mozilla Public License 2.0
C++ command line parsing library
License: Mozilla Public License 2.0
ubuntu 21.04,
g++ --version
g++ (Ubuntu 10.3.0-1ubuntu1) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
In file included from /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/value.h:6, from /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/option.h:6, from /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/optionconfig.h:6, from /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/argparser.h:11, from /home/cmorgan/projects/a/argumentum/include/argumentum/argparse.h:6, from /home/cmorgan/projects/a/basic.cpp:2: /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/convert.h: In instantiation of ‘argumentum::parse_int<int>::<lambda(auto:1)> [with auto:1 = long long unsigned int]’: /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/convert.h:49:25: required from ‘T argumentum::parse_int(const string&) [with T = int; std::string = std::__cxx11::basic_string<char>]’ /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/convert.h:130:32: required from here /home/cmorgan/projects/a/argumentum/include/argumentum/../../src/convert.h:41:16: error: comparison of integer expressions of different signedness: ‘long long unsigned int’ and ‘int’ [-Werror=sign-compare] 41 | if ( res < std::numeric_limits<T>::min() || res > std::numeric_limits<T>::max() )
Hello! I'm getting trouble using the library as a header-only library. The existing documentation doesn't help either.
Here's what I got when I tried to use the library as a header-only library:
> cat <<EOF > argentum_example.cc
#include <climits>
#include <argumentum/argparse.h>
#include <numeric>
#include <vector>
using namespace std;
using namespace argumentum;
int main( int argc, char** argv )
{
vector<int> numbers;
bool isSum = false;
auto parser = argument_parser{};
auto params = parser.params();
parser.config().program( argv[0] ).description( "Accumulator" );
params.add_parameter( numbers, "N" ).minargs( 1 ).metavar( "INT" ).help( "Integers" );
params.add_parameter( isSum, "--sum", "-s" )
.nargs( 0 )
.help( "Sum the integers (default: find the max)" );
if ( !parser.parse_args( argc, argv, 1 ) )
return 1;
auto mmax = []( auto&& a, auto&& b ) { return max( a, b ); };
auto acc = isSum ? accumulate( numbers.begin(), numbers.end(), 0 )
: accumulate( numbers.begin(), numbers.end(), INT_MIN, mmax );
cout << acc << "\n";
return 0;
}
EOF
> c++ -Wall -Werror -o argumentum_example -I `pwd`/argumentum/include argumentum_example.cc
/usr/bin/ld: /tmp/ccxJUb3B.o: warning: relocation against `_ZTVN10argumentum5ValueE' in read-only section `.text._ZN10argumentum5ValueC2Ev[_ZN10argumentum5ValueC5Ev]'
/usr/bin/ld: /tmp/ccxJUb3B.o: in function `main':
argumentum_example.cc:(.text+0x8c): undefined reference to `argumentum::argument_parser::config()'
/usr/bin/ld: argumentum_example.cc:(.text+0xc7): undefined reference to `argumentum::ParserConfig::program(std::basic_string_view<char, std::char_traits<char> >)'
/usr/bin/ld: argumentum_example.cc:(.text+0xff): undefined reference to `argumentum::ParserConfig::description(std::basic_string_view<char, std::char_traits<char> >)'
/usr/bin/ld: argumentum_example.cc:(.text+0x3a6): undefined reference to `argumentum::argument_parser::parse_args(int, char**, int)'
/usr/bin/ld: argumentum_example.cc:(.text+0x3b5): undefined reference to `argumentum::ParseResult::operator bool() const'
/usr/bin/ld: argumentum_example.cc:(.text+0x3c9): undefined reference to `argumentum::ParseResult::~ParseResult()'
/usr/bin/ld: argumentum_example.cc:(.text+0x585): undefined reference to `argumentum::ParseResult::~ParseResult()'
/usr/bin/ld: /tmp/ccxJUb3B.o: in function `argumentum::argument_parser::params()':
argumentum_example.cc:(.text._ZN10argumentum15argument_parser6paramsEv[_ZN10argumentum15argument_parser6paramsEv]+0x2a): undefined reference to `argumentum::ParameterConfig::ParameterConfig(argumentum::
...
That is the code is compiled successfully but the linker has failed because the library needs its "to-be-compiled" components.
On the other hand an attempt to compile the sample using a simple CMakeLists.txt like this also fails:
> cat <<EOF >CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
if (POLICY CMP0022)
cmake_policy(SET CMP0022 NEW)
endif()
project(argumentum_example)
# to define CMAKE_INSTALL_INCLUDEDIR
include(GNUInstallDirs)
add_subdirectory(argumentum/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/argumentum/include)
add_executable(argumentum_example argumentum_example.cc)
EOF
It fails because copying of the headers into an uber-header inside ${CMAKE_CURRENT_BINARY_DIR}/argumentum/include/argumentum/
fails with a cryptic error:
1/5] Preparing library headers for publishing
FAILED: argumentum/include/fake_create_headers.cpp argumentum/include/argumentum/argparse.h /home/alex/tmp/c++/argumentum_example/build/argumentum/include/fake_create_headers.cpp /home/alex/tmp/c++/argumentum_example/build/argumentum/include/argumentum/argparse.h
cd /home/alex/tmp/c++/argumentum_example/build/argumentum/include && /usr/bin/cmake -E copy /home/alex/tmp/c++/argumentum_example/util/faketarget.cpp /home/alex/tmp/c++/argumentum_example/build/argumentum/include/fake_create_headers.cpp && /usr/bin/cmake -D TOP_SOURCE_DIR="/home/alex/tmp/c++/argumentum_example" -D P_SOURCE_DIR="/home/alex/tmp/c++/argumentum_example/argumentum/include" -D P_BINARY_DIR="/home/alex/tmp/c++/argumentum_example/build/argumentum/include" -P /home/alex/tmp/c++/argumentum_example/argumentum/include/prepare-headers.cmake
Error copying file "/home/alex/tmp/c++/argumentum_example/util/faketarget.cpp" to "/home/alex/tmp/c++/argumentum_example/build/argumentum/include/fake_create_headers.cpp".
All in all I would greatly appreciate a working example for a header-only usage.
Thank you in advance.
When a line of a file from which arguments are read contains leading or trailing spaces, those spaces become part of the argument. The parser does not recognize the arguments with leading or trailing spaces. The lines should be cleaned when they are read. Double quotes could be used where leading or trailing spaces are needed.
I have the following parser setup:
std::list<std::string> include_directories;
std::string input_file;
auto parser = argumentum::argument_parser{};
auto params = parser.params();
parser.config().program(argv[0]).description("A General-Purpose IDL Compiler");
params.add_parameter(include_directories, "-I", "--include_directories")
.minargs(1)
.required(false)
.help("The list of include directories ");
params.add_parameter(input_file, "-i", "--input_file")
.nargs(1)
.required(true)
.help("The input file to parse");
It seems to work fine, but when I invoke my program with the following input:
my_program.exe -i C:\my_directory\my_file.txt -I C:\my_directory\
I get the output:
** Assignment is not implemented. ('C:\my_directory\')
Am I using unimplemented behavior somewhere? The message is a bit cryptic.
If you have an std::optional parameter containing an std::vector, you currently need to manually override the action in order to get it to behave properly.
If you input more than a single value for that argument, it will only ever insert a single value into the vector, and then continuously overwrite that one value.
Example code:
std::optional<std::vector<std::string>> my_optional_value = std::nullopt;
auto parser = argumentum::argument_parser();
auto params = argument_parser.params();
parser.config().program(argv[0]).description(
"A dummy program."
);
params.add_parameter(my_optional_value, "--dummy", "-d")
.help("A dummy value")
.metavar("DUMMY")
.minargs(1)
.required(true);
assert(parser.parse_args(argc, argv, 1)); //Asserting here for the example. Just assume it parses successfully
for(auto it = my_optional_value.value().begin(); it != my_optional_value.value().end(); it++)
{
std::cout << *it << std::endl;
}
Input:
-d A B C D
Output:
D
If I update the parameter by adding the following method invocation:
.action( [&]( auto& target, const std::string& value ) {
if(!target.has_value())
{
target = std::make_optional<ArgumentList>(ArgumentList());
}
target.value().push_back(value);
} )
I get the output:
A
B
C
D
As such, it looks to me like the default action for an optional vector isn't appending anything to the vector, and is instead continuously overwriting the first value.
I have the following:
params.add_parameter(join, "--join", "-j" )
.nargs(2)
.help("Join an existing cluster");
which prints the following: -j, --join JOIN JOIN Join an existing cluster
I want to set JOIN to something, for each value. I tried to use the metavar, like argprase in python like so: .metavar("IP CERTPATH")
however that just resulted in -j, --join IP CERTPATH IP CERTPATH
Hi, recently decided to consume this library as part of a larger project. We generally prefer not to install CMake libraries and distribute all dependencies via git submodules to pin dependency versions and make the building less dependent on users needing to understand/know what the actual dependencies are.
Being able to consume this library via the standard, non-install, CMake syntax of:
add_subdirectory(argumentum)
target_link_libraries(my_target PUBLIC argumentum)
... would be ideal. This is a more modern way of consuming external dependencies and removes the need for using the global include_directories
command, which has significant drawbacks in more complex CMake projects.
Would you be open to a pull request reorganizing your CMake to handle this?
Right now, I am getting around this limitation by ignoring the argumentum CMake entirely and consuming it with the following:
add_library(argumentum INTERFACE)
target_include_directories(argumentum SYSTEM INTERFACE 3rdparty/argumentum/include)
# ...
target_link_libraries(my_target PUBLIC argumentum)
This might also be a suggestion for an alternative piece of documentation in your building documentation in lieu of a reorganization.
Thanks for your maintenance.
The version of project seems to be 0.3.2. Could you create tag v0.3.2
?
Line 3 in cb7bf0e
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.