Antkeeper  0.0.1
cli.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_DEBUG_CLI_HPP
21 #define ANTKEEPER_DEBUG_CLI_HPP
22 
23 #include <functional>
24 #include <sstream>
25 #include <string>
26 #include <tuple>
27 #include <type_traits>
28 #include <unordered_map>
29 
30 namespace debug {
31 
35 class cli
36 {
37 public:
44  std::string interpret(const std::string& line) const;
45 
56  template <class T, class... Args>
57  void register_command(const std::string& name, const std::function<T(Args...)>& function);
58  template <class T, class... Args>
59  void register_command(const std::string& name, T (*function)(Args...));
61 
67  void unregister_command(const std::string& name);
68 
69 private:
71  typedef std::function<std::string(const std::string&)> command_type;
72 
80  template <class T>
81  [[nodiscard]] static T parse(std::istringstream& stream);
82 
93  template <class T, class... Args>
94  [[nodiscard]] static command_type wrap(std::function<T(Args...)> function);
95 
96  std::unordered_map<std::string, command_type> commands;
97 };
98 
99 template <class T, class... Args>
100 void cli::register_command(const std::string& name, const std::function<T(Args...)>& function)
101 {
102  commands[name] = wrap(function);
103 }
104 
105 template <class T, class... Args>
106 void cli::register_command(const std::string& name, T (*function)(Args...))
107 {
108  commands[name] = wrap(std::function(function));
109 }
110 
111 template <class T>
112 T cli::parse(std::istringstream& stream)
113 {
114  T value;
115  stream >> value;
116  return value;
117 }
118 
119 template <class T, class... Args>
120 typename cli::command_type cli::wrap(std::function<T(Args...)> function)
121 {
122  return std::bind
123  (
124  [function](const std::string& line) -> std::string
125  {
126  //constexpr std::size_t argument_count = sizeof...(Args);
127 
128  // Parse string into tuple of arguments
129  std::istringstream istream(line);
130  std::tuple<Args...> arguments{parse<Args>(istream)...};
131 
132  if constexpr(std::is_void_v<T>)
133  {
134  // Invoke function with parsed arguments
135  std::apply(function, arguments);
136 
137  // Return empty string
138  return std::string();
139  }
140  else
141  {
142  // Invoke function with parsed arguments and save the result
143  T result = std::apply(function, arguments);
144 
145  // Return invocation result as a string
146  std::ostringstream ostream;
147  ostream << result;
148  return ostream.str();
149  }
150  },
151  std::placeholders::_1
152  );
153 }
154 
155 } // namespace debug
156 
157 #endif // ANTKEEPER_DEBUG_CLI_HPP
Minimal command-line interpreter.
Definition: cli.hpp:36
std::string interpret(const std::string &line) const
Interprets a command line as a function invocation.
Definition: cli.cpp:24
void unregister_command(const std::string &name)
Unregisters a command from the CLI.
Definition: cli.cpp:38
void register_command(const std::string &name, const std::function< T(Args...)> &function)
Registers a command with the CLI.
Definition: cli.hpp:100
Debugging functions and classes.
Definition: cli.cpp:22