summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrzej Rybczak <electricityispower@gmail.com>2012-09-05 20:19:21 +0200
committerAndrzej Rybczak <electricityispower@gmail.com>2012-09-05 20:21:02 +0200
commiteff1d672b93cdb792dd53217d4a99758b5c2032e (patch)
tree46c5d92ba1b6d91ecd1ee34659001e0e403d6a0f /src
parent7c6467a9e7ce67495274c7dcf989e2c08500b843 (diff)
keys: implement support for a few macro utilities
Diffstat (limited to 'src')
-rw-r--r--src/actions.h5
-rw-r--r--src/keys.cpp72
-rw-r--r--src/keys.h1
-rw-r--r--src/macro_utilities.h47
4 files changed, 93 insertions, 32 deletions
diff --git a/src/actions.h b/src/actions.h
index d2a0cbc6..0757f118 100644
--- a/src/actions.h
+++ b/src/actions.h
@@ -59,6 +59,8 @@ struct Action
const char *Name() const { return itsName; }
ActionType Type() const { return itsType; }
+ virtual bool canBeRun() const { return true; }
+
bool Execute()
{
if (canBeRun())
@@ -78,7 +80,7 @@ struct Action
static bool AskYesNoQuestion(const std::string &question, void (*callback)());
static bool isMPDMusicDirSet();
- static Action *Get(ActionType);
+ static Action *Get(ActionType at);
static Action *Get(const std::string &name);
static bool OriginalStatusbarVisibility;
@@ -91,7 +93,6 @@ struct Action
static size_t FooterStartY;
protected:
- virtual bool canBeRun() const { return true; }
virtual void Run() = 0;
static void Seek();
diff --git a/src/keys.cpp b/src/keys.cpp
index 34caed8d..9bd2f378 100644
--- a/src/keys.cpp
+++ b/src/keys.cpp
@@ -20,8 +20,8 @@
#include <fstream>
#include <iostream>
+#include "global.h"
#include "keys.h"
-#include "utility/comparators.h"
#include "utility/string.h"
KeyConfiguration Keys;
@@ -30,7 +30,7 @@ Key Key::noOp = Key(ERR, NCurses);
namespace {//
-Key stringToKey(const std::string &s)
+Key stringToSpecialKey(const std::string &s)
{
Key result = Key::noOp;
if (!s.compare("mouse"))
@@ -73,7 +73,13 @@ Key stringToKey(const std::string &s)
result = Key(KEY_BACKSPACE, Key::NCurses);
else if (!s.compare("backspace_2"))
result = Key(KEY_BACKSPACE_2, Key::Standard);
- else
+ return result;
+}
+
+Key stringToKey(const std::string &s)
+{
+ Key result = stringToSpecialKey(s);
+ if (result == Key::noOp)
{
std::wstring ws = ToWString(s);
if (ws.length() == 1)
@@ -82,6 +88,56 @@ Key stringToKey(const std::string &s)
return result;
}
+template <typename F>
+Action *parseActionLine(const std::string &line, F error)
+{
+ Action *result = 0;
+ size_t i = 0;
+ for (; i < line.size() && !isspace(line[i]); ++i) { }
+ if (i == line.size()) // only action name
+ result = Action::Get(line);
+ else // there is something else
+ {
+ std::string action_name = line.substr(0, i);
+ if (action_name == "push_character")
+ {
+ // push single character into input queue
+ std::string arg = getEnclosedString(line, '"', '"', 0);
+ Key k = stringToSpecialKey(arg);
+ if (k != Key::noOp)
+ result = new PushCharacters(&Global::wFooter, { k.getChar() });
+ else
+ error() << "invalid argument to function push_character: '" << arg << "'\n";
+ }
+ else if (action_name == "push_characters")
+ {
+ // push sequence of characters into input queue
+ std::string arg = getEnclosedString(line, '"', '"', 0);
+ if (!arg.empty())
+ {
+ std::vector<int> queue(arg.begin(), arg.end());
+ // if char is signed, cancel 1s from char -> int conversion
+ for (auto it = arg.begin(); it != arg.end(); ++it)
+ *it &= 0xff;
+ result = new PushCharacters(&Global::wFooter, std::move(queue));
+ }
+ else
+ error() << "push_characters requires its argument to be non-empty";
+ }
+ else if (action_name == "require_runnable")
+ {
+ // require that given action is runnable
+ std::string arg = getEnclosedString(line, '"', '"', 0);
+ Action *action = Action::Get(arg);
+ if (action)
+ result = new RequireRunnable(action);
+ else
+ error() << "invalid action passed as argument to require_runnable: '" << arg << "'\n";
+ }
+ }
+ return result;
+}
+
}
Key Key::read(NC::Window &w)
@@ -138,6 +194,7 @@ bool KeyConfiguration::read(const std::string &file)
result = false;
return std::cerr;
};
+
auto bind_key_def = [&]() -> bool {
if (!actions.empty())
{
@@ -147,7 +204,7 @@ bool KeyConfiguration::read(const std::string &file)
}
else
{
- error() << "definition of key \"" << strkey << "\" cannot be empty.\n";
+ error() << "definition of key '" << strkey << "' cannot be empty.\n";
return false;
}
};
@@ -170,19 +227,19 @@ bool KeyConfiguration::read(const std::string &file)
key = stringToKey(strkey);
if (key == Key::noOp)
{
- error() << "invalid key: \"" << strkey << "\"\n";
+ error() << "invalid key: '" << strkey << "'\n";
break;
}
}
else if (isspace(line[0])) // name of action to be bound
{
trim(line);
- Action *action = Action::Get(line);
+ Action *action = parseActionLine(line, error);
if (action)
actions.push_back(action);
else
{
- error() << "unknown action: \"" << line << "\"\n";
+ error() << "unknown action: '" << line << "'\n";
break;
}
}
@@ -191,7 +248,6 @@ bool KeyConfiguration::read(const std::string &file)
bind_key_def();
f.close();
return result;
-
}
void KeyConfiguration::generateBindings()
diff --git a/src/keys.h b/src/keys.h
index 90614383..41c3581e 100644
--- a/src/keys.h
+++ b/src/keys.h
@@ -23,6 +23,7 @@
#include <cassert>
#include "actions.h"
+#include "macro_utilities.h"
/// Key for binding actions to it. Supports non-ascii characters.
struct Key
diff --git a/src/macro_utilities.h b/src/macro_utilities.h
index 35af60e2..82fa7555 100644
--- a/src/macro_utilities.h
+++ b/src/macro_utilities.h
@@ -18,34 +18,37 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
+#ifndef _MACRO_UTILITIES
+#define _MACRO_UTILITIES
+
+#include <cassert>
#include "actions.h"
struct PushCharacters : public Action
{
- template <typename Iterator> PushCharacters(Window **w, Iterator first, Iterator last) : Action(aMacroUtility, "")
- {
- construct(w, first, last);
- }
+ PushCharacters(NC::Window **w, std::vector<int> &&queue)
+ : Action(aMacroUtility, ""), m_window(w), m_queue(queue) { }
- PushCharacters(Window **w, const std::initializer_list<int> &v) : Action(aMacroUtility, "")
- {
- construct(w, v.begin(), v.end());
+ virtual void Run() {
+ for (auto it = m_queue.begin(); it != m_queue.end(); ++it)
+ (*m_window)->pushChar(*it);
}
- virtual void Run()
- {
- for (auto it = itsQueue.begin(); it != itsQueue.end(); ++it)
- (*itsWindow)->PushChar(*it);
- }
+private:
+ NC::Window **m_window;
+ std::vector<int> m_queue;
+};
+
+struct RequireRunnable : public Action
+{
+ RequireRunnable(Action *action)
+ : Action(aMacroUtility, ""), m_action(action) { assert(action); }
- private:
- template <typename Iterator> void construct(Window **w, Iterator first, Iterator last)
- {
- itsWindow = w;
- for (; first != last; ++first)
- itsQueue.push_back(*first);
- }
-
- Window **itsWindow;
- std::vector<int> itsQueue;
+ virtual bool canBeRun() const { return m_action->canBeRun(); }
+ virtual void Run() { }
+
+private:
+ Action *m_action;
};
+
+#endif // _MACRO_UTILITIES