actions: use shared_ptr to store actions
This commit is contained in:
@@ -76,7 +76,7 @@ namespace ph = std::placeholders;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Actions::BaseAction>> AvailableActions;
|
std::vector<std::shared_ptr<Actions::BaseAction>> AvailableActions;
|
||||||
|
|
||||||
void populateActions();
|
void populateActions();
|
||||||
|
|
||||||
@@ -281,22 +281,26 @@ BaseAction &get(Actions::Type at)
|
|||||||
{
|
{
|
||||||
if (AvailableActions.empty())
|
if (AvailableActions.empty())
|
||||||
populateActions();
|
populateActions();
|
||||||
BaseAction *action = AvailableActions.at(static_cast<size_t>(at)).get();
|
return *AvailableActions.at(static_cast<size_t>(at));
|
||||||
// action should be always present if action type in queried
|
|
||||||
assert(action != nullptr);
|
|
||||||
return *action;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseAction *get(const std::string &name)
|
std::shared_ptr<BaseAction> get_(Actions::Type at)
|
||||||
{
|
{
|
||||||
BaseAction *result = nullptr;
|
if (AvailableActions.empty())
|
||||||
|
populateActions();
|
||||||
|
return AvailableActions.at(static_cast<size_t>(at));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BaseAction> get_(const std::string &name)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BaseAction> result;
|
||||||
if (AvailableActions.empty())
|
if (AvailableActions.empty())
|
||||||
populateActions();
|
populateActions();
|
||||||
for (const auto &action : AvailableActions)
|
for (const auto &action : AvailableActions)
|
||||||
{
|
{
|
||||||
if (action->name() == name)
|
if (action->name() == name)
|
||||||
{
|
{
|
||||||
result = action.get();
|
result = action;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
BaseAction &get(Type at);
|
BaseAction &get(Type at);
|
||||||
BaseAction *get(const std::string &name);
|
|
||||||
|
std::shared_ptr<BaseAction> get_(Type at);
|
||||||
|
std::shared_ptr<BaseAction> get_(const std::string &name);
|
||||||
|
|
||||||
struct Dummy: BaseAction
|
struct Dummy: BaseAction
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,13 +134,13 @@ NC::Key::Type stringToKey(const std::string &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
std::shared_ptr<Actions::BaseAction> parseActionLine(const std::string &line, F error)
|
||||||
{
|
{
|
||||||
Actions::BaseAction *result = 0;
|
std::shared_ptr<Actions::BaseAction> result;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (; i < line.size() && !isspace(line[i]); ++i) { }
|
for (; i < line.size() && !isspace(line[i]); ++i) { }
|
||||||
if (i == line.size()) // only action name
|
if (i == line.size()) // only action name
|
||||||
result = Actions::get(line);
|
result = Actions::get_(line);
|
||||||
else // there is something else
|
else // there is something else
|
||||||
{
|
{
|
||||||
std::string action_name = line.substr(0, i);
|
std::string action_name = line.substr(0, i);
|
||||||
@@ -149,9 +149,11 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
// push single character into input queue
|
// push single character into input queue
|
||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
NC::Key::Type k = stringToSpecialKey(arg);
|
NC::Key::Type k = stringToSpecialKey(arg);
|
||||||
auto queue = std::vector<NC::Key::Type>{ k };
|
|
||||||
if (k != NC::Key::None)
|
if (k != NC::Key::None)
|
||||||
result = new Actions::PushCharacters(&Global::wFooter, std::move(queue));
|
result = std::static_pointer_cast<Actions::BaseAction>(
|
||||||
|
std::make_shared<Actions::PushCharacters>(
|
||||||
|
&Global::wFooter,
|
||||||
|
std::vector<NC::Key::Type>{k}));
|
||||||
else
|
else
|
||||||
error() << "invalid character passed to push_character: '" << arg << "'\n";
|
error() << "invalid character passed to push_character: '" << arg << "'\n";
|
||||||
}
|
}
|
||||||
@@ -161,11 +163,13 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
if (!arg.empty())
|
if (!arg.empty())
|
||||||
{
|
{
|
||||||
std::vector<NC::Key::Type> queue(arg.begin(), arg.end());
|
|
||||||
// if char is signed, erase 1s from char -> int conversion
|
// if char is signed, erase 1s from char -> int conversion
|
||||||
for (auto it = arg.begin(); it != arg.end(); ++it)
|
for (auto it = arg.begin(); it != arg.end(); ++it)
|
||||||
*it &= 0xff;
|
*it &= 0xff;
|
||||||
result = new Actions::PushCharacters(&Global::wFooter, std::move(queue));
|
result = std::static_pointer_cast<Actions::BaseAction>(
|
||||||
|
std::make_shared<Actions::PushCharacters>(
|
||||||
|
&Global::wFooter,
|
||||||
|
std::vector<NC::Key::Type>{arg.begin(), arg.end()}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error() << "empty argument passed to push_characters\n";
|
error() << "empty argument passed to push_characters\n";
|
||||||
@@ -176,7 +180,8 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
ScreenType screen_type = stringToScreenType(arg);
|
ScreenType screen_type = stringToScreenType(arg);
|
||||||
if (screen_type != ScreenType::Unknown)
|
if (screen_type != ScreenType::Unknown)
|
||||||
result = new Actions::RequireScreen(screen_type);
|
result = std::static_pointer_cast<Actions::BaseAction>(
|
||||||
|
std::make_shared<Actions::RequireScreen>(screen_type));
|
||||||
else
|
else
|
||||||
error() << "unknown screen passed to require_screen: '" << arg << "'\n";
|
error() << "unknown screen passed to require_screen: '" << arg << "'\n";
|
||||||
}
|
}
|
||||||
@@ -184,9 +189,10 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
{
|
{
|
||||||
// require that given action is runnable
|
// require that given action is runnable
|
||||||
std::string arg = getEnclosedString(line, '"', '"', 0);
|
std::string arg = getEnclosedString(line, '"', '"', 0);
|
||||||
auto action = Actions::get(arg);
|
auto action = Actions::get_(arg);
|
||||||
if (action)
|
if (action)
|
||||||
result = new Actions::RequireRunnable(action);
|
result = std::static_pointer_cast<Actions::BaseAction>(
|
||||||
|
std::make_shared<Actions::RequireRunnable>(action));
|
||||||
else
|
else
|
||||||
error() << "unknown action passed to require_runnable: '" << arg << "'\n";
|
error() << "unknown action passed to require_runnable: '" << arg << "'\n";
|
||||||
}
|
}
|
||||||
@@ -194,7 +200,8 @@ Actions::BaseAction *parseActionLine(const std::string &line, F error)
|
|||||||
{
|
{
|
||||||
std::string command = getEnclosedString(line, '"', '"', 0);
|
std::string command = getEnclosedString(line, '"', '"', 0);
|
||||||
if (!command.empty())
|
if (!command.empty())
|
||||||
result = new Actions::RunExternalCommand(std::move(command));
|
result = std::static_pointer_cast<Actions::BaseAction>(
|
||||||
|
std::make_shared<Actions::RunExternalCommand>(std::move(command)));
|
||||||
else
|
else
|
||||||
error() << "empty command passed to run_external_command\n";
|
error() << "empty command passed to run_external_command\n";
|
||||||
}
|
}
|
||||||
@@ -472,11 +479,11 @@ void BindingsConfiguration::generateDefaults()
|
|||||||
if (notBound(k = stringToKey("up")))
|
if (notBound(k = stringToKey("up")))
|
||||||
bind(k, Actions::Type::ScrollUp);
|
bind(k, Actions::Type::ScrollUp);
|
||||||
if (notBound(k = stringToKey("shift-up")))
|
if (notBound(k = stringToKey("shift-up")))
|
||||||
bind(k, Binding::ActionChain({ &Actions::get(Actions::Type::SelectItem), &Actions::get(Actions::Type::ScrollUp) }));
|
bind(k, Binding::ActionChain({Actions::get_(Actions::Type::SelectItem), Actions::get_(Actions::Type::ScrollUp)}));
|
||||||
if (notBound(k = stringToKey("down")))
|
if (notBound(k = stringToKey("down")))
|
||||||
bind(k, Actions::Type::ScrollDown);
|
bind(k, Actions::Type::ScrollDown);
|
||||||
if (notBound(k = stringToKey("shift-down")))
|
if (notBound(k = stringToKey("shift-down")))
|
||||||
bind(k, Binding::ActionChain({ &Actions::get(Actions::Type::SelectItem), &Actions::get(Actions::Type::ScrollDown) }));
|
bind(k, Binding::ActionChain({Actions::get_(Actions::Type::SelectItem), Actions::get_(Actions::Type::ScrollDown)}));
|
||||||
if (notBound(k = stringToKey("[")))
|
if (notBound(k = stringToKey("[")))
|
||||||
bind(k, Actions::Type::ScrollUpAlbum);
|
bind(k, Actions::Type::ScrollUpAlbum);
|
||||||
if (notBound(k = stringToKey("]")))
|
if (notBound(k = stringToKey("]")))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ std::wstring keyToWString(const NC::Key::Type key);
|
|||||||
/// Represents either single action or chain of actions bound to a certain key
|
/// Represents either single action or chain of actions bound to a certain key
|
||||||
struct Binding
|
struct Binding
|
||||||
{
|
{
|
||||||
typedef std::vector<Actions::BaseAction *> ActionChain;
|
typedef std::vector<std::shared_ptr<Actions::BaseAction>> ActionChain;
|
||||||
|
|
||||||
template <typename ArgT>
|
template <typename ArgT>
|
||||||
Binding(ArgT &&actions_)
|
Binding(ArgT &&actions_)
|
||||||
@@ -41,7 +41,7 @@ struct Binding
|
|||||||
assert(!m_actions.empty());
|
assert(!m_actions.empty());
|
||||||
}
|
}
|
||||||
Binding(Actions::Type at)
|
Binding(Actions::Type at)
|
||||||
: Binding(ActionChain({&Actions::get(at)})) { }
|
: Binding(ActionChain({Actions::get_(at)})) { }
|
||||||
|
|
||||||
bool execute() const {
|
bool execute() const {
|
||||||
return std::all_of(m_actions.begin(), m_actions.end(),
|
return std::all_of(m_actions.begin(), m_actions.end(),
|
||||||
@@ -53,9 +53,10 @@ struct Binding
|
|||||||
return m_actions.size() == 1;
|
return m_actions.size() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions::BaseAction *action() const {
|
Actions::BaseAction &action() const {
|
||||||
assert(isSingle());
|
assert(isSingle());
|
||||||
return m_actions[0];
|
assert(m_actions[0] != nullptr);
|
||||||
|
return *m_actions[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionChain &actions() const {
|
const ActionChain &actions() const {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ std::string display_keys(const Actions::Type at)
|
|||||||
{
|
{
|
||||||
for (auto j = it->second.begin(); j != it->second.end(); ++j)
|
for (auto j = it->second.begin(); j != it->second.end(); ++j)
|
||||||
{
|
{
|
||||||
if (j->isSingle() && j->action()->type() == at)
|
if (j->isSingle() && j->action().type() == at)
|
||||||
{
|
{
|
||||||
skey = keyToWString(it->first);
|
skey = keyToWString(it->first);
|
||||||
if (!skey.empty())
|
if (!skey.empty())
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ void PushCharacters::run()
|
|||||||
(*m_window)->pushChar(*it);
|
(*m_window)->pushChar(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequireRunnable::RequireRunnable(BaseAction *action)
|
RequireRunnable::RequireRunnable(std::shared_ptr<BaseAction> action)
|
||||||
: BaseAction(Type::MacroUtility, "require_runnable")
|
: BaseAction(Type::MacroUtility, "require_runnable")
|
||||||
, m_action(action)
|
, m_action(std::move(action))
|
||||||
{
|
{
|
||||||
assert(m_action != nullptr);
|
assert(m_action != nullptr);
|
||||||
m_name += " \"";
|
m_name += " \"";
|
||||||
@@ -75,7 +75,7 @@ bool RequireScreen::canBeRun()
|
|||||||
return Global::myScreen->type() == m_screen_type;
|
return Global::myScreen->type() == m_screen_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunExternalCommand::RunExternalCommand(std::string command)
|
RunExternalCommand::RunExternalCommand(std::string &&command)
|
||||||
: BaseAction(Type::MacroUtility, "run_external_command")
|
: BaseAction(Type::MacroUtility, "run_external_command")
|
||||||
, m_command(std::move(command))
|
, m_command(std::move(command))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ private:
|
|||||||
|
|
||||||
struct RequireRunnable: BaseAction
|
struct RequireRunnable: BaseAction
|
||||||
{
|
{
|
||||||
RequireRunnable(BaseAction *action);
|
RequireRunnable(std::shared_ptr<BaseAction> action);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool canBeRun() override;
|
virtual bool canBeRun() override;
|
||||||
virtual void run() override { }
|
virtual void run() override { }
|
||||||
|
|
||||||
BaseAction *m_action;
|
std::shared_ptr<BaseAction> m_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RequireScreen: BaseAction
|
struct RequireScreen: BaseAction
|
||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
|
|
||||||
struct RunExternalCommand: BaseAction
|
struct RunExternalCommand: BaseAction
|
||||||
{
|
{
|
||||||
RunExternalCommand(std::string command);
|
RunExternalCommand(std::string &&command);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|||||||
@@ -207,8 +207,6 @@ int main(int argc, char **argv)
|
|||||||
if (!key_pressed)
|
if (!key_pressed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Statusbar::print(ToString(keyToWString(input)));
|
|
||||||
|
|
||||||
// The reason we want to update timer here is that if the timer is updated
|
// The reason we want to update timer here is that if the timer is updated
|
||||||
// in Status::trace, then Key::read usually blocks for 500ms and if key is
|
// in Status::trace, then Key::read usually blocks for 500ms and if key is
|
||||||
// pressed 400ms after Key::read was called, we end up with Timer that is
|
// pressed 400ms after Key::read was called, we end up with Timer that is
|
||||||
|
|||||||
Reference in New Issue
Block a user