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