Coder Social home page Coder Social logo

mmahnic / argumentum Goto Github PK

View Code? Open in Web Editor NEW
192.0 4.0 10.0 613 KB

C++ command line parsing library

License: Mozilla Public License 2.0

CMake 3.37% C++ 92.77% C 0.37% Shell 3.49%
parser library command-line argparse cpp cpp17 optparse argument-parser header-only argv

argumentum's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

argumentum's Issues

Error when consuming the library

Sans titre

I basically just used the includes and static library generated with Cmake + Visual Studio but I still can't compile my project.
However, the examples provided in the source code run perfectly ; perhaps because they use directly the source code instead of the build output.

Specify value name for optional arguments

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

Creating an argument that takes a list of strings produces the error string "Assignment is Not Implemented"

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.

compile error with basic example and latest master

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() )

Clean the arguments loaded with the @ parameter

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.

Suggestion on CMake consumption as non-installed library.

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.

Likely, the documentation for building and consuming the library should elaborated.

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.

A parameter of type std::optional<std::vector<>> will only ever be populated with the last element in the list.

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.