Arkanjo 0.2
A tool for find code duplicated functions in codebases
Loading...
Searching...
No Matches
command_base.hpp
Go to the documentation of this file.
1#pragma once
2
7#include <algorithm>
8
9#define COMMAND_DESCRIPTION(str) \
10 std::string_view description() const override { \
11 static constexpr char description_str[] = str; \
12 return description_str; \
13 }
14
15template <typename, typename = std::void_t<>>
16struct has_options : std::false_type {};
17
18template <typename T>
19struct has_options<T, std::void_t<decltype(T::options_)>> : std::true_type {};
20
21template <typename Derived>
22class CommandBase : public ICommand {
23
24 public:
25 virtual void print_help(const std::string command_name, const OptionsCollector* collector) const {
26 constexpr int OPTION_WIDTH = 26;
27
28 std::string s(description());
29 std::cout << wrapped(s, 0) << "\n";
30
31 const CliOption* command_options = collector == nullptr ? options() : collector->get_options().data();
32 if (command_options) {
33 std::vector<const CliOption*> vector_arguments, vector_options;
34 for (const CliOption* opt = command_options; opt->long_name != nullptr; ++opt) {
35 if (opt->has_arg == PositionalArgument) {
36 vector_arguments.push_back(opt);
37 } else {
38 vector_options.push_back(opt);
39 }
40 }
41
42 std::cout << BOLD(UNDERLINE("Usage:")) << " "
43 << Config::config().program_name << " "
44 << command_name
45 << (!vector_options.empty() ? " [OPTIONS]" : "")
46 << (!vector_arguments.empty() ? " [--] [ARGUMENTS]" : "")
47 << "..." << "\n\n";
48
49 if (!vector_arguments.empty()) {
50 std::cout << BOLD(UNDERLINE("Arguments:")) << "\n";
51
52 for (const auto& item : vector_arguments) {
53 std::string opts_str = " ";
54 opts_str += "<";
55 opts_str += Utils::to_uppercase(item->long_name);
56 opts_str += ">";
57 std::cout << std::left << std::setw(OPTION_WIDTH) << opts_str;
58 if (item->description != nullptr) {
59 std::cout << wrapped(item->description, OPTION_WIDTH);
60 }
61 std::cout << "\n";
62 }
63 }
64
65 if (!vector_options.empty()) {
66 std::sort(vector_options.begin(), vector_options.end(), [](const CliOption* a, const CliOption* b) {
67 return std::string_view(a->long_name) < std::string_view(b->long_name);
68 });
69
70 std::cout << BOLD(UNDERLINE("Options:")) << "\n";
71
72 for (const auto& item : vector_options) {
73 std::string opts_str = " ";
74 if (item->short_name != 0)
75 opts_str += "-" + std::string(1, static_cast<char>(item->short_name));
76 if (!opts_str.empty() && item->long_name && item->short_name)
77 opts_str += ", ";
78 if (!item->short_name)
79 opts_str += " ";
80 if (item->long_name)
81 opts_str += "--" + std::string(item->long_name);
82 opts_str = BOLD(opts_str);
83
84 if (item->has_arg == RequiredArgument || item->has_arg == OptionalArgument) {
85 opts_str += " <" + Utils::to_uppercase(item->long_name) + "> ";
86 }
87 std::cout << std::left << std::setw(OPTION_WIDTH + 8) << opts_str;
88 if (item->description != nullptr) {
89 std::cout << wrapped(item->description, OPTION_WIDTH);
90 }
91 std::cout << "\n";
92 }
93 }
94 }
95 }
96
97 const CliOption* options() const final {
98 if constexpr (has_options<Derived>::value) {
99 return Derived::options_;
100 } else {
101 return nullptr;
102 }
103 }
104
105 bool do_run(const std::string command_name, const ParsedOptions& options, const OptionsCollector* collector = nullptr) override {
106 if (options.args.count("help") > 0) {
107 print_help(command_name, collector);
108 return true;
109 }
110 return run(options);
111 }
112};
virtual void print_help(const std::string command_name, const OptionsCollector *collector) const
bool do_run(const std::string command_name, const ParsedOptions &options, const OptionsCollector *collector=nullptr) override
const CliOption * options() const final
static Config & config()
Gets the singleton configuration instance.
Definition config.cpp:37
std::string program_name
Name of the program.
Definition config.hpp:41
Basic interface for all CLI commands.
Definition command.hpp:11
virtual bool run(const ParsedOptions &options)=0
Executes the main logic of the command.
virtual std::string_view description() const =0
const std::vector< CliOption > & get_options() const
Configuration management interface.
std::string to_uppercase(const std::string input)
Definition utils.cpp:126
@ RequiredArgument
@ OptionalArgument
@ PositionalArgument
const char * long_name
Defines utility functions used across all files.
Wrapped wrapped(const std::string &text, size_t spaces=1, bool use_first_line=true)
Definition utils.cpp:90