| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- //
- // 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 <string_utils/cast.h>
- #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:
- explicit cli(std::string const & prompt, std::istream &in = std::cin);
- explicit 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;
-
- private:
- bool active() const;
-
- cli(cli const &) = delete;
- cli(cli &&) = delete;
- cli &operator=(cli const &) = delete;
- cli &operator=(cli &&) = delete;
- };
- template <typename... Args, size_t... Is>
- void cli_invoke(std::function<void(Args...)> cb, cli::args_t const & args,
- std::index_sequence<Is...>) {
- std::tuple<std::decay_t<Args>...> object;
- if (string_utils::cast(object, args)) {
- cb(std::move(std::get<Is>(object))...);
- }
- }
- template <typename... Args>
- cli & cli::register_callback(std::string const & handle,
- std::function<void(Args...)> 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<N>());
- });
- 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 if constexpr (detail::is_map_value_type_v<T>) {
- std::cout << " " << value.first << ": " << value.second << "\n";
- } 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;
- }
- }
|