1 /***************************************************************************
2 * Copyright (C) 2008-2014 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #ifndef NCMPCPP_BINDINGS_H
22 #define NCMPCPP_BINDINGS_H
25 #include <boost/bind.hpp>
27 #include <unordered_map>
29 #include "macro_utilities.h"
31 /// Key for binding actions to it. Supports non-ascii characters.
34 enum Type
{ Standard
, NCurses
};
36 Key(wchar_t ch
, Type ct
) : m_char(ch
), m_type(ct
) { }
38 wchar_t getChar() const {
41 Type
getType() const {
45 # define KEYS_DEFINE_OPERATOR(CMP) \
46 bool operator CMP (const Key &k) const { \
47 if (m_char CMP k.m_char) \
49 if (m_char != k.m_char) \
51 return m_type CMP k.m_type; \
53 KEYS_DEFINE_OPERATOR(<);
54 KEYS_DEFINE_OPERATOR(<=);
55 KEYS_DEFINE_OPERATOR(>);
56 KEYS_DEFINE_OPERATOR(>=);
57 # undef KEYS_DEFINE_OPERATOR
59 bool operator==(const Key
&k
) const {
60 return m_char
== k
.m_char
&& m_type
== k
.m_type
;
62 bool operator!=(const Key
&k
) const {
66 static Key
read(NC::Window
&w
);
74 /// Represents either single action or chain of actions bound to a certain key
77 typedef std::vector
<Actions::BaseAction
*> ActionChain
;
79 template <typename ArgT
>
80 Binding(ArgT
&&actions
)
81 : m_actions(std::forward
<ArgT
>(actions
)) {
82 assert(!m_actions
.empty());
84 Binding(Actions::Type at
)
85 : Binding(ActionChain({&Actions::get(at
)})) { }
87 bool execute() const {
88 return std::all_of(m_actions
.begin(), m_actions
.end(),
89 boost::bind(&Actions::BaseAction::execute
, _1
)
93 bool isSingle() const {
94 return m_actions
.size() == 1;
97 Actions::BaseAction
*action() const {
103 ActionChain m_actions
;
106 /// Represents executable command
109 template <typename ArgT
>
110 Command(ArgT
&&binding_
, bool immediate_
)
111 : m_binding(std::forward
<ArgT
>(binding_
)), m_immediate(immediate_
) { }
113 const Binding
&binding() const { return m_binding
; }
114 bool immediate() const { return m_immediate
; }
121 /// Keybindings configuration
122 class BindingsConfiguration
125 size_t operator()(const Key
&k
) const {
126 return (k
.getChar() << 1) | (k
.getType() == Key::Standard
);
129 typedef std::unordered_map
<std::string
, Command
> CommandsSet
;
130 typedef std::unordered_map
<Key
, std::vector
<Binding
>, KeyHash
> BindingsMap
;
133 typedef BindingsMap::value_type::second_type::iterator BindingIterator
;
134 typedef BindingsMap::value_type::second_type::const_iterator ConstBindingIterator
;
136 bool read(const std::string
&file
);
137 void generateDefaults();
139 const Command
*findCommand(const std::string
&name
) {
140 const Command
*ptr
= 0;
141 auto it
= m_commands
.find(name
);
142 if (it
!= m_commands
.end())
147 std::pair
<BindingIterator
, BindingIterator
> get(const Key
&k
) {
148 std::pair
<BindingIterator
, BindingIterator
> result
;
149 auto it
= m_bindings
.find(k
);
150 if (it
!= m_bindings
.end()) {
151 result
.first
= it
->second
.begin();
152 result
.second
= it
->second
.end();
154 auto list_end
= m_bindings
.begin()->second
.end();
155 result
.first
= list_end
;
156 result
.second
= list_end
;
161 BindingsMap::const_iterator
begin() const { return m_bindings
.begin(); }
162 BindingsMap::const_iterator
end() const { return m_bindings
.end(); }
165 bool notBound(const Key
&k
) const {
166 return k
!= Key::noOp
&& m_bindings
.find(k
) == m_bindings
.end();
169 template <typename ArgT
>
170 void bind(Key k
, ArgT
&&t
) {
171 m_bindings
[k
].push_back(std::forward
<ArgT
>(t
));
174 BindingsMap m_bindings
;
175 CommandsSet m_commands
;
178 extern BindingsConfiguration Bindings
;
180 #endif // NCMPCPP_BINDINGS_H