refactor(cli): improve option handling with defaults and protected inheritance
Update OptionUtils to include name placeholders for default values, switch cli classes to protected inheritance, and use at() for safer option retrieval.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "echo_client_cli.hpp"
|
#include "echo_client_cli.hpp"
|
||||||
|
#include <boost/program_options/value_semantic.hpp>
|
||||||
|
|
||||||
EchoClientCli::EchoClientCli()
|
EchoClientCli::EchoClientCli()
|
||||||
: CliBase("Echo Client Options")
|
: CliBase("Echo Client Options")
|
||||||
@@ -12,24 +13,22 @@ void EchoClientCli::setupOptions()
|
|||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
desc_.add_options()
|
desc_.add_options()
|
||||||
("help,h", "Show help")
|
("help,h", "Show help")
|
||||||
("host,H", withDefault(host_), "Server host (IP or DNS name)")
|
("host,H", withDefault(host_, "<HOST>"), "Server host (IP or DNS)")
|
||||||
("port,p", withDefault(port_), "Server port")
|
("port,p", withDefault(port_, "<PORT>"), "Server port")
|
||||||
("message,m", withDefault(message_), "Message to send");
|
("message,m", withDefault(message_, "<TEXT>"), "Message to send");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EchoClientCli::getHost() const
|
std::string EchoClientCli::getHost() const
|
||||||
{
|
{
|
||||||
return vm_["host"].as<std::string>();
|
return vm_.at("host").as<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EchoClientCli::getPort() const
|
int EchoClientCli::getPort() const
|
||||||
{
|
{
|
||||||
return vm_["port"].as<int>();
|
return vm_.at("port").as<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EchoClientCli::getMessage() const
|
std::string EchoClientCli::getMessage() const
|
||||||
{
|
{
|
||||||
return vm_["message"].as<std::string>();
|
return vm_.at("message").as<std::string>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "option_utils.hpp"
|
#include "option_utils.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class EchoClientCli : public CliBase, public OptionUtils
|
class EchoClientCli : public CliBase, protected OptionUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EchoClientCli();
|
EchoClientCli();
|
||||||
@@ -17,6 +17,7 @@ class EchoClientCli : public CliBase, public OptionUtils
|
|||||||
void setupOptions() override;
|
void setupOptions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// defaults (used only to show defaults in help via withDefault)
|
||||||
std::string host_;
|
std::string host_;
|
||||||
int port_;
|
int port_;
|
||||||
std::string message_;
|
std::string message_;
|
||||||
|
|||||||
@@ -4,11 +4,17 @@
|
|||||||
|
|
||||||
class OptionUtils
|
class OptionUtils
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
using OptionValue = boost::program_options::typed_value<T> *;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static OptionValue<T>
|
||||||
|
withDefault(const T &value, const char *name = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OptionUtils() = default;
|
OptionUtils() = default;
|
||||||
~OptionUtils() = default;
|
~OptionUtils() = default;
|
||||||
|
|
||||||
template <typename T> static auto withDefault(T value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "option_utils.tpp"
|
#include "option_utils.tpp"
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "option_utils.hpp"
|
#include "option_utils.hpp"
|
||||||
|
|
||||||
template <typename T> auto OptionUtils::withDefault(T value)
|
template <typename T>
|
||||||
|
OptionUtils::OptionValue<T>
|
||||||
|
OptionUtils::withDefault(const T &value, const char *name)
|
||||||
{
|
{
|
||||||
return boost::program_options::value<T>()->default_value(value);
|
auto v = boost::program_options::value<T>()->default_value(value);
|
||||||
|
if (name) {
|
||||||
|
v->value_name(name); // Optional
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class Server
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Server() = default;
|
|
||||||
virtual void start() = 0;
|
|
||||||
virtual void stop() = 0;
|
|
||||||
};
|
|
||||||
@@ -11,18 +11,17 @@ void EchoServerCli::setupOptions()
|
|||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
desc_.add_options()
|
desc_.add_options()
|
||||||
("help,h", "Show help")
|
("help,h", "Show help")
|
||||||
("port,p", withDefault(port_), "Port to listen on")
|
("port,p", withDefault(port_, "<PORT>"), "Port to listen on")
|
||||||
("address,a", withDefault(address_), "Bind address (e.g. 0.0.0.0 or 127.0.0.1)");
|
("address,a", withDefault(address_, "<ADDRESS>"), "Bind address (e.g. 0.0.0.0)");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
int EchoServerCli::getPort() const
|
int EchoServerCli::getPort() const
|
||||||
{
|
{
|
||||||
return vm_["port"].as<int>();
|
return vm_.at("port").as<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EchoServerCli::getAddress() const
|
std::string EchoServerCli::getAddress() const
|
||||||
{
|
{
|
||||||
return vm_["address"].as<std::string>();
|
return vm_.at("address").as<std::string>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "option_utils.hpp"
|
#include "option_utils.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class EchoServerCli : public CliBase, public OptionUtils
|
class EchoServerCli : public CliBase, protected OptionUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EchoServerCli();
|
EchoServerCli();
|
||||||
|
|||||||
Reference in New Issue
Block a user