✨ add command executor.
parent
83cf9af94e
commit
1d2394068d
|
@ -11,6 +11,10 @@ twq_lib = static_library('tiwiq',
|
||||||
sources: [
|
sources: [
|
||||||
'src/core/KeyMod.cpp',
|
'src/core/KeyMod.cpp',
|
||||||
'src/core/Shortcut.cpp',
|
'src/core/Shortcut.cpp',
|
||||||
|
'src/core/Command.cpp',
|
||||||
|
'src/core/Context.cpp',
|
||||||
|
'src/core/Binding.cpp',
|
||||||
|
'src/core/Executor.cpp',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
dependency('ncursesw')
|
dependency('ncursesw')
|
||||||
|
@ -34,6 +38,7 @@ executable('twq-tests',
|
||||||
sources: [
|
sources: [
|
||||||
'tests/main.cpp',
|
'tests/main.cpp',
|
||||||
'tests/Shortcut.cpp',
|
'tests/Shortcut.cpp',
|
||||||
|
'tests/Executor.cpp',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
twq_dep,
|
twq_dep,
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TWQ_ASSERT(COND, MSG) \
|
#define TWQ_ASSERT(COND, MSG) \
|
||||||
if (! COND) { \
|
if (! (COND) ) { \
|
||||||
std::cerr << MSG << std::endl; \
|
std::cerr << MSG << std::endl; \
|
||||||
abort(); \
|
abort(); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "Binding.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Binding::Binding(std::shared_ptr<Shortcut> shortcut,
|
||||||
|
std::shared_ptr<Command> command)
|
||||||
|
: m_shortcut { shortcut }
|
||||||
|
, m_command { command }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Binding::~Binding()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef twq_core_BINDING_HPP
|
||||||
|
#define twq_core_BINDING_HPP
|
||||||
|
|
||||||
|
#include "Command.hpp"
|
||||||
|
#include "Shortcut.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Binding
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Binding(std::shared_ptr<Shortcut> shortcut,
|
||||||
|
std::shared_ptr<Command> command);
|
||||||
|
virtual ~Binding();
|
||||||
|
|
||||||
|
std::weak_ptr<Shortcut> shortcut() const { return m_shortcut; }
|
||||||
|
std::weak_ptr<Command> command() const { return m_command; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Shortcut> m_shortcut;
|
||||||
|
std::shared_ptr<Command> m_command;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "Command.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Command::Command()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Command::~Command()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef twq_core_COMMAND_HPP
|
||||||
|
#define twq_core_COMMAND_HPP
|
||||||
|
|
||||||
|
#include "Context.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Command();
|
||||||
|
virtual ~Command();
|
||||||
|
|
||||||
|
virtual void execute(Context& context) = 0;
|
||||||
|
virtual void undo(Context& context) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "Context.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Context::Context()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Context::~Context()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef twq_core_CONTEXT_HPP
|
||||||
|
#define twq_core_CONTEXT_HPP
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Context
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Context();
|
||||||
|
virtual ~Context();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "Executor.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Executor::Executor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Executor::~Executor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Executor::register_binding(Binding& binding)
|
||||||
|
{
|
||||||
|
m_entries.push_back({binding, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Executor::update(Context& context, KeyMod const& keymod)
|
||||||
|
{
|
||||||
|
for (auto& entry: m_entries)
|
||||||
|
{
|
||||||
|
auto shortcut = entry.binding.shortcut().lock();
|
||||||
|
|
||||||
|
if (shortcut->get(entry.progression).equals(keymod))
|
||||||
|
{
|
||||||
|
entry.progression++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.progression = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.progression >=
|
||||||
|
shortcut->count())
|
||||||
|
{
|
||||||
|
entry.binding.command().lock()->execute(context);
|
||||||
|
|
||||||
|
for (auto& entry: m_entries)
|
||||||
|
{
|
||||||
|
entry.progression = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef twq_core_EXECUTOR_HPP
|
||||||
|
#define twq_core_EXECUTOR_HPP
|
||||||
|
|
||||||
|
#include "Binding.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
struct Entry {
|
||||||
|
Binding binding;
|
||||||
|
size_t progression = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Executor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Executor();
|
||||||
|
virtual ~Executor();
|
||||||
|
|
||||||
|
void register_binding(Binding& binding);
|
||||||
|
void update(Context& context, KeyMod const& keymod);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Entry> m_entries;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,6 +10,64 @@ namespace twq
|
||||||
return KeyMod { key_type, mods, std::nullopt };
|
return KeyMod { key_type, mods, std::nullopt };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*explicit*/ KeyMod::KeyMod(std::string const& repr)
|
||||||
|
{
|
||||||
|
std::vector<ModType> mods;
|
||||||
|
|
||||||
|
if (repr.find("C-") != std::string::npos)
|
||||||
|
{
|
||||||
|
mods.push_back(MOD_LCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repr.find("A-") != std::string::npos)
|
||||||
|
{
|
||||||
|
mods.push_back(MOD_ALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t k = repr.size() - 1;
|
||||||
|
while (k >= 0 && std::isspace(repr[k]))
|
||||||
|
{
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
while (k >= 0
|
||||||
|
&& !std::isspace(repr[k])
|
||||||
|
&& repr[k] != '-')
|
||||||
|
{
|
||||||
|
value = repr[k] + value;
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.size() == 1)
|
||||||
|
{
|
||||||
|
m_key_type = KEY_TEXT;
|
||||||
|
m_mods = mods;
|
||||||
|
m_text = value.front();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<KEY_COUNT; i++)
|
||||||
|
{
|
||||||
|
std::string val = KeyTypeStr[i] + strlen("KEY_");
|
||||||
|
|
||||||
|
if (val == value)
|
||||||
|
{
|
||||||
|
m_key_type = (KeyType) i;
|
||||||
|
m_mods = mods;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw invalid_keymod_error {"cannot convert '"
|
||||||
|
+ repr
|
||||||
|
+ "' to keymod."};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*explicit*/ KeyMod::KeyMod(char text,
|
/*explicit*/ KeyMod::KeyMod(char text,
|
||||||
std::vector<ModType> const& mods)
|
std::vector<ModType> const& mods)
|
||||||
: m_key_type { KEY_TEXT }
|
: m_key_type { KEY_TEXT }
|
||||||
|
@ -38,6 +96,36 @@ namespace twq
|
||||||
std::find(std::begin(m_mods), std::end(m_mods), mod_type);
|
std::find(std::begin(m_mods), std::end(m_mods), mod_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyMod::equals(KeyMod const& rhs) const
|
||||||
|
{
|
||||||
|
if (m_key_type != rhs.m_key_type)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_key_type == KEY_TEXT
|
||||||
|
&& *m_text != *rhs.m_text)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mods.size() != rhs.m_mods.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<m_mods.size(); i++)
|
||||||
|
{
|
||||||
|
if (m_mods[i] != rhs.m_mods[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string KeyMod::string() const
|
std::string KeyMod::string() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -20,6 +20,8 @@ namespace twq
|
||||||
{
|
{
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
|
TWQ_ERROR(invalid_keymod_error);
|
||||||
|
|
||||||
TWQ_ENUM(KeyType, KEY_TYPES);
|
TWQ_ENUM(KeyType, KEY_TYPES);
|
||||||
TWQ_ENUM(ModType, MOD_TYPES);
|
TWQ_ENUM(ModType, MOD_TYPES);
|
||||||
|
|
||||||
|
@ -29,8 +31,11 @@ namespace twq
|
||||||
static KeyMod key(KeyType key_type,
|
static KeyMod key(KeyType key_type,
|
||||||
std::vector<ModType> const& mods={});
|
std::vector<ModType> const& mods={});
|
||||||
|
|
||||||
|
explicit KeyMod(std::string const& repr);
|
||||||
|
|
||||||
explicit KeyMod(char text, std::vector<ModType> const& mods={});
|
explicit KeyMod(char text, std::vector<ModType> const& mods={});
|
||||||
|
|
||||||
|
|
||||||
explicit KeyMod(KeyType key_type,
|
explicit KeyMod(KeyType key_type,
|
||||||
std::vector<ModType> const& mods,
|
std::vector<ModType> const& mods,
|
||||||
std::optional<char> text);
|
std::optional<char> text);
|
||||||
|
@ -41,6 +46,8 @@ namespace twq
|
||||||
|
|
||||||
bool has_mod(ModType mod_type) const;
|
bool has_mod(ModType mod_type) const;
|
||||||
|
|
||||||
|
bool equals(KeyMod const& rhs) const;
|
||||||
|
|
||||||
std::string string() const;
|
std::string string() const;
|
||||||
|
|
||||||
virtual ~KeyMod();
|
virtual ~KeyMod();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "Shortcut.hpp"
|
#include "Shortcut.hpp"
|
||||||
|
#include "src/commons.hpp"
|
||||||
#include "src/core/KeyMod.hpp"
|
#include "src/core/KeyMod.hpp"
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
|
@ -14,56 +15,6 @@ namespace twq
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
std::vector<ModType> mods;
|
std::vector<ModType> mods;
|
||||||
|
|
||||||
auto create_keymod = [&](){
|
|
||||||
if (buffer.find("C-") != std::string::npos)
|
|
||||||
{
|
|
||||||
mods.push_back(MOD_LCTRL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer.find("A-") != std::string::npos)
|
|
||||||
{
|
|
||||||
mods.push_back(MOD_ALT);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t k = buffer.size() - 1;
|
|
||||||
while (k >= 0 && std::isspace(buffer[k]))
|
|
||||||
{
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string value;
|
|
||||||
|
|
||||||
while (k >= 0
|
|
||||||
&& !std::isspace(buffer[k])
|
|
||||||
&& buffer[k] != '-')
|
|
||||||
{
|
|
||||||
value = buffer[k] + value;
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.size() == 1)
|
|
||||||
{
|
|
||||||
return KeyMod {KEY_TEXT, mods, value.front()};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t i=0; i<KEY_COUNT; i++)
|
|
||||||
{
|
|
||||||
std::string val = KeyTypeStr[i] + strlen("KEY_");
|
|
||||||
|
|
||||||
if (val == value)
|
|
||||||
{
|
|
||||||
return KeyMod {(KeyType) i, mods, std::nullopt};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw invalid_shortcut_error {"cannot convert '"
|
|
||||||
+ repr
|
|
||||||
+ "' to shortcut."};
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i=0; i<repr.size(); i++)
|
for (size_t i=0; i<repr.size(); i++)
|
||||||
{
|
{
|
||||||
char c = repr[i];
|
char c = repr[i];
|
||||||
|
@ -72,7 +23,16 @@ namespace twq
|
||||||
{
|
{
|
||||||
if (!buffer.empty())
|
if (!buffer.empty())
|
||||||
{
|
{
|
||||||
push(create_keymod());
|
try
|
||||||
|
{
|
||||||
|
push(KeyMod {buffer});
|
||||||
|
}
|
||||||
|
catch (invalid_keymod_error const& err)
|
||||||
|
{
|
||||||
|
throw invalid_shortcut_error {"cannot convert '"
|
||||||
|
+ repr
|
||||||
|
+ "' to shortcut"};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mods.clear();
|
mods.clear();
|
||||||
|
@ -86,7 +46,16 @@ namespace twq
|
||||||
|
|
||||||
if (!buffer.empty())
|
if (!buffer.empty())
|
||||||
{
|
{
|
||||||
push(create_keymod());
|
try
|
||||||
|
{
|
||||||
|
push(KeyMod {buffer});
|
||||||
|
}
|
||||||
|
catch (invalid_keymod_error const& err)
|
||||||
|
{
|
||||||
|
throw invalid_shortcut_error {"cannot convert '"
|
||||||
|
+ repr
|
||||||
|
+ "' to shortcut"};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +63,15 @@ namespace twq
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyMod Shortcut::get(size_t index) const
|
||||||
|
{
|
||||||
|
TWQ_ASSERT(index < count(), "cannot get shortcut at index '"
|
||||||
|
+ std::to_string(index)
|
||||||
|
+ "'");
|
||||||
|
|
||||||
|
return m_keymods[index];
|
||||||
|
}
|
||||||
|
|
||||||
void Shortcut::push(KeyMod const& keymod)
|
void Shortcut::push(KeyMod const& keymod)
|
||||||
{
|
{
|
||||||
m_keymods.push_back(keymod);
|
m_keymods.push_back(keymod);
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace twq
|
||||||
explicit Shortcut(std::string const& repr);
|
explicit Shortcut(std::string const& repr);
|
||||||
virtual ~Shortcut();
|
virtual ~Shortcut();
|
||||||
|
|
||||||
|
size_t count() const { return m_keymods.size(); }
|
||||||
|
KeyMod get(size_t index) const;
|
||||||
|
|
||||||
void push(KeyMod const& keymod);
|
void push(KeyMod const& keymod);
|
||||||
std::string string() const;
|
std::string string() const;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
#include "../src/core/Executor.hpp"
|
||||||
|
|
||||||
|
using namespace twq::core;
|
||||||
|
|
||||||
|
class ExecutorTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ExecutorTest() {}
|
||||||
|
virtual ~ExecutorTest() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandMock: public Command
|
||||||
|
{
|
||||||
|
int execute_count = 0;
|
||||||
|
|
||||||
|
void execute(Context&) override
|
||||||
|
{
|
||||||
|
execute_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo(Context&) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_one_key")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
|
Binding b {std::make_shared<Shortcut>("a"), cmd};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b);
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(2 == cmd->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_same_keys")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
|
Binding b {std::make_shared<Shortcut>("a a"), cmd};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b);
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(2 == cmd->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_keys")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
|
||||||
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
|
Binding b {std::make_shared<Shortcut>("a b"), cmd};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b);
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
REQUIRE(2 == cmd->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_wrong_key")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
|
||||||
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
|
Binding b {std::make_shared<Shortcut>("a b"), cmd};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b);
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"c"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"a"});
|
||||||
|
REQUIRE(0 == cmd->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
REQUIRE(1 == cmd->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
|
||||||
|
auto cmd0 = std::make_shared<CommandMock>();
|
||||||
|
Binding b0 {std::make_shared<Shortcut>("C-a b"), cmd0};
|
||||||
|
|
||||||
|
auto cmd1 = std::make_shared<CommandMock>();
|
||||||
|
Binding b1 {std::make_shared<Shortcut>("C-a c"), cmd1};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b0);
|
||||||
|
exec.register_binding(b1);
|
||||||
|
|
||||||
|
SECTION("execute first")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"C-a"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
|
||||||
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("execute second")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"C-a"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"c"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(1 == cmd1->execute_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fail first, try but fail second")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"C-a"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"d"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_sequentials_commands")
|
||||||
|
{
|
||||||
|
Context ctx;
|
||||||
|
|
||||||
|
auto cmd0 = std::make_shared<CommandMock>();
|
||||||
|
Binding b0 {std::make_shared<Shortcut>("C-a b"), cmd0};
|
||||||
|
|
||||||
|
auto cmd1 = std::make_shared<CommandMock>();
|
||||||
|
Binding b1 {std::make_shared<Shortcut>("b c"), cmd1};
|
||||||
|
|
||||||
|
Executor exec;
|
||||||
|
exec.register_binding(b0);
|
||||||
|
exec.register_binding(b1);
|
||||||
|
|
||||||
|
SECTION("execute sequentially")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"C-a"});
|
||||||
|
|
||||||
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
|
||||||
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"c"});
|
||||||
|
|
||||||
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"b"});
|
||||||
|
|
||||||
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
exec.update(ctx, KeyMod {"c"});
|
||||||
|
|
||||||
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
|
REQUIRE(1 == cmd1->execute_count);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue