keys: implement support for a few macro utilities

This commit is contained in:
Andrzej Rybczak
2012-09-05 20:19:21 +02:00
parent 7c6467a9e7
commit eff1d672b9
4 changed files with 95 additions and 34 deletions

View File

@@ -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();

View File

@@ -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()

View File

@@ -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

View File

@@ -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) { }
virtual void Run() {
for (auto it = m_queue.begin(); it != m_queue.end(); ++it)
(*m_window)->pushChar(*it);
}
PushCharacters(Window **w, const std::initializer_list<int> &v) : Action(aMacroUtility, "")
{
construct(w, v.begin(), v.end());
}
virtual void Run()
{
for (auto it = itsQueue.begin(); it != itsQueue.end(); ++it)
(*itsWindow)->PushChar(*it);
}
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;
private:
NC::Window **m_window;
std::vector<int> m_queue;
};
struct RequireRunnable : public Action
{
RequireRunnable(Action *action)
: Action(aMacroUtility, ""), m_action(action) { assert(action); }
virtual bool canBeRun() const { return m_action->canBeRun(); }
virtual void Run() { }
private:
Action *m_action;
};
#endif // _MACRO_UTILITIES