catchorg / Clara

A simple to use, composable, command line parser for C++ 11 and beyond
Boost Software License 1.0
648 stars 67 forks source link

Provide a mechanism for "default" values #82

Open johschmitz opened 5 years ago

johschmitz commented 5 years ago

One example for this is a default output filename if none is provided.

parnmatt commented 5 years ago

Use a struct

if you make your own struct, you can set default arguments for each of the values.

namespace fs = std::filesystem;
struct cli_args {
    bool help{false};
    fs::path filename{"/some/default/path/location/file.txt"}
    // ...
};

auto cli_parser(cli_args& args) {
    return clara::Help(args.help)
        | clara::Opt(args.filename, "filename")[-f][--file]("filename of something")
        |  // ...
}

int main(int argc, char* argv[]) {
    auto args = cli_args{};
    auto parser = cli_parser(args);
    auto const parsed = args.parse(clara::Args(argc, argv));
    // ...
}

For more control, I use a class with const accessors, which also has some private only variables used for lifetime of some things; and I make cli_parser a member function, and have a parse member function too.


For example; here is a simple one I am using myself:


class cli_args {
public:
    auto parser() noexcept -> clara::Parser& { return m_parser; }

    template <typename... Args>
    auto parse(Args&&... args) -> decltype(auto) {
        return m_parser.parse(std::forward<Args>(args)...);
    }

    bool constexpr help() const noexcept { return m_help; }
    auto constexpr tree() const noexcept -> std::string const& { return m_tree; }
    auto constexpr list_dir() const noexcept -> fs::path const& { return m_list_dir; }
    auto constexpr workers() const noexcept { return m_workers; }
    auto constexpr log() noexcept -> std::ostream& { return m_log; }
    auto constexpr output_dir() const noexcept -> fs::path const& { return m_output_dir; }

private:
    bool m_help{false};
    std::string m_tree{"output"};
    fs::path m_list_dir{data_dir};
    unsigned int m_workers{std::max(std::thread::hardware_concurrency(), 1u)};
    std::ostream m_log{std::clog.rdbuf()};
    std::ofstream m_log_{};
    fs::path m_output_dir{data_dir};

    clara::Parser m_parser{clara::Help(m_help)
                           | clara::Opt(m_tree, "tree-name")["-t"]["--tree"]("name of the TTree to use")
                           | clara::Opt(m_list_dir, "dirname")["-i"]["--list-dir"]("directory of list files")
                           | clara::Opt(m_workers, "number")["-j"]["--workers"]("number of parallel workers")
                           | clara::Opt(
                               [&](fs::path const& filename) {
                                   m_log_.open(filename);
                                   m_log.rdbuf(m_log_.rdbuf());
                                   return clara::ParserResult::ok(clara::ParseResultType::Matched);
                               },
                               "filename")["-l"]["--log"]("set log file")
                           | clara::Opt(m_output_dir, "dirname")["-o"]["--output"]("output directory")};
};