Consolix
Loading...
Searching...
No Matches
CliComponent.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _CONSOLIX_CLI_COMPONENT_HPP_INCLUDED
3#define _CONSOLIX_CLI_COMPONENT_HPP_INCLUDED
4
8
9#if CONSOLIX_USE_CXXOPTS == 1
10
11#include <cxxopts.hpp>
12#include <string>
13#include <memory>
14
15namespace consolix {
16
22 class CliComponent : public IAppComponent {
23 public:
24
29 CliComponent(
30 const std::string& name,
31 const std::string& description,
32 std::function<void(CliOptions&)> creator)
33 : m_creator(std::move(creator)) {
34 register_service<CliOptions>([&name, &description]() {
35 return std::make_shared<CliOptions>(name, description);
36 });
37 }
38
45 CliComponent(
46 const std::string& name,
47 const std::string& description,
48 std::function<void(CliOptions&)> creator,
49 int argc,
50 const char* argv[])
51 : m_creator(std::move(creator)) {
52 register_service<CliOptions>([&name, &description](){
53 return std::make_shared<CliOptions>(name, description);
54 });
55 m_argc = argc;
56 for (int i = 0; i < argc; ++i) {
57 m_argv_c.push_back(argv[i]);
58 }
59 }
60
65 template <typename T>
66 void add_option(const std::string& key, const std::string& description) {
67 get_service<CliOptions>().add_options()(key, description, cxxopts::value<T>());
68 }
69
75 template <typename T>
76 void add_option(const std::string& key, const std::string& description, T default_value) {
77 get_service<CliOptions>().add_options()(key, description, cxxopts::value<T>()->default_value(std::to_string(default_value)));
78 }
79
85 template <typename T>
86 void add_option_implicit(const std::string& key, const std::string& description, T implicit_value) {
87 get_service<CliOptions>().add_options()(key, description, cxxopts::value<T>()->implicit_value(std::to_string(implicit_value)));
88 }
89
93 void parse(int argc, const char* argv[]) {
94 try {
95 auto result = get_service<CliOptions>().parse(argc, argv);
96 register_service<CliArguments>([&result](){
97 return std::make_shared<CliArguments>(result);
98 });
99 } catch (const std::exception& e) {
100 CONSOLIX_STREAM() << "Error parsing command-line arguments: " << e.what() << std::endl;
101# if CONSOLIX_USE_LOGIT == 1
102 LOGIT_PRINT_ERROR("Error parsing command-line arguments: ", e.what());
103# endif
104 throw;
105 }
106 }
107
113 template <typename T>
114 T get(const std::string& key) const {
115 if (!get_service<CliArguments>().count(key)) {
116# if CONSOLIX_USE_LOGIT == 1
117 LOGIT_PRINT_ERROR("Option not found: ", key);
118# endif
119 throw std::runtime_error("Option not found: " + key);
120 }
121 return get_service<CliArguments>()[key].as<T>();
122 }
123
124 protected:
125
128 bool initialize() override {
129 try {
130 auto &options = get_service<CliOptions>();
131 if (!m_creator) {
132 throw std::runtime_error("CLI options creator function is null. Ensure you provide a valid function to initialize CLI options.");
133 }
134 m_creator(options);
135# if defined(_WIN32) || defined(_WIN64)
136 parse_windows();
137# else
138 if (m_argc) {
139 parse(m_argc, m_argv_c.data());
140 }
141# endif
142 } catch (const std::exception& e) {
143# if CONSOLIX_USE_LOGIT == 1
144 LOGIT_PRINT_ERROR("CLI component initialization failed: ", e.what());
145 throw;
146# else
147 CONSOLIX_STREAM() << "Error initializing CLI component: " << e.what() << std::endl;
148 throw;
149# endif
150 }
151 m_is_init = true;
152 return true;
153 }
154
157 bool is_initialized() const override {
158 return m_is_init;
159 }
160
162 void process() override {}
163
164 private:
165 int m_argc = 0;
166 std::vector<const char*> m_argv_c;
167 std::function<void(CliOptions&)> m_creator;
168 std::atomic<bool> m_is_init{false};
169
170# if defined(_WIN32) || defined(_WIN64)
172 void parse_windows() {
173 int argc = 0;
174 LPWSTR* argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
175
176 std::vector<std::string> args;
177 for (int i = 0; i < argc; ++i) {
178 args.push_back(utf16_to_utf8(argv_w[i]));
179 }
180
181 // Convert to standard `char*` for cxxopts
182 std::vector<const char*> argv_c;
183 for (const auto& arg : args) {
184 argv_c.push_back(arg.c_str());
185 }
186
187 parse(argc, argv_c.data());
188 }
189# endif
190
191 }; // CliComponent
192
193}; // namespace consolix
194
195#endif // #if CONSOLIX_USE_CXXOPTS == 1
196
197#endif // _CONSOLIX_CLI_COMPONENT_HPP_INCLUDED
#define CONSOLIX_STREAM()
Fallback for general logging.
< Utility modules and helpers.