// // cli.h // tax-manager // // Created by Sam Jaffe on 10/8/20. // Copyright © 2020 Sam Jaffe. All rights reserved. // #pragma once #include #include #include #include #include #include #include #include "lambda_cast.h" #include "types.h" namespace cli { class cli { public: using args_t = std::vector; using callback = std::function; private: std::istream &in_; std::string prompt_; std::unordered_map arguments_; std::unordered_map callbacks_; bool eof_; public: cli(std::string const & prompt, std::istream &in = std::cin); cli(std::istream &in = std::cin); template cli & register_callback(std::string const & handle, std::function cb); template cli & register_callback(std::string const & handle, F && cb) { return register_callback(handle, lambdas::FFL(cb)); } template cli & register_query(std::string const & handle, std::function cb); template cli & register_query(std::string const & handle, F && cb) { return register_query(handle, lambdas::FFL(cb)); } void run() const; private: bool active() const; }; template void cli_invoke(std::function cb, cli::args_t const & args, std::index_sequence) { std::tuple...> object; if (string_utils::cast(args, object)) { cb(std::move(std::get(object))...); } } template cli & cli::register_callback(std::string const & handle, std::function cb) { constexpr size_t N = sizeof...(Args); arguments_.emplace(handle, N); callbacks_.emplace(handle, [=](args_t args) { if (N > args.size()) { std::cerr << "Missing Args in command '" << handle << "', " << N << " required, but " << args.size() << " input\n"; return; } args.resize(N); cli_invoke(cb, args, std::make_index_sequence()); }); return *this; } template void cli_print(T const & value) { if constexpr (detail::is_container_v && !detail::is_string_v) { using ::cli::cli_print; for (auto & elem : value) { cli_print(elem); } } else if constexpr (detail::is_map_value_type_v) { std::cout << " " << value.first << ": " << value.second << "\n"; } else { std::cout << " " << value << "\n"; } } template cli & cli::register_query(std::string const & handle, std::function cb) { arguments_.emplace(handle, 0); callbacks_.emplace(handle, [=](args_t const & args) { using ::cli::cli_print; cli_print(cb()); }); return *this; } }