bindings: allow for binding multiple chains to one key
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user