Code Monkey home page Code Monkey logo

structopt's People

Contributors

anonymerniklasistanonym avatar ken-matsui avatar p-ranav avatar wx257osn2 avatar

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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

structopt's Issues

Support `std::string_view`

With the current implementation, the option handling/parsing only works with a lot of allocations. If the implementation would use string_view internally and can save arguments as viewer structs, that could be neat.

Excess positional arguments do not generate an error.

If excess positional arguments are provided the parser does not raise an exception.

struct FileOptions {
  // Positional arguments
  // ./main <input_file> <output_file>
  std::string input_file;
  std::string output_file;
};
STRUCTOPT(FileOptions, input_file, output_file);

Executing ./main file1 file2 file3 does not raise an exception.

Custom help message

Hi, do you plan to add ability of setting up a custom help message? structopt adds --help command line flag unconditionally, without ability to override built-in help message format, so I think it makes sense even if you add a help description per argument in the future.
It requires only a small change, I made it to the structopt bundled in my project, you can see how it looks here

GCC with strong compilation flags (Werror) throws errors in include/structopt/is_number.hpp file

When including structopt in my custom project which adds strong compilation flags for GCC (-pedantic -Wall -Werror -Wextra -Wformat) the following errors appear:

In file included from [...]/structopt/include/structopt/parser.hpp:13,
                 from [...]/structopt/include/structopt/app.hpp:8,
                 from [...]/main.cpp:1:
