bindings: allow for binding multiple chains to one key
This commit is contained in:
15
doc/bindings
15
doc/bindings
@@ -22,17 +22,12 @@
|
|||||||
## action2
|
## 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
|
## executed, each action in chain is run until the end of
|
||||||
## chain is reached or one of actions failed to execute
|
## chain is reached or one of its actions fails to execute
|
||||||
## due to its requirements not being met. Note that
|
## due to its requirements not being met. If multiple actions
|
||||||
## execution of chain of actions ALWAYS succeeds, no
|
## and/or chains are bound to the same key, they will be
|
||||||
## matter if one of actions from the chain failed (even
|
## consecutively run until one of them gets fully executed.
|
||||||
## 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.
|
|
||||||
##
|
##
|
||||||
## 3) When ncmpcpp starts, bindings configuration file is
|
## 3) When ncmpcpp starts, bindings configuration file is
|
||||||
## parsed and then ncmpcpp provides "missing pieces"
|
## parsed and then ncmpcpp provides "missing pieces"
|
||||||
|
|||||||
@@ -826,7 +826,8 @@ void ExecuteCommand::run()
|
|||||||
if (cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
Statusbar::msg(1, "Executing %s...", cmd_name.c_str());
|
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
|
else
|
||||||
Statusbar::msg("No command named \"%s\"", cmd_name.c_str());
|
Statusbar::msg("No command named \"%s\"", cmd_name.c_str());
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ bool BindingsConfiguration::read(const std::string &file)
|
|||||||
{
|
{
|
||||||
if (!actions.empty())
|
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();
|
actions.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#ifndef NCMPCPP_BINDINGS_H
|
#ifndef NCMPCPP_BINDINGS_H
|
||||||
#define NCMPCPP_BINDINGS_H
|
#define NCMPCPP_BINDINGS_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
@@ -74,57 +76,43 @@ struct Binding
|
|||||||
{
|
{
|
||||||
typedef std::vector<Actions::BaseAction *> ActionChain;
|
typedef std::vector<Actions::BaseAction *> ActionChain;
|
||||||
|
|
||||||
Binding(Actions::Type at) : m_is_single(true), m_action(&Actions::get(at)) { }
|
template <typename ArgT>
|
||||||
Binding(const ActionChain &actions) {
|
Binding(ArgT &&actions)
|
||||||
assert(actions.size() > 0);
|
: m_actions(std::forward<ArgT>(actions)) {
|
||||||
if (actions.size() == 1) {
|
assert(!m_actions.empty());
|
||||||
m_is_single = true;
|
|
||||||
m_action = actions[0];
|
|
||||||
} else {
|
|
||||||
m_is_single = false;
|
|
||||||
m_chain = new ActionChain(actions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Binding(Actions::Type at)
|
||||||
|
: Binding(ActionChain({&Actions::get(at)})) { }
|
||||||
|
|
||||||
bool execute() const {
|
bool execute() const {
|
||||||
bool result = false;
|
return std::all_of(m_actions.begin(), m_actions.end(),
|
||||||
if (m_is_single) {
|
boost::bind(&Actions::BaseAction::execute, _1)
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSingle() const {
|
bool isSingle() const {
|
||||||
return m_is_single;
|
return m_actions.size() == 1;
|
||||||
}
|
|
||||||
ActionChain *chain() const {
|
|
||||||
assert(!m_is_single);
|
|
||||||
return m_chain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions::BaseAction *action() const {
|
Actions::BaseAction *action() const {
|
||||||
assert(m_is_single);
|
assert(isSingle());
|
||||||
return m_action;
|
return m_actions[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActionChain &actions() const {
|
||||||
|
return m_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_is_single;
|
ActionChain m_actions;
|
||||||
union {
|
|
||||||
Actions::BaseAction *m_action;
|
|
||||||
ActionChain *m_chain;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents executable command
|
/// Represents executable command
|
||||||
struct Command
|
struct Command
|
||||||
{
|
{
|
||||||
Command(const Binding &binding_, bool immediate_)
|
template <typename ArgT>
|
||||||
: m_binding(binding_), m_immediate(immediate_) { }
|
Command(ArgT &&binding_, bool immediate_)
|
||||||
|
: m_binding(std::forward<ArgT>(binding_)), m_immediate(immediate_) { }
|
||||||
|
|
||||||
const Binding &binding() const { return m_binding; }
|
const Binding &binding() const { return m_binding; }
|
||||||
bool immediate() const { return m_immediate; }
|
bool immediate() const { return m_immediate; }
|
||||||
@@ -182,8 +170,9 @@ private:
|
|||||||
return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
|
return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void bind(Key k, const T &t) {
|
template <typename ArgT>
|
||||||
m_bindings[k].push_back(Binding(t));
|
void bind(Key k, ArgT &&t) {
|
||||||
|
m_bindings[k].push_back(std::forward<ArgT>(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingsMap m_bindings;
|
BindingsMap m_bindings;
|
||||||
|
|||||||
@@ -256,9 +256,7 @@ int main(int argc, char **argv)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto k = Bindings.get(input);
|
auto k = Bindings.get(input);
|
||||||
for (; k.first != k.second; ++k.first)
|
std::any_of(k.first, k.second, boost::bind(&Binding::execute, _1));
|
||||||
if (k.first->execute())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (ConversionError &e)
|
catch (ConversionError &e)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user