changeset 802:f26bb089232d

irccdctl: fix alias invocations
author David Demelier <markand@malikania.fr>
date Mon, 12 Nov 2018 21:42:23 +0100
parents fe27ed0c1eae
children 14f9e3b03779
files irccdctl/cli.cpp irccdctl/main.cpp libirccd-ctl/irccd/ctl/controller.cpp libirccd-ctl/irccd/ctl/controller.hpp libirccd-test/irccd/test/command_fixture.cpp
diffstat 5 files changed, 56 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/irccdctl/cli.cpp	Mon Nov 12 21:47:00 2018 +0100
+++ b/irccdctl/cli.cpp	Mon Nov 12 21:42:23 2018 +0100
@@ -187,7 +187,7 @@
 
 void get_event(ctl::controller& ctl, std::string fmt)
 {
-	ctl.read([&ctl, fmt] (auto code, auto message) {
+	ctl.recv([&ctl, fmt] (auto code, auto message) {
 		if (code)
 			throw std::system_error(code);
 
@@ -268,25 +268,22 @@
 
 void cli::recv_response(ctl::controller& ctl, nlohmann::json req, handler_t handler)
 {
-	ctl.read([&ctl, req, handler, this] (auto code, auto message) {
+	ctl.recv([&ctl, req, handler, this] (auto code, auto message) {
 		if (code)
 			throw std::system_error(code);
 
 		const auto c = deserializer(message).get<std::string>("command");
 
-		if (!c) {
+		if (!c)
 			recv_response(ctl, std::move(req), std::move(handler));
-			return;
-		}
-
-		if (handler)
+		else if (handler)
 			handler(std::move(message));
 	});
 }
 
 void cli::request(ctl::controller& ctl, nlohmann::json req, handler_t handler)
 {
-	ctl.write(req, [&ctl, req, handler, this] (auto code) {
+	ctl.send(req, [&ctl, req, handler, this] (auto code) {
 		if (code)
 			throw std::system_error(code);
 
--- a/irccdctl/main.cpp	Mon Nov 12 21:47:00 2018 +0100
+++ b/irccdctl/main.cpp	Mon Nov 12 21:42:23 2018 +0100
@@ -59,6 +59,9 @@
 std::unordered_map<std::string, alias> aliases;
 std::unordered_map<std::string, std::unique_ptr<cli>> commands;
 
+// Vector of commands to execute.
+std::vector<std::function<void ()>> requests;
+
 /*
  * Configuration file parsing.
  * -------------------------------------------------------------------
@@ -389,9 +392,9 @@
 	return result;
 }
 
-void exec(std::vector<std::string>);
+void enqueue(std::vector<std::string>);
 
-void exec(const alias& alias, std::vector<std::string> args_copy)
+void enqueue(const alias& alias, std::vector<std::string> args_copy)
 {
 	for (const auto& cmd : alias) {
 		std::vector<std::string> args(args_copy);
@@ -424,11 +427,11 @@
 		std::copy(args.begin(), args.end(), std::back_inserter(cmd_args));
 
 		// 4. Finally try to execute.
-		exec(cmd_args);
+		enqueue(cmd_args);
 	}
 }
 
-void exec(std::vector<std::string> args)
+void enqueue(std::vector<std::string> args)
 {
 	assert(args.size() > 0);
 
@@ -438,16 +441,19 @@
 	// Remove name.
 	args.erase(args.begin());
 
-	if (alias != aliases.end())
-		exec(alias->second, args);
-	else {
-		auto cmd = commands.find(name);
+	if (alias != aliases.end()) {
+		enqueue(alias->second, args);
+		return;
+	}
+
+	const auto cmd = commands.find(name);
 
-		if (cmd != commands.end())
+	if (cmd != commands.end())
+		requests.push_back([args, cmd] () {
 			cmd->second->exec(*ctl, args);
-		else
-			throw std::invalid_argument("no alias or command named " + name);
-	}
+		});
+	else
+		throw std::invalid_argument("no alias or command named " + name);
 }
 
 void init(int &argc, char **&argv)
@@ -497,8 +503,13 @@
 	for (int i = 0; i < argc; ++i)
 		args.push_back(argv[i]);
 
-	exec(args);
-	service.run();
+	enqueue(args);
+
+	for (const auto& req : requests) {
+		req();
+		service.run();
+		service.reset();
+	}
 }
 
 } // !namespace
@@ -510,7 +521,7 @@
 	irccd::ctl::init(argc, argv);
 
 	// 1. Read command line arguments.
-	auto result = irccd::ctl::parse(argc, argv);
+	const auto result = irccd::ctl::parse(argc, argv);
 
 	/*
 	 * 2. Open optional config by command line or by searching it
--- a/libirccd-ctl/irccd/ctl/controller.cpp	Mon Nov 12 21:47:00 2018 +0100
+++ b/libirccd-ctl/irccd/ctl/controller.cpp	Mon Nov 12 21:42:23 2018 +0100
@@ -39,13 +39,13 @@
 		{ "password",   password_       }
 	});
 
-	write(cmd, [handler, info, this] (auto code) {
+	send(cmd, [handler, info, this] (auto code) {
 		if (code) {
 			handler(std::move(code), nullptr);
 			return;
 		}
 
-		read([handler, info] (auto code, auto) {
+		recv([handler, info] (auto code, auto) {
 			handler(std::move(code), std::move(info));
 		});
 	});
@@ -53,7 +53,7 @@
 
 void controller::verify(connect_handler handler)
 {
-	read([handler, this] (auto code, auto message) {
+	recv([handler, this] (auto code, auto message) {
 		if (code) {
 			handler(std::move(code), std::move(message));
 			return;
@@ -106,10 +106,10 @@
 	});
 }
 
-void controller::read(stream::recv_handler handler)
+void controller::recv(stream::recv_handler handler)
 {
+	assert(stream_);
 	assert(handler);
-	assert(stream_);
 
 	auto stream = stream_;
 
@@ -139,10 +139,11 @@
 	});
 }
 
-void controller::write(nlohmann::json message, stream::send_handler handler)
+void controller::send(nlohmann::json message, stream::send_handler handler)
 {
+	assert(stream_);
 	assert(message.is_object());
-	assert(stream_);
+	assert(handler);
 
 	auto stream = stream_;
 
--- a/libirccd-ctl/irccd/ctl/controller.hpp	Mon Nov 12 21:47:00 2018 +0100
+++ b/libirccd-ctl/irccd/ctl/controller.hpp	Mon Nov 12 21:42:23 2018 +0100
@@ -48,9 +48,9 @@
 	/**
 	 * Connection completion handler.
 	 *
-	 * This callback is called when connection has been completed or failed. In
-	 * both case, the error code is set and the JSON object may contain the
-	 * irccd program information.
+	 * This callback is called when connection has been completed or failed.
+	 * In both case, the error code is set and the JSON object may contain
+	 * the * irccd program information.
 	 */
 	using connect_handler = std::function<void (std::error_code, nlohmann::json)>;
 
@@ -92,29 +92,31 @@
 	/**
 	 * Attempt to connect to the irccd daemon.
 	 *
+	 * \pre another connect operation must not be running
 	 * \pre handler != nullptr
 	 * \param handler the handler
 	 */
 	void connect(connect_handler handler);
 
 	/**
-	 * Queue a receive operation, if receive operations are already running,
-	 * it is queued and ran once ready.
+	 * Request a message.
 	 *
+	 * \pre another recv operation must not be running
 	 * \pre handler != nullptr
 	 * \param handler the recv handler
 	 */
-	void read(stream::recv_handler handler);
+	void recv(stream::recv_handler handler);
 
 	/**
-	 * Queue a send operation, if receive operations are already running, it
-	 * is queued and ran once ready.
+	 * Send a message.
 	 *
+	 * \pre another send operation must not be running
 	 * \pre message.is_object()
+	 * \pre handler != nullptr
 	 * \param message the JSON message
 	 * \param handler the optional completion handler
 	 */
-	void write(nlohmann::json message, stream::send_handler handler = nullptr);
+	void send(nlohmann::json message, stream::send_handler handler);
 };
 
 } // !irccd::ctl
--- a/libirccd-test/irccd/test/command_fixture.cpp	Mon Nov 12 21:47:00 2018 +0100
+++ b/libirccd-test/irccd/test/command_fixture.cpp	Mon Nov 12 21:42:23 2018 +0100
@@ -42,10 +42,13 @@
 {
 	result r;
 
-	ctl_->write(std::move(json));
-	ctl_->read([&] (auto result, auto message) {
+	ctl_->send(std::move(json), [] (auto code) {
+		if (code)
+			throw std::system_error(std::move(code));
+	});
+	ctl_->recv([&] (auto code, auto message) {
 		r.first = message;
-		r.second = result;
+		r.second = code;
 	});
 	wait_for([&] {
 		return r.second || r.first.is_object();