[...]/structopt/include/structopt/is_number.hpp:9:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
    9 | static const bool is_binary_notation(std::string const &input) {
      |        ^~~~~
[...]/structopt/include/structopt/is_number.hpp:14:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   14 | static const bool is_hex_notation(std::string const &input) {
      |        ^~~~~
[...]/structopt/include/structopt/is_number.hpp:19:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   19 | static const bool is_octal_notation(std::string const &input) {
      |        ^~~~~
[...]/structopt/include/structopt/is_number.hpp: In function ‘bool structopt::details::is_valid_number(const string&)’:
[...]/structopt/include/structopt/is_number.hpp:34:12: error: comparison of unsigned expression in ‘>= 0’ is always true [-Werror=type-limits]
   34 |   while (j >= 0 && input[j] == ' ')
      |          ~~^~~~

My main.cpp:

#include <structopt/app.hpp>

int main()
{
  std::cout << "Test" << std::endl;
}

My CMakeLists.txt:

# Set minimum CMake version
cmake_minimum_required(VERSION 3.14)

# Set project name and the programming language
project("test" LANGUAGES CXX)

# Set path to project root
set(VENDOR_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor")

option(STRUCTOPT_TESTS "Don't build structopt tests" OFF)
option(STRUCTOPT_SAMPLES "Don't build structopt examples" OFF)
add_subdirectory("${VENDOR_DIR}/structopt" build_extern_structopt)

# Create executable with all provided sources
add_executable(${PROJECT_NAME} main.cpp)

# Link structopt
target_link_libraries(${PROJECT_NAME} PRIVATE structopt::structopt)

# Set library source files compilation flags for different compilers
target_compile_options(${PROJECT_NAME}
                       PRIVATE $<$<CXX_COMPILER_ID:GNU>:
                               -pedantic
                               -Wall
                               -Werror
                               -Wextra
                               -Wformat
                               >
                               $<$<CXX_COMPILER_ID:MSCV>:
                               /W4
                               /Wall
                               /WX
                               >)

# Set C++ version for the local source files
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)

My build commands build.sh:

#!/usr/bin/env bash

rm -rf build && mkdir -p build && cd build
cmake .. -G "Unix Makefiles"
cmake --build .

The complete log:

-- The CXX compiler identification is GNU 10.1.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: PROJECT_ROOT/build
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
In file included from PROJECT_ROOT/vendor/structopt/include/structopt/parser.hpp:13,
                 from PROJECT_ROOT/vendor/structopt/include/structopt/app.hpp:8,
                 from PROJECT_ROOT/main.cpp:1:
PROJECT_ROOT/vendor/structopt/include/structopt/is_number.hpp:9:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
    9 | static const bool is_binary_notation(std::string const &input) {
      |        ^~~~~
PROJECT_ROOT/vendor/structopt/include/structopt/is_number.hpp:14:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   14 | static const bool is_hex_notation(std::string const &input) {
      |        ^~~~~
PROJECT_ROOT/vendor/structopt/include/structopt/is_number.hpp:19:8: error: type qualifiers ignored on function return type [-Werror=ignored-qualifiers]
   19 | static const bool is_octal_notation(std::string const &input) {
      |        ^~~~~
PROJECT_ROOT/vendor/structopt/include/structopt/is_number.hpp: In function ‘bool structopt::details::is_valid_number(const string&)’:
PROJECT_ROOT/vendor/structopt/include/structopt/is_number.hpp:34:12: error: comparison of unsigned expression in ‘>= 0’ is always true [-Werror=type-limits]
   34 |   while (j >= 0 && input[j] == ' ')
      |          ~~^~~~
cc1plus: all warnings being treated as errors
make[2]: *** [CMakeFiles/test.dir/build.make:82: CMakeFiles/test.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:115: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

This was tested on a Linux PC (Kernel: 5.8.1-2-MANJARO, Architecture: x86_64 GNU/Linux) with c++ (GCC) 10.1.0 and cmake 3.18.1.

It is just a minor issue I just removed the const qualifiers and the j >= 0 as described in the warnings and then everything worked for me (my main.cpp was at one point more advanced but I trimmed it for this issue - --help and the other features were working fine).

At least one positional argument is required to properly raise an error for unknown optional arguments.

If you only have optional arguments in the structure no error will be produced when unknown optional or positional arguments are provided.

struct Options {
  std::optional<std::string> directory;
};
STRUCTOPT(Options, directory);

Executing ./a.out --bad or ./a.out bad will not raise an exception. If you add a positional argument, you will get the expected result.

struct Options {
  std::optional<std::string> directory;
  std::string dummy;
};
STRUCTOPT(Options, directory, dummy);

Ambiguous help, short name duplicates

I seems that first character of long-name is used in a short-name.

In case:

struct Options
{
  // oositional flags
  // ./main [--bar] [--baz]
  std::optional<bool> bar = false;
  std::optional<bool> baz = false;
};
STRUCTOPT(Options, bar, baz);

Help prints:

USAGE: my_app [FLAGS] [OPTIONS] 

FLAGS:
    -b, --bar
    -b, --baz

OPTIONS:
    -h, --help <help>
    -v, --version <version>

There are -b twice. Ii can be confusing, specially with many another options between duplicates.

BTW, it's possible (or is planned) to set flag name (short name)?

Maybe something like

std::optional<bool> baz = false;
...
STRUCTOPT(Options, bar, structopt::short(baz, "z"));

Exception without try catch?

#include <iostream>
#include <optional>
#include <string>

#include <structopt/app.hpp>

struct Options {
  std::string db_name;
  std::string path_files;
  std::string path_archive;
  enum class LogLevel { trace, debug, info, warn, err, critical, off };
  std::optional<LogLevel> log_level = LogLevel::debug;
};
STRUCTOPT(Options, db_name, path_files, path_archive, log_level);

int main(int argc, char* argv[]) {
  auto opts = structopt::app("test", "1.0.0.1").parse<Options>(argc, argv);

  std::cout << "Hello World!\n";
}

without parameters
./test.exe

Microsoft Visual Studio Community 2019
Version 16.7.2
VisualStudio.16.Release/16.7.2+30413.136

boost::pfr

In the current beta release of boost, boost::pfr comes with a new feature for extracting the struct name from a given type. This way structopt could get rid of the library visit_struct and fully rely on boost::pfr. Or, since the new boost::pfr feature requries C++20, to still support older C++ standards , the current reflection mechanism might stay as fallback.

Provide help string for arguments

Hello,

I would like to add some help strings for the arguments / subcommands defined in the options struct.

i.e. - provide an explanation for what each subcommand does or for the arguments in the help usage.

Is it currently possible?

Thanks for the great work!

compile error when structopt is used in namespace

Hello and first of all, thanks for this nice piece of software !

When STRUCTOPT(...) is used inside a namespace, I encounter the following error:

/home/chybz/dev/zap/build/root/include/structopt/third_party/visit_struct/visit_struct.hpp:839:22: error: ‘visitable’ is not a class template
  839 |   template <> struct visitable<STRUCT_NAME, void> {                                      \
      |                      ^~~~~~~~~
/home/chybz/dev/zap/build/root/include/structopt/app.hpp:13:19: note: in expansion of macro ‘VISITABLE_STRUCT’
   13 | #define STRUCTOPT VISITABLE_STRUCT
      |                   ^~~~~~~~~~~~~~~~
so.cpp:16:1: note: in expansion of macro ‘STRUCTOPT’
   16 | STRUCTOPT(Options, config_file, bind_address, verbose, user, files);
      | ^~~~~~~~~
/home/chybz/dev/zap/build/root/include/structopt/third_party/visit_struct/visit_struct.hpp:839:51: error: explicit specialization of non-template ‘foo::visit_struct::traits::visitable’
  839 |   template <> struct visitable<STRUCT_NAME, void> {

Here's the minimal example I used, compiled with gcc (Debian 10.2.1-6) 10.2.1 20210110:

g++ -Wall -std=c++20 -o test test.cpp
#include <iostream>
#include <optional>
#include <vector>

#include <structopt/app.hpp>

namespace foo {

struct Options {
   std::string config_file;
   std::optional<std::string> bind_address;
   std::optional<bool> verbose = false;
   std::optional<std::pair<std::string, std::string>> user;
   std::vector<std::string> files;
};
STRUCTOPT(Options, config_file, bind_address, verbose, user, files);

}

int main(int argc, char *argv[]) {

  try {
    auto options = structopt::app("my_app").parse<foo::Options>(argc, argv);

    std::cout << "config_file  = " << options.config_file << "\n";
  } catch (structopt::exception& e) {
    std::cout << e.what() << "\n";
    std::cout << e.help();
  }
}

If I remove namespace foo { ... }, it compiles without error.

Could you please have a look ?
Thank you !

config file vs args

The examples don't make clear, if all arguments can be passed from within a config file imho. Can this be done?

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.