✨ can now quit tiwiq using C-C C-C keys.
parent
1d2394068d
commit
5188860936
19
meson.build
19
meson.build
|
@ -9,12 +9,25 @@ project('tiwiq',
|
||||||
|
|
||||||
twq_lib = static_library('tiwiq',
|
twq_lib = static_library('tiwiq',
|
||||||
sources: [
|
sources: [
|
||||||
'src/core/KeyMod.cpp',
|
'src/core/Binding.cpp',
|
||||||
'src/core/Shortcut.cpp',
|
|
||||||
'src/core/Command.cpp',
|
'src/core/Command.cpp',
|
||||||
'src/core/Context.cpp',
|
'src/core/Context.cpp',
|
||||||
'src/core/Binding.cpp',
|
|
||||||
'src/core/Executor.cpp',
|
'src/core/Executor.cpp',
|
||||||
|
'src/core/KeyMod.cpp',
|
||||||
|
'src/core/Plugin.cpp',
|
||||||
|
'src/core/Shortcut.cpp',
|
||||||
|
'src/core/Tiwiq.cpp',
|
||||||
|
'src/core/UI.cpp',
|
||||||
|
'src/core/Observer.cpp',
|
||||||
|
'src/core/Observable.cpp',
|
||||||
|
'src/core/Event.cpp',
|
||||||
|
|
||||||
|
'src/cmd/QuitCmd.cpp',
|
||||||
|
|
||||||
|
'src/plugins/CorePlugin.cpp',
|
||||||
|
|
||||||
|
'src/term/Controller.cpp',
|
||||||
|
'src/term/Term.cpp',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
dependency('ncursesw')
|
dependency('ncursesw')
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include "QuitCmd.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace cmd
|
||||||
|
{
|
||||||
|
/*explicit*/ QuitCmd::QuitCmd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ QuitCmd::~QuitCmd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ void QuitCmd::execute(core::Context& context) /*override*/
|
||||||
|
{
|
||||||
|
context.tiwiq().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ void QuitCmd::undo(core::Context&) /*override*/
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef twq_cmd_QUITCMD_HPP
|
||||||
|
#define twq_cmd_QUITCMD_HPP
|
||||||
|
|
||||||
|
#include "../core/Command.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace cmd
|
||||||
|
{
|
||||||
|
class QuitCmd: public core::Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit QuitCmd();
|
||||||
|
virtual ~QuitCmd();
|
||||||
|
|
||||||
|
virtual void execute(core::Context& context) override;
|
||||||
|
virtual void undo(core::Context& context) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -4,7 +4,8 @@ namespace twq
|
||||||
{
|
{
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
/*explicit*/ Context::Context()
|
/*explicit*/ Context::Context(Tiwiq& tiwiq)
|
||||||
|
: m_tiwiq { tiwiq }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef twq_core_CONTEXT_HPP
|
#ifndef twq_core_CONTEXT_HPP
|
||||||
#define twq_core_CONTEXT_HPP
|
#define twq_core_CONTEXT_HPP
|
||||||
|
|
||||||
|
#include "Tiwiq.hpp"
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
namespace core
|
namespace core
|
||||||
|
@ -8,10 +10,13 @@ namespace twq
|
||||||
class Context
|
class Context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Context();
|
explicit Context(Tiwiq& tiwiq);
|
||||||
virtual ~Context();
|
virtual ~Context();
|
||||||
|
|
||||||
|
Tiwiq& tiwiq() const { return m_tiwiq; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Tiwiq& m_tiwiq;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Event.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef twq_core_EVENT_HPP
|
||||||
|
#define twq_core_EVENT_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "KeyMod.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
struct Event
|
||||||
|
{
|
||||||
|
std::optional<KeyMod> key;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,18 +10,18 @@ namespace twq
|
||||||
return KeyMod { key_type, mods, std::nullopt };
|
return KeyMod { key_type, mods, std::nullopt };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*explicit*/ KeyMod::KeyMod(std::string const& repr)
|
/*explicit*/ KeyMod::KeyMod(std::wstring const& repr)
|
||||||
{
|
{
|
||||||
std::vector<ModType> mods;
|
std::vector<ModType> mods;
|
||||||
|
|
||||||
if (repr.find("C-") != std::string::npos)
|
if (repr.find(L"C-") != std::string::npos)
|
||||||
{
|
{
|
||||||
mods.push_back(MOD_LCTRL);
|
mods.push_back(KM_MOD_LCTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repr.find("A-") != std::string::npos)
|
if (repr.find(L"A-") != std::string::npos)
|
||||||
{
|
{
|
||||||
mods.push_back(MOD_ALT);
|
mods.push_back(KM_MOD_ALT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t k = repr.size() - 1;
|
ssize_t k = repr.size() - 1;
|
||||||
|
@ -30,7 +30,7 @@ namespace twq
|
||||||
k--;
|
k--;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string value;
|
std::wstring value;
|
||||||
|
|
||||||
while (k >= 0
|
while (k >= 0
|
||||||
&& !std::isspace(repr[k])
|
&& !std::isspace(repr[k])
|
||||||
|
@ -42,16 +42,17 @@ namespace twq
|
||||||
|
|
||||||
if (value.size() == 1)
|
if (value.size() == 1)
|
||||||
{
|
{
|
||||||
m_key_type = KEY_TEXT;
|
m_key_type = KM_KEY_TEXT;
|
||||||
m_mods = mods;
|
m_mods = mods;
|
||||||
m_text = value.front();
|
m_text = value.front();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<KEY_COUNT; i++)
|
for (size_t i=0; i<KM_KEY_COUNT; i++)
|
||||||
{
|
{
|
||||||
std::string val = KeyTypeStr[i] + strlen("KEY_");
|
std::string v = KeyTypeStr[i] + strlen("KM_KEY_");
|
||||||
|
std::wstring val(std::begin(v), std::end(v));
|
||||||
|
|
||||||
if (val == value)
|
if (val == value)
|
||||||
{
|
{
|
||||||
|
@ -62,15 +63,16 @@ namespace twq
|
||||||
}
|
}
|
||||||
|
|
||||||
throw invalid_keymod_error {"cannot convert '"
|
throw invalid_keymod_error {"cannot convert '"
|
||||||
+ repr
|
+ std::string(std::begin(repr),
|
||||||
|
std::end(repr))
|
||||||
+ "' to keymod."};
|
+ "' to keymod."};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*explicit*/ KeyMod::KeyMod(char text,
|
/*explicit*/ KeyMod::KeyMod(wchar_t text,
|
||||||
std::vector<ModType> const& mods)
|
std::vector<ModType> const& mods)
|
||||||
: m_key_type { KEY_TEXT }
|
: m_key_type { KM_KEY_TEXT }
|
||||||
, m_mods { mods }
|
, m_mods { mods }
|
||||||
, m_text { text }
|
, m_text { text }
|
||||||
{
|
{
|
||||||
|
@ -78,7 +80,7 @@ namespace twq
|
||||||
|
|
||||||
/*explicit*/ KeyMod::KeyMod(KeyType key_type,
|
/*explicit*/ KeyMod::KeyMod(KeyType key_type,
|
||||||
std::vector<ModType> const& mods,
|
std::vector<ModType> const& mods,
|
||||||
std::optional<char> text)
|
std::optional<wchar_t> text)
|
||||||
: m_key_type { key_type }
|
: m_key_type { key_type }
|
||||||
, m_mods { mods }
|
, m_mods { mods }
|
||||||
, m_text { text }
|
, m_text { text }
|
||||||
|
@ -103,7 +105,7 @@ namespace twq
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_key_type == KEY_TEXT
|
if (m_key_type == KM_KEY_TEXT
|
||||||
&& *m_text != *rhs.m_text)
|
&& *m_text != *rhs.m_text)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -126,27 +128,27 @@ namespace twq
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyMod::string() const
|
std::wstring KeyMod::wstring() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::wstringstream ss;
|
||||||
|
|
||||||
if (has_mod(MOD_LCTRL))
|
if (has_mod(KM_MOD_LCTRL))
|
||||||
{
|
{
|
||||||
ss << "C-";
|
ss << "C-";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_mod(MOD_ALT))
|
if (has_mod(KM_MOD_ALT))
|
||||||
{
|
{
|
||||||
ss << "A-";
|
ss << "A-";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_key_type == KEY_TEXT)
|
if (m_key_type == KM_KEY_TEXT)
|
||||||
{
|
{
|
||||||
ss << *m_text;
|
ss << *m_text;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ss << (KeyTypeStr[m_key_type] + strlen("KEY_"));
|
ss << (KeyTypeStr[m_key_type] + strlen("KM_KEY_"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
#include "../commons.hpp"
|
#include "../commons.hpp"
|
||||||
|
|
||||||
#define KEY_TYPES(G) \
|
#define KEY_TYPES(G) \
|
||||||
G(KEY_TEXT), \
|
G(KM_KEY_TEXT), \
|
||||||
G(KEY_UP), \
|
G(KM_KEY_UP), \
|
||||||
G(KEY_DOWN), \
|
G(KM_KEY_DOWN), \
|
||||||
G(KEY_LEFT), \
|
G(KM_KEY_LEFT), \
|
||||||
G(KEY_RIGHT), \
|
G(KM_KEY_RIGHT), \
|
||||||
G(KEY_COUNT),
|
G(KM_KEY_COUNT),
|
||||||
|
|
||||||
#define MOD_TYPES(G)\
|
#define MOD_TYPES(G)\
|
||||||
G(MOD_LCTRL), \
|
G(KM_MOD_LCTRL), \
|
||||||
G(MOD_ALT), \
|
G(KM_MOD_ALT), \
|
||||||
G(MOD_COUNT),
|
G(KM_MOD_COUNT),
|
||||||
|
|
||||||
namespace twq
|
namespace twq
|
||||||
{
|
{
|
||||||
|
@ -31,31 +31,31 @@ 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(std::wstring const& repr);
|
||||||
|
|
||||||
explicit KeyMod(char text, std::vector<ModType> const& mods={});
|
explicit KeyMod(wchar_t 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<wchar_t> text);
|
||||||
|
|
||||||
KeyType key_type() const { return m_key_type; }
|
KeyType key_type() const { return m_key_type; }
|
||||||
std::vector<ModType> mods() const { return m_mods; }
|
std::vector<ModType> mods() const { return m_mods; }
|
||||||
std::optional<char> text() const { return m_text; }
|
std::optional<wchar_t> text() const { return m_text; }
|
||||||
|
|
||||||
bool has_mod(ModType mod_type) const;
|
bool has_mod(ModType mod_type) const;
|
||||||
|
|
||||||
bool equals(KeyMod const& rhs) const;
|
bool equals(KeyMod const& rhs) const;
|
||||||
|
|
||||||
std::string string() const;
|
std::wstring wstring() const;
|
||||||
|
|
||||||
virtual ~KeyMod();
|
virtual ~KeyMod();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KeyType m_key_type;
|
KeyType m_key_type;
|
||||||
std::vector<ModType> m_mods;
|
std::vector<ModType> m_mods;
|
||||||
std::optional<char> m_text;
|
std::optional<wchar_t> m_text;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "Observable.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Observable::Observable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Observable::~Observable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Observable::add_observer(std::weak_ptr<Observer> observer)
|
||||||
|
{
|
||||||
|
m_observers.push_back(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Observable::notify(Event& event)
|
||||||
|
{
|
||||||
|
for (auto observer: m_observers)
|
||||||
|
{
|
||||||
|
if (auto obs = observer.lock();
|
||||||
|
obs)
|
||||||
|
{
|
||||||
|
obs->update(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef twq_core_OBSERVABLE_HPP
|
||||||
|
#define twq_core_OBSERVABLE_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Observer.hpp"
|
||||||
|
#include "Event.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Observable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Observable();
|
||||||
|
virtual ~Observable();
|
||||||
|
|
||||||
|
void add_observer(std::weak_ptr<Observer> observer);
|
||||||
|
void notify(Event& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::weak_ptr<Observer>> m_observers;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "Observer.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Observer::Observer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Observer::~Observer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef twq_core_OBSERVER_HPP
|
||||||
|
#define twq_core_OBSERVER_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Event.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Observer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Observer();
|
||||||
|
virtual ~Observer();
|
||||||
|
|
||||||
|
virtual void update(Event&) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "Plugin.hpp"
|
||||||
|
#include "Executor.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Plugin::Plugin(std::string const& name)
|
||||||
|
: m_name { name }
|
||||||
|
, m_executor { std::make_shared<Executor>() }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Plugin::~Plugin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Executor> Plugin::executor()
|
||||||
|
{
|
||||||
|
return m_executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef twq_core_PLUGIN_HPP
|
||||||
|
#define twq_core_PLUGIN_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "UI.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Executor;
|
||||||
|
|
||||||
|
class Plugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Plugin(std::string const& name);
|
||||||
|
virtual ~Plugin();
|
||||||
|
|
||||||
|
std::string name() const { return m_name; }
|
||||||
|
std::weak_ptr<UI> ui() { return m_ui; }
|
||||||
|
|
||||||
|
std::weak_ptr<Executor> executor();
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
std::shared_ptr<Executor> m_executor;
|
||||||
|
|
||||||
|
std::shared_ptr<UI> m_ui =
|
||||||
|
std::make_shared<UI>();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,14 +10,14 @@ namespace twq
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*explicit*/ Shortcut::Shortcut(std::string const& repr)
|
/*explicit*/ Shortcut::Shortcut(std::wstring const& repr)
|
||||||
{
|
{
|
||||||
std::string buffer;
|
std::wstring buffer;
|
||||||
std::vector<ModType> mods;
|
std::vector<ModType> mods;
|
||||||
|
|
||||||
for (size_t i=0; i<repr.size(); i++)
|
for (size_t i=0; i<repr.size(); i++)
|
||||||
{
|
{
|
||||||
char c = repr[i];
|
wchar_t c = repr[i];
|
||||||
|
|
||||||
if (std::isspace(c))
|
if (std::isspace(c))
|
||||||
{
|
{
|
||||||
|
@ -29,8 +29,10 @@ namespace twq
|
||||||
}
|
}
|
||||||
catch (invalid_keymod_error const& err)
|
catch (invalid_keymod_error const& err)
|
||||||
{
|
{
|
||||||
throw invalid_shortcut_error {"cannot convert '"
|
throw invalid_shortcut_error {
|
||||||
+ repr
|
"cannot convert '"
|
||||||
|
+ std::string(std::begin(repr),
|
||||||
|
std::end(repr))
|
||||||
+ "' to shortcut"};
|
+ "' to shortcut"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +55,8 @@ namespace twq
|
||||||
catch (invalid_keymod_error const& err)
|
catch (invalid_keymod_error const& err)
|
||||||
{
|
{
|
||||||
throw invalid_shortcut_error {"cannot convert '"
|
throw invalid_shortcut_error {"cannot convert '"
|
||||||
+ repr
|
+ std::string(std::begin(repr),
|
||||||
|
std::end(repr))
|
||||||
+ "' to shortcut"};
|
+ "' to shortcut"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,15 +80,15 @@ namespace twq
|
||||||
m_keymods.push_back(keymod);
|
m_keymods.push_back(keymod);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Shortcut::string() const
|
std::wstring Shortcut::wstring() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::wstringstream ss;
|
||||||
std::string sep;
|
std::wstring sep;
|
||||||
|
|
||||||
for (auto const& km: m_keymods)
|
for (auto const& km: m_keymods)
|
||||||
{
|
{
|
||||||
ss << sep << km.string();
|
ss << sep << km.wstring();
|
||||||
sep = " ";
|
sep = L" ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace twq
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Shortcut();
|
explicit Shortcut();
|
||||||
explicit Shortcut(std::string const& repr);
|
explicit Shortcut(std::wstring const& repr);
|
||||||
virtual ~Shortcut();
|
virtual ~Shortcut();
|
||||||
|
|
||||||
size_t count() const { return m_keymods.size(); }
|
size_t count() const { return m_keymods.size(); }
|
||||||
KeyMod get(size_t index) const;
|
KeyMod get(size_t index) const;
|
||||||
|
|
||||||
void push(KeyMod const& keymod);
|
void push(KeyMod const& keymod);
|
||||||
std::string string() const;
|
std::wstring wstring() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<KeyMod> m_keymods;
|
std::vector<KeyMod> m_keymods;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "Tiwiq.hpp"
|
||||||
|
#include "Event.hpp"
|
||||||
|
#include "Executor.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ Tiwiq::Tiwiq()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Tiwiq::~Tiwiq()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tiwiq::start()
|
||||||
|
{
|
||||||
|
m_is_running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tiwiq::stop()
|
||||||
|
{
|
||||||
|
m_is_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tiwiq::add_plugin(std::shared_ptr<Plugin> plugin)
|
||||||
|
{
|
||||||
|
m_plugins.push_back(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tiwiq::update(Event& event) /*override*/
|
||||||
|
{
|
||||||
|
if (event.key)
|
||||||
|
{
|
||||||
|
if (!m_plugins.empty())
|
||||||
|
{
|
||||||
|
Context ctx { *this };
|
||||||
|
m_plugins.back()->executor().lock()->update(ctx, *event.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef twq_core_TIWIQ_HPP
|
||||||
|
#define twq_core_TIWIQ_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Plugin.hpp"
|
||||||
|
#include "Observer.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class Tiwiq: public Observer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Tiwiq();
|
||||||
|
virtual ~Tiwiq();
|
||||||
|
|
||||||
|
bool is_running() const { return m_is_running; }
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
void add_plugin(std::shared_ptr<Plugin> plugin);
|
||||||
|
|
||||||
|
void update(Event& event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_is_running = false;
|
||||||
|
std::vector<std::shared_ptr<Plugin>> m_plugins;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "UI.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
/*explicit*/ UI::UI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ UI::~UI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef twq_core_UI_HPP
|
||||||
|
#define twq_core_UI_HPP
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace core
|
||||||
|
{
|
||||||
|
class UI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit UI();
|
||||||
|
virtual ~UI();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
21
src/main.cpp
21
src/main.cpp
|
@ -1,6 +1,27 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "core/Tiwiq.hpp"
|
||||||
|
#include "term/Term.hpp"
|
||||||
|
#include "plugins/CorePlugin.hpp"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
|
auto tiwiq = std::make_shared<twq::core::Tiwiq>();
|
||||||
|
auto term = std::make_shared<twq::term::Term>();
|
||||||
|
term->controller().lock()->add_observer(tiwiq);
|
||||||
|
|
||||||
|
// Build and add plugins
|
||||||
|
// ---------------------
|
||||||
|
auto core_plugin = std::make_shared<twq::plugins::CorePlugin>();
|
||||||
|
tiwiq->add_plugin(core_plugin);
|
||||||
|
|
||||||
|
// Start TiwiQ
|
||||||
|
// -----------
|
||||||
|
tiwiq->start();
|
||||||
|
|
||||||
|
while (tiwiq->is_running())
|
||||||
|
{
|
||||||
|
term->controller().lock()->update();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "CorePlugin.hpp"
|
||||||
|
#include "../core/Executor.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace plugins
|
||||||
|
{
|
||||||
|
/*explicit*/ CorePlugin::CorePlugin()
|
||||||
|
: core::Plugin {"core"}
|
||||||
|
{
|
||||||
|
auto exec = executor().lock();
|
||||||
|
|
||||||
|
auto sc = std::make_shared<core::Shortcut>(L"C-C C-C");
|
||||||
|
auto cmd = std::make_shared<cmd::QuitCmd>();
|
||||||
|
auto binding = core::Binding{sc, cmd};
|
||||||
|
exec->register_binding(binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ CorePlugin::~CorePlugin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef twq_plugins_COREPLUGIN_HPP
|
||||||
|
#define twq_plugins_COREPLUGIN_HPP
|
||||||
|
|
||||||
|
#include "../core/Plugin.hpp"
|
||||||
|
#include "../cmd/QuitCmd.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace plugins
|
||||||
|
{
|
||||||
|
class CorePlugin: public core::Plugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CorePlugin();
|
||||||
|
virtual ~CorePlugin();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include <curses.h>
|
||||||
|
#include "Controller.hpp"
|
||||||
|
#include "../core/KeyMod.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
/*explicit*/ Controller::Controller()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Controller::~Controller()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::update()
|
||||||
|
{
|
||||||
|
core::Event event;
|
||||||
|
event.key = get();
|
||||||
|
notify(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
core::KeyMod Controller::get() const
|
||||||
|
{
|
||||||
|
wint_t c;
|
||||||
|
get_wch(&c);
|
||||||
|
|
||||||
|
core::KeyType key_type = core::KM_KEY_TEXT;
|
||||||
|
std::optional<wchar_t> text;
|
||||||
|
std::vector<core::ModType> mods;
|
||||||
|
|
||||||
|
if (c == 27)
|
||||||
|
{
|
||||||
|
get_wch(&c);
|
||||||
|
mods.push_back(core::KM_MOD_ALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name = keyname(c);
|
||||||
|
std::wstring wname {std::begin(name), std::end(name)};
|
||||||
|
|
||||||
|
if (wname.size() > 1 && wname[0] == L'^')
|
||||||
|
{
|
||||||
|
text = wname[1];
|
||||||
|
mods.push_back(core::KM_MOD_LCTRL);
|
||||||
|
}
|
||||||
|
else if (std::iswprint((wchar_t) c))
|
||||||
|
{
|
||||||
|
text = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TWQ_ASSERT(0, "keymod not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto keymod = core::KeyMod {key_type, mods, text};
|
||||||
|
return keymod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef twq_term_CONTROLLER_HPP
|
||||||
|
#define twq_term_CONTROLLER_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "../core/KeyMod.hpp"
|
||||||
|
#include "../core/Observable.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
class Controller: public core::Observable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Controller();
|
||||||
|
virtual ~Controller();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
core::KeyMod get() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "Term.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
/*explicit*/ Term::Term()
|
||||||
|
{
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
initscr();
|
||||||
|
raw();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
noecho();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Term::~Term()
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef twq_term_TERM_HPP
|
||||||
|
#define twq_term_TERM_HPP
|
||||||
|
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
#include "Controller.hpp"
|
||||||
|
|
||||||
|
namespace twq
|
||||||
|
{
|
||||||
|
namespace term
|
||||||
|
{
|
||||||
|
class Term
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Term();
|
||||||
|
virtual ~Term();
|
||||||
|
|
||||||
|
std::weak_ptr<Controller> controller() { return m_controller; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Controller> m_controller =
|
||||||
|
std::make_shared<Controller>();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,5 @@
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
#include "../src/core/Tiwiq.hpp"
|
||||||
#include "../src/core/Executor.hpp"
|
#include "../src/core/Executor.hpp"
|
||||||
|
|
||||||
using namespace twq::core;
|
using namespace twq::core;
|
||||||
|
@ -9,7 +10,13 @@ public:
|
||||||
explicit ExecutorTest() {}
|
explicit ExecutorTest() {}
|
||||||
virtual ~ExecutorTest() {}
|
virtual ~ExecutorTest() {}
|
||||||
|
|
||||||
|
Context get_context()
|
||||||
|
{
|
||||||
|
return Context {m_tiwiq};
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
twq::core::Tiwiq m_tiwiq;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandMock: public Command
|
struct CommandMock: public Command
|
||||||
|
@ -28,95 +35,95 @@ struct CommandMock: public Command
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_one_key")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_one_key")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
auto cmd = std::make_shared<CommandMock>();
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
Binding b {std::make_shared<Shortcut>("a"), cmd};
|
Binding b {std::make_shared<Shortcut>(L"a"), cmd};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b);
|
exec.register_binding(b);
|
||||||
|
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(2 == cmd->execute_count);
|
REQUIRE(2 == cmd->execute_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_two_same_keys")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_same_keys")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
auto cmd = std::make_shared<CommandMock>();
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
Binding b {std::make_shared<Shortcut>("a a"), cmd};
|
Binding b {std::make_shared<Shortcut>(L"a a"), cmd};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b);
|
exec.register_binding(b);
|
||||||
|
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(2 == cmd->execute_count);
|
REQUIRE(2 == cmd->execute_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_two_keys")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_keys")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
|
|
||||||
auto cmd = std::make_shared<CommandMock>();
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
Binding b {std::make_shared<Shortcut>("a b"), cmd};
|
Binding b {std::make_shared<Shortcut>(L"a b"), cmd};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b);
|
exec.register_binding(b);
|
||||||
|
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
REQUIRE(2 == cmd->execute_count);
|
REQUIRE(2 == cmd->execute_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_wrong_key")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_wrong_key")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
|
|
||||||
auto cmd = std::make_shared<CommandMock>();
|
auto cmd = std::make_shared<CommandMock>();
|
||||||
Binding b {std::make_shared<Shortcut>("a b"), cmd};
|
Binding b {std::make_shared<Shortcut>(L"a b"), cmd};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b);
|
exec.register_binding(b);
|
||||||
|
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"c"});
|
exec.update(ctx, KeyMod {L"c"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"a"});
|
exec.update(ctx, KeyMod {L"a"});
|
||||||
REQUIRE(0 == cmd->execute_count);
|
REQUIRE(0 == cmd->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
REQUIRE(1 == cmd->execute_count);
|
REQUIRE(1 == cmd->execute_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
|
|
||||||
auto cmd0 = std::make_shared<CommandMock>();
|
auto cmd0 = std::make_shared<CommandMock>();
|
||||||
Binding b0 {std::make_shared<Shortcut>("C-a b"), cmd0};
|
Binding b0 {std::make_shared<Shortcut>(L"C-a b"), cmd0};
|
||||||
|
|
||||||
auto cmd1 = std::make_shared<CommandMock>();
|
auto cmd1 = std::make_shared<CommandMock>();
|
||||||
Binding b1 {std::make_shared<Shortcut>("C-a c"), cmd1};
|
Binding b1 {std::make_shared<Shortcut>(L"C-a c"), cmd1};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b0);
|
exec.register_binding(b0);
|
||||||
|
@ -126,11 +133,11 @@ TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
{
|
{
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"C-a"});
|
exec.update(ctx, KeyMod {L"C-a"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
|
|
||||||
REQUIRE(1 == cmd0->execute_count);
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
@ -140,11 +147,11 @@ TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
{
|
{
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"C-a"});
|
exec.update(ctx, KeyMod {L"C-a"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"c"});
|
exec.update(ctx, KeyMod {L"c"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(1 == cmd1->execute_count);
|
REQUIRE(1 == cmd1->execute_count);
|
||||||
|
@ -154,15 +161,15 @@ TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
{
|
{
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"C-a"});
|
exec.update(ctx, KeyMod {L"C-a"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"d"});
|
exec.update(ctx, KeyMod {L"d"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
|
@ -171,13 +178,13 @@ TEST_CASE_METHOD(ExecutorTest, "Executor_two_commands")
|
||||||
|
|
||||||
TEST_CASE_METHOD(ExecutorTest, "Executor_two_sequentials_commands")
|
TEST_CASE_METHOD(ExecutorTest, "Executor_two_sequentials_commands")
|
||||||
{
|
{
|
||||||
Context ctx;
|
Context ctx = get_context();
|
||||||
|
|
||||||
auto cmd0 = std::make_shared<CommandMock>();
|
auto cmd0 = std::make_shared<CommandMock>();
|
||||||
Binding b0 {std::make_shared<Shortcut>("C-a b"), cmd0};
|
Binding b0 {std::make_shared<Shortcut>(L"C-a b"), cmd0};
|
||||||
|
|
||||||
auto cmd1 = std::make_shared<CommandMock>();
|
auto cmd1 = std::make_shared<CommandMock>();
|
||||||
Binding b1 {std::make_shared<Shortcut>("b c"), cmd1};
|
Binding b1 {std::make_shared<Shortcut>(L"b c"), cmd1};
|
||||||
|
|
||||||
Executor exec;
|
Executor exec;
|
||||||
exec.register_binding(b0);
|
exec.register_binding(b0);
|
||||||
|
@ -187,23 +194,23 @@ TEST_CASE_METHOD(ExecutorTest, "Executor_two_sequentials_commands")
|
||||||
{
|
{
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"C-a"});
|
exec.update(ctx, KeyMod {L"C-a"});
|
||||||
|
|
||||||
REQUIRE(0 == cmd0->execute_count);
|
REQUIRE(0 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
|
|
||||||
REQUIRE(1 == cmd0->execute_count);
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"c"});
|
exec.update(ctx, KeyMod {L"c"});
|
||||||
|
|
||||||
REQUIRE(1 == cmd0->execute_count);
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"b"});
|
exec.update(ctx, KeyMod {L"b"});
|
||||||
|
|
||||||
REQUIRE(1 == cmd0->execute_count);
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
REQUIRE(0 == cmd1->execute_count);
|
REQUIRE(0 == cmd1->execute_count);
|
||||||
exec.update(ctx, KeyMod {"c"});
|
exec.update(ctx, KeyMod {L"c"});
|
||||||
|
|
||||||
REQUIRE(1 == cmd0->execute_count);
|
REQUIRE(1 == cmd0->execute_count);
|
||||||
REQUIRE(1 == cmd1->execute_count);
|
REQUIRE(1 == cmd1->execute_count);
|
||||||
|
|
|
@ -9,7 +9,7 @@ public:
|
||||||
explicit ShortcutTest() {}
|
explicit ShortcutTest() {}
|
||||||
virtual ~ShortcutTest() {}
|
virtual ~ShortcutTest() {}
|
||||||
|
|
||||||
void test_to_string(std::string const& oracle,
|
void test_to_string(std::wstring const& oracle,
|
||||||
std::vector<KeyMod> keymods)
|
std::vector<KeyMod> keymods)
|
||||||
{
|
{
|
||||||
Shortcut sc;
|
Shortcut sc;
|
||||||
|
@ -19,16 +19,15 @@ public:
|
||||||
sc.push(km);
|
sc.push(km);
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("Expected '" << oracle << "' got '" << sc.string() << "'");
|
REQUIRE(oracle == sc.wstring());
|
||||||
REQUIRE(oracle == sc.string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_from_string(std::string const& oracle,
|
void test_from_string(std::wstring const& oracle,
|
||||||
std::string const& shortcut)
|
std::wstring const& shortcut)
|
||||||
{
|
{
|
||||||
Shortcut sc { shortcut };
|
Shortcut sc { shortcut };
|
||||||
INFO("Expected '" << oracle << "' got '" << sc.string() << "'");
|
|
||||||
REQUIRE(oracle == sc.string());
|
REQUIRE(oracle == sc.wstring());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -36,71 +35,71 @@ protected:
|
||||||
|
|
||||||
TEST_CASE_METHOD(ShortcutTest, "Shortcut_string")
|
TEST_CASE_METHOD(ShortcutTest, "Shortcut_string")
|
||||||
{
|
{
|
||||||
test_to_string("f", {KeyMod {'f'}});
|
test_to_string(L"f", {KeyMod {'f'}});
|
||||||
|
|
||||||
test_to_string("a b c", {
|
test_to_string(L"a b c", {
|
||||||
KeyMod {'a'},
|
KeyMod {L'a'},
|
||||||
KeyMod {'b'},
|
KeyMod {L'b'},
|
||||||
KeyMod {'c'},
|
KeyMod {L'c'},
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("C-g", {KeyMod {'g', {MOD_LCTRL}}});
|
test_to_string(L"C-g", {KeyMod {L'g', {KM_MOD_LCTRL}}});
|
||||||
test_to_string("A-g", {KeyMod {'g', {MOD_ALT}}});
|
test_to_string(L"A-g", {KeyMod {L'g', {KM_MOD_ALT}}});
|
||||||
test_to_string("C-A-g", {KeyMod {'g', {MOD_LCTRL, MOD_ALT}}});
|
test_to_string(L"C-A-g", {KeyMod {L'g', {KM_MOD_LCTRL, KM_MOD_ALT}}});
|
||||||
|
|
||||||
test_to_string("A-a C-A-b C-c d", {
|
test_to_string(L"A-a C-A-b C-c d", {
|
||||||
KeyMod {'a', {MOD_ALT}},
|
KeyMod {L'a', {KM_MOD_ALT}},
|
||||||
KeyMod {'b', {MOD_LCTRL, MOD_ALT}},
|
KeyMod {L'b', {KM_MOD_LCTRL, KM_MOD_ALT}},
|
||||||
KeyMod {'c', {MOD_LCTRL}},
|
KeyMod {L'c', {KM_MOD_LCTRL}},
|
||||||
KeyMod {'d'},
|
KeyMod {L'd'},
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("UP", {
|
test_to_string(L"UP", {
|
||||||
KeyMod::key(KEY_UP)
|
KeyMod::key(KM_KEY_UP)
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("DOWN", {
|
test_to_string(L"DOWN", {
|
||||||
KeyMod::key(KEY_DOWN)
|
KeyMod::key(KM_KEY_DOWN)
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("LEFT", {
|
test_to_string(L"LEFT", {
|
||||||
KeyMod::key(KEY_LEFT)
|
KeyMod::key(KM_KEY_LEFT)
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("RIGHT", {
|
test_to_string(L"RIGHT", {
|
||||||
KeyMod::key(KEY_RIGHT)
|
KeyMod::key(KM_KEY_RIGHT)
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("C-UP", {
|
test_to_string(L"C-UP", {
|
||||||
KeyMod::key(KEY_UP, {MOD_LCTRL})
|
KeyMod::key(KM_KEY_UP, {KM_MOD_LCTRL})
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("A-LEFT", {
|
test_to_string(L"A-LEFT", {
|
||||||
KeyMod::key(KEY_LEFT, {MOD_ALT}),
|
KeyMod::key(KM_KEY_LEFT, {KM_MOD_ALT}),
|
||||||
});
|
});
|
||||||
|
|
||||||
test_to_string("C-A-RIGHT", {
|
test_to_string(L"C-A-RIGHT", {
|
||||||
KeyMod::key(KEY_RIGHT, {MOD_LCTRL, MOD_ALT}),
|
KeyMod::key(KM_KEY_RIGHT, {KM_MOD_LCTRL, KM_MOD_ALT}),
|
||||||
});
|
});
|
||||||
|
|
||||||
test_from_string("", "");
|
test_from_string(L"", L"");
|
||||||
|
|
||||||
test_from_string("a", "a");
|
test_from_string(L"a", L"a");
|
||||||
test_from_string("a", " a");
|
test_from_string(L"a", L" a");
|
||||||
test_from_string("a", "a ");
|
test_from_string(L"a", L"a ");
|
||||||
|
|
||||||
test_from_string("C-a", "C-a");
|
test_from_string(L"C-a", L"C-a");
|
||||||
test_from_string("C-a", " C-a ");
|
test_from_string(L"C-a", L" C-a ");
|
||||||
test_from_string("A-a", "A-a");
|
test_from_string(L"A-a", L"A-a");
|
||||||
test_from_string("A-a", " A-a ");
|
test_from_string(L"A-a", L" A-a ");
|
||||||
|
|
||||||
test_from_string("C-A-a", " A-C-a ");
|
test_from_string(L"C-A-a", L" A-C-a ");
|
||||||
test_from_string("C-A-a", " C-A-a ");
|
test_from_string(L"C-A-a", L" C-A-a ");
|
||||||
|
|
||||||
test_from_string("C-A-a b C-c", " C-A-a b C-c");
|
test_from_string(L"C-A-a b C-c", L" C-A-a b C-c");
|
||||||
|
|
||||||
test_from_string("C-A-LEFT RIGHT C-UP",
|
test_from_string(L"C-A-LEFT RIGHT C-UP",
|
||||||
" C-A-LEFT RIGHT C-UP");
|
L" C-A-LEFT RIGHT C-UP");
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(Shortcut { "C-A-DUCK" }, invalid_shortcut_error);
|
REQUIRE_THROWS_AS(Shortcut { L"C-A-DUCK" }, invalid_shortcut_error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue