From a287fb5e8ca66592ee20b38811729d39bc7ed7d9 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Sun, 31 May 2020 00:09:44 +0200
Subject: [PATCH] fix: Use module name in action string
Action strings now have the form '#MODULE#ACTION'
For example to trigger the action 'toggle' in the 'module/date' module
one would now use '%{A1:#date#toggle:}'
With this action strings can now be uniquely assigned to one module.
Fixes #1172
---
include/components/controller.hpp | 7 ++-
include/modules/meta/base.hpp | 6 ++
include/modules/meta/base.inl | 6 ++
include/modules/meta/input_handler.hpp | 5 ++
src/components/controller.cpp | 77 ++++++++++++++++++--------
5 files changed, 76 insertions(+), 25 deletions(-)
diff --git a/include/components/controller.hpp b/include/components/controller.hpp
index 6b07f527..2067a4ec 100644
--- a/include/components/controller.hpp
+++ b/include/components/controller.hpp
@@ -117,9 +117,12 @@ class controller
modulemap_t m_blocks;
/**
- * \brief Module input handlers
+ * \brief Input handlers modules
+ *
+ * Maps the name of the input handler (module name) to the corresponding input
+ * handler
*/
- vector m_inputhandlers;
+ std::map> m_inputhandlers;
/**
* \brief Maximum number of subsequent events to swallow
diff --git a/include/modules/meta/base.hpp b/include/modules/meta/base.hpp
index aed26f6f..558f5b90 100644
--- a/include/modules/meta/base.hpp
+++ b/include/modules/meta/base.hpp
@@ -101,6 +101,10 @@ namespace modules {
public:
virtual ~module_interface() {}
+ /**
+ * Module name w/o 'module/' prefix
+ */
+ virtual string name_raw() const = 0;
virtual string name() const = 0;
virtual bool running() const = 0;
@@ -119,6 +123,7 @@ namespace modules {
module(const bar_settings bar, string name);
~module() noexcept;
+ string name_raw() const;
string name() const;
bool running() const;
void stop();
@@ -148,6 +153,7 @@ namespace modules {
std::condition_variable m_sleephandler;
string m_name;
+ string m_name_raw;
unique_ptr m_builder;
unique_ptr m_formatter;
vector m_threads;
diff --git a/include/modules/meta/base.inl b/include/modules/meta/base.inl
index 73255347..f201c9cf 100644
--- a/include/modules/meta/base.inl
+++ b/include/modules/meta/base.inl
@@ -17,6 +17,7 @@ namespace modules {
, m_log(logger::make())
, m_conf(config::make())
, m_name("module/" + name)
+ , m_name_raw(name)
, m_builder(make_unique(bar))
, m_formatter(make_unique(m_conf, m_name))
, m_handle_events(m_conf.get(m_name, "handle-events", true)) {}
@@ -40,6 +41,11 @@ namespace modules {
return m_name;
}
+ template
+ string module::name_raw() const {
+ return m_name_raw;
+ }
+
template
bool module::running() const {
return static_cast(m_enabled);
diff --git a/include/modules/meta/input_handler.hpp b/include/modules/meta/input_handler.hpp
index 3ce847f3..b3362cc3 100644
--- a/include/modules/meta/input_handler.hpp
+++ b/include/modules/meta/input_handler.hpp
@@ -8,6 +8,11 @@ namespace modules {
class input_handler {
public:
virtual ~input_handler() {}
+ /**
+ * Handle command
+ *
+ * \returns true if the command is supported and false otherwise
+ */
virtual bool input(string&& cmd) = 0;
};
}
diff --git a/src/components/controller.cpp b/src/components/controller.cpp
index 8560d00c..2929a4f3 100644
--- a/src/components/controller.cpp
+++ b/src/components/controller.cpp
@@ -143,11 +143,12 @@ bool controller::run(bool writeback, string snapshot_dst) {
size_t started_modules{0};
for (const auto& module : m_modules) {
- auto inp_handler = dynamic_cast(&*module);
+ auto inp_handler = std::dynamic_pointer_cast(module);
auto evt_handler = dynamic_cast(&*module);
- if (inp_handler != nullptr) {
- m_inputhandlers.emplace_back(inp_handler);
+ if (inp_handler) {
+ m_log.trace("Registering module %s as input handler", module->name_raw());
+ m_inputhandlers.emplace(module->name_raw(), inp_handler);
}
if (evt_handler != nullptr) {
@@ -390,32 +391,62 @@ void controller::process_eventqueue() {
* Process stored input data
*/
void controller::process_inputdata() {
- if (!m_inputdata.empty()) {
- string cmd = m_inputdata;
- m_inputdata.clear();
+ if (m_inputdata.empty()) {
+ return;
+ }
- for (auto&& handler : m_inputhandlers) {
- if (handler->input(string{cmd})) {
- return;
- }
+ const string cmd = m_inputdata;
+ m_inputdata.clear();
+
+ /*
+ * Module inputs have the following form (w/o the quotes): "#NAME#INPUT"
+ * where 'NAME' is the name of the module (for which '#' is a forbidden
+ * character) and 'INPUT' is the input that is sent to the module
+ */
+ if (cmd.front() == '#') {
+ // Find the second delimiter '#'
+ auto end_pos = cmd.find('#', 1);
+
+ if (end_pos == string::npos) {
+ m_log.err("Invalid action string (input: %s)", cmd);
+ return;
}
- try {
- m_log.info("Uncaught input event, forwarding to shell... (input: %s)", cmd);
+ auto handler_name = cmd.substr(1, end_pos - 1);
+ auto action = cmd.substr(end_pos + 1);
- if (m_command) {
- m_log.warn("Terminating previous shell command");
- m_command->terminate();
- }
+ m_log.info("Forwarding data to input handler (name: %s, action: %s) ", handler_name, action);
- m_log.info("Executing shell command: %s", cmd);
- m_command = command_util::make_command(move(cmd));
- m_command->exec();
- m_command.reset();
- process_update(true);
- } catch (const application_error& err) {
- m_log.err("controller: Error while forwarding input to shell -> %s", err.what());
+ auto handler = m_inputhandlers.find(handler_name);
+
+ if (handler == m_inputhandlers.end()) {
+ m_log.err("The input handler with name '%s' doesn't exist (input: %s)", handler_name, cmd);
+ return;
}
+
+ if(!handler->second->input(string{action})) {
+ m_log.warn("The '%s' module does not support the '%s' action.", handler_name, action);
+ }
+
+ return;
+ }
+
+ try {
+ // Run input as command if it's not an input for a module
+ m_log.info("Forwarding command to shell... (input: %s)", cmd);
+
+ if (m_command) {
+ m_log.warn("Terminating previous shell command");
+ m_command->terminate();
+ }
+
+ m_log.info("Executing shell command: %s", cmd);
+ m_command = command_util::make_command(move(cmd));
+ m_command->exec();
+ m_command.reset();
+ process_update(true);
+ } catch (const application_error& err) {
+ m_log.err("controller: Error while forwarding input to shell -> %s", err.what());
}
}