actions: use shared_ptr to store actions

This commit is contained in:
Andrzej Rybczak
2016-12-07 19:02:47 +01:00
parent 59197f23d0
commit 56cb940a12
8 changed files with 47 additions and 35 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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