bindings: allow for binding multiple chains to one key

This commit is contained in:
Andrzej Rybczak
2014-08-27 01:15:28 +02:00
parent afd5c22acf
commit a7f3992c97
5 changed files with 36 additions and 53 deletions

View File

@@ -22,17 +22,12 @@
## action2
## ...
##
## This creates chain of actions. When such chain is
## This creates a chain of actions. When such chain is
## executed, each action in chain is run until the end of
## chain is reached or one of actions failed to execute
## due to its requirements not being met. Note that
## execution of chain of actions ALWAYS succeeds, no
## matter if one of actions from the chain failed (even
## if it was the first one in order and thus nothing
## was really executed). Because of that, if you decide
## to bind both actions and chains to a single key, make
## sure that chain is defined in the end. Otherwise, all
## actions bound to the key after chain will never be run.
## chain is reached or one of its actions fails to execute
## due to its requirements not being met. If multiple actions
## and/or chains are bound to the same key, they will be
## consecutively run until one of them gets fully executed.
##
## 3) When ncmpcpp starts, bindings configuration file is
## parsed and then ncmpcpp provides "missing pieces"

View File

@@ -826,7 +826,8 @@ void ExecuteCommand::run()
if (cmd)
{
Statusbar::msg(1, "Executing %s...", cmd_name.c_str());
cmd->binding().execute();
bool res = cmd->binding().execute();
Statusbar::msg("Execution %s.", res ? "successful" : "unsuccessful");
}
else
Statusbar::msg("No command named \"%s\"", cmd_name.c_str());

View File

@@ -233,7 +233,7 @@ bool BindingsConfiguration::read(const std::string &file)
{
if (!actions.empty())
{
m_commands.insert(std::make_pair(cmd_name, Command(actions, cmd_immediate)));
m_commands.insert(std::make_pair(cmd_name, Command(std::move(actions), cmd_immediate)));
actions.clear();
return true;
}

View File

@@ -21,6 +21,8 @@
#ifndef NCMPCPP_BINDINGS_H
#define NCMPCPP_BINDINGS_H
#include <algorithm>
#include <boost/bind.hpp>
#include <cassert>
#include <unordered_map>
#include "actions.h"
@@ -74,57 +76,43 @@ struct Binding
{
typedef std::vector<Actions::BaseAction *> ActionChain;
Binding(Actions::Type at) : m_is_single(true), m_action(&Actions::get(at)) { }
Binding(const ActionChain &actions) {
assert(actions.size() > 0);
if (actions.size() == 1) {
m_is_single = true;
m_action = actions[0];
} else {
m_is_single = false;
m_chain = new ActionChain(actions);
}
template <typename ArgT>
Binding(ArgT &&actions)
: m_actions(std::forward<ArgT>(actions)) {
assert(!m_actions.empty());
}
Binding(Actions::Type at)
: Binding(ActionChain({&Actions::get(at)})) { }
bool execute() const {
bool result = false;
if (m_is_single) {
assert(m_action);
result = m_action->execute();
} else {
for (auto it = m_chain->begin(); it != m_chain->end(); ++it)
if (!(*it)->execute())
break;
result = true;
}
return result;
return std::all_of(m_actions.begin(), m_actions.end(),
boost::bind(&Actions::BaseAction::execute, _1)
);
}
bool isSingle() const {
return m_is_single;
}
ActionChain *chain() const {
assert(!m_is_single);
return m_chain;
return m_actions.size() == 1;
}
Actions::BaseAction *action() const {
assert(m_is_single);
return m_action;
assert(isSingle());
return m_actions[0];
}
const ActionChain &actions() const {
return m_actions;
}
private:
bool m_is_single;
union {
Actions::BaseAction *m_action;
ActionChain *m_chain;
};
ActionChain m_actions;
};
/// Represents executable command
struct Command
{
Command(const Binding &binding_, bool immediate_)
: m_binding(binding_), m_immediate(immediate_) { }
template <typename ArgT>
Command(ArgT &&binding_, bool immediate_)
: m_binding(std::forward<ArgT>(binding_)), m_immediate(immediate_) { }
const Binding &binding() const { return m_binding; }
bool immediate() const { return m_immediate; }
@@ -182,8 +170,9 @@ private:
return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
}
template <typename T> void bind(Key k, const T &t) {
m_bindings[k].push_back(Binding(t));
template <typename ArgT>
void bind(Key k, ArgT &&t) {
m_bindings[k].push_back(std::forward<ArgT>(t));
}
BindingsMap m_bindings;

View File

@@ -256,9 +256,7 @@ int main(int argc, char **argv)
try
{
auto k = Bindings.get(input);
for (; k.first != k.second; ++k.first)
if (k.first->execute())
break;
std::any_of(k.first, k.second, boost::bind(&Binding::execute, _1));
}
catch (ConversionError &e)
{