From eff1d672b93cdb792dd53217d4a99758b5c2032e Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Wed, 5 Sep 2012 20:19:21 +0200 Subject: keys: implement support for a few macro utilities --- src/actions.h | 5 ++-- src/keys.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++------ src/keys.h | 1 + src/macro_utilities.h | 47 +++++++++++++++++---------------- 4 files changed, 93 insertions(+), 32 deletions(-) (limited to 'src') 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 #include +#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 +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 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 #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 #include "actions.h" struct PushCharacters : public Action { - template PushCharacters(Window **w, Iterator first, Iterator last) : Action(aMacroUtility, "") - { - construct(w, first, last); - } + PushCharacters(NC::Window **w, std::vector &&queue) + : Action(aMacroUtility, ""), m_window(w), m_queue(queue) { } - PushCharacters(Window **w, const std::initializer_list &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 m_queue; +}; + +struct RequireRunnable : public Action +{ + RequireRunnable(Action *action) + : Action(aMacroUtility, ""), m_action(action) { assert(action); } - private: - template void construct(Window **w, Iterator first, Iterator last) - { - itsWindow = w; - for (; first != last; ++first) - itsQueue.push_back(*first); - } - - Window **itsWindow; - std::vector itsQueue; + virtual bool canBeRun() const { return m_action->canBeRun(); } + virtual void Run() { } + +private: + Action *m_action; }; + +#endif // _MACRO_UTILITIES -- cgit v1.2.3