Commands: finish CommandSetup helper (#1088)

this is a prerequisite for command instance management:
We have now an (almost) complete framework for writing actual
command definitions in practice, which will be registered automatically.

This could be complemented (future work) by a script in the build process
to regenerate proc/cmd.hpp based on the IDs of those automatic definitions.
This commit is contained in:
Fischlurch 2017-03-31 18:15:02 +02:00
parent e7d24febee
commit 95af930a71
5 changed files with 53 additions and 36 deletions

View file

@ -34,21 +34,18 @@
#include "lib/error.hpp"
//#include "lib/symbol.hpp"
#include "include/logging.h"
#include "include/lifecycle.h"
//#include "lib/format-string.hpp"
#include "proc/control/command-setup.hpp"
#include "proc/control/command-instance-manager.hpp"
#include "proc/control/command-def.hpp"
//#include "lib/format-string.hpp"
//#include "lib/util.hpp"
//#include <string>
#include <tuple>
#include <utility>
//using std::string;
using std::tuple;
using std::get;
using std::function;
@ -56,6 +53,7 @@ using std::move;
using lib::Symbol;
using lumiera::LifecycleHook;
using lumiera::ON_GLOBAL_INIT;
//using std::string;
//using util::cStr;
//using util::_Fmt;
@ -64,25 +62,27 @@ namespace proc {
namespace control {
namespace error = lumiera::error;
namespace { // implementation details of command setup...
namespace { // implementation details: storage for pending static command definitions...
using CmdDefEntry = std::tuple<Symbol, DefinitionClosure>;
std::deque<CmdDefEntry> pendingCmdDefinitions;
}//(End) implementation details
/** storage for.... */
CommandSetup::~CommandSetup() { }
/** Start a command setup for defining a Proc-Layer command with the given cmdID */
/** Start a command setup for defining a Proc-Layer command with the given cmdID
* @param cmdID the ID under with the new command will be registered
* @note after defining a static variable of type CommandSetup,
* a functor or lambda should be assigned, which then
* provides the actual setup of the CommandDef
*/
CommandSetup::CommandSetup(Symbol cmdID)
: cmdID_(cmdID)
{ }
@ -107,7 +107,7 @@ namespace control {
* reason for this is the fact that CommandDef rejects duplicate command definitions.
* Moreover, please note that invoking this operation at any point _after_ the
* lifecycle event ON_BASIC_INIT will likely have no effect at all, since the
* given closure will then just sit in the static queue and never be invoked.
* given closure will then just sit in the static queue and never be invoked.
*/
CommandSetup&
CommandSetup::operator= (DefinitionClosure definitionBlock)
@ -116,11 +116,11 @@ namespace control {
throw error::Invalid ("unbound function/closure provided for CommandSetup"
, error::LUMIERA_ERROR_BOTTOM_VALUE);
pendingCmdDefinitions.emplace_front (Symbol(cmdID_), move(definitionBlock));
pendingCmdDefinitions.emplace_front (cmdID_, move(definitionBlock));
return *this;
}
size_t
CommandSetup::pendingCnt()
{
@ -149,6 +149,9 @@ namespace control {
}
// emit dtors of embedded objects here....
CommandInstanceManager::~CommandInstanceManager() { }
@ -157,7 +160,7 @@ namespace control {
/** more to come here...*/
/* more to come here...*/

View file

@ -31,16 +31,14 @@
** the Session data must be performed by invoking such commands, a huge amount of individual command
** definitions need to be written eventually.
**
** The macro COMMAND_DEFINITION(name) allows to introduce a new definition with a single line,
** The macro COMMAND_DEFINITION(_NAME_) allows to introduce a new definition with a single line,
** followed by a code block, which actually ends up as the body of a lambda function, and receives
** the bare CommandDef as single argument with name `cmd`. The `name` argument of the macro ends up
** both stringified as the value of the command-ID, and as an identifier holding a new CommandSetup
** the bare CommandDef as single argument with name `cmd`. The `_NAME_` argument of the macro ends up
** both stringified as the value of the command-ID, and as an variable holding a new CommandSetup
** instance. It is assumed that a header with corresponding _declarations_ (the header \ref cmd.hpp)
** is included by all UI elements actually to use, handle and invoke commands towards the
** session-command-facade.h
**
** @todo WIP-WIP 3/2017 initial draft
**
** @see command-def.hpp
** @see command.hpp
** @see command-accessor.hpp
@ -56,7 +54,6 @@
#include "lib/error.hpp"
#include "proc/control/command.hpp"
#include "lib/symbol.hpp"
//#include "proc/common.hpp"
#include <functional>
#include <string>
@ -68,9 +65,7 @@ namespace proc {
namespace control {
using std::string;
// using lib::Symbol;
using lib::Symbol;
//using std::shared_ptr;
class CommandDef;
@ -79,7 +74,23 @@ namespace control {
/**
* @todo write type comment
* Marker and Helper for writing Proc-Layer Command definitions.
* Together with the Macro #COMMAND_DEFINITION, such definitions
* may be written statically, in DSL-style:
* - statically define a variable of type CommandSetup,
* with external linkage
* - the ctor argument is what will be used as command-ID
* - assign a functor, function or lambda to this variable,
* with the signature `void(CommandDef&)`
* - the argument passed to this functor will be the CommandDef
* about to be configured and registered. Thus, the body of the
* functor should use the member functions of CommandDef to setup
* the command's operation, state capturing and undo functions.
* - behind the scenes, a lumiera::LifecycleHook is scheduled
* to run ON_GLOBAL_INIT. When this hook is activated, all the
* lambdas assigned to all CommandSetup instances thus far will
* be invoked one by one. Which causes all those commands actually
* to be defined and configured for use with the session subsystem.
*/
class CommandSetup
{
@ -131,7 +142,7 @@ namespace control {
* and immediately be assigned by a lambda, whose body is what follows the macro invocation
*/
#define COMMAND_DEFINITION(_NAME_) \
CommandSetup _NAME_ = CommandSetup{STRINGIFY(_NAME_)} = [&](CommandDef& def)
CommandSetup _NAME_ = CommandSetup{STRINGIFY(_NAME_)} = [&](CommandDef& def)

View file

@ -3,7 +3,7 @@ TESTING "Component Test Suite: Proc-Layer controller" ./test-suite --group=contr
TEST "CommandBasic_test" CommandBasic_test <<END
TEST "Command Basics" CommandBasic_test <<END
return: 0
END
@ -117,6 +117,11 @@ return: 0
END
TEST "Command setup helper" CommandSetup_test <<END
return: 0
END
TEST "Dispatcher loop control logic" DispatcherLooper_test <<END
return: 0
END

View file

@ -31,25 +31,15 @@
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"
#include "lib/util.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/p.hpp"
//#include <cstdlib>
#include <string>
#include <regex>
//using std::rand;
namespace proc {
namespace cmd {
namespace test {
//using lib::time::Time;
//using lib::time::TimeVar;
//using lib::time::TimeValue;
//using lib::time::Offset;
using lib::Literal;
using std::string;
using std::regex;
@ -188,6 +178,7 @@ namespace test {
_Fmt pattern{" %d times."};
/** @test actually issue the definitions captured as side-effect of the preceding test. */
void
verify_DefinitionRegistration()
@ -213,6 +204,7 @@ namespace test {
com1.bind (string{"^(\\w+)"}, string{"No $1"});
com2.bind (uint(42));
CHECK (testString == "Ichthyostega wuz here");
com1();
CHECK (testString == "No Ichthyostega wuz here");

View file

@ -11678,7 +11678,12 @@
<linktarget COLOR="#584d79" DESTINATION="ID_341428100" ENDARROW="Default" ENDINCLINATION="1995;-1317;" ID="Arrow_ID_879741123" SOURCE="ID_1331796226" STARTARROW="None" STARTINCLINATION="334;-13;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1489196572055" ID="ID_339289633" MODIFIED="1489196577154" TEXT="Command-ID">
<node CREATED="1489196578470" ID="ID_1460242316" MODIFIED="1489196591032" TEXT="extensible ID anschauen"/>
<node CREATED="1489196578470" ID="ID_1460242316" MODIFIED="1490976980566" TEXT="extensible ID anschauen">
<icon BUILTIN="button_cancel"/>
</node>
<node CREATED="1490976981548" ID="ID_319912426" MODIFIED="1490977023076" TEXT="nein: es gen&#xfc;gen rein textuelle IDs">
<arrowlink DESTINATION="ID_119293304" ENDARROW="Default" ENDINCLINATION="183;-268;" ID="Arrow_ID_1691148413" STARTARROW="None" STARTINCLINATION="363;0;"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1489191252503" ID="ID_1621107057" MODIFIED="1489191308469" TEXT="#1090 Command access for UI-Elements">
@ -11814,7 +11819,8 @@
<node CREATED="1489717406447" ID="ID_1938762085" MODIFIED="1489717411690" TEXT="Bang sendet nur diese ID"/>
</node>
</node>
<node CREATED="1489717768805" HGAP="79" ID="ID_119293304" MODIFIED="1489718863072" TEXT="Entscheidung" VSHIFT="4">
<node CREATED="1489717768805" HGAP="79" ID="ID_119293304" MODIFIED="1490977023076" TEXT="Entscheidung" VSHIFT="4">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_119293304" ENDARROW="Default" ENDINCLINATION="183;-268;" ID="Arrow_ID_1691148413" SOURCE="ID_319912426" STARTARROW="None" STARTINCLINATION="363;0;"/>
<icon BUILTIN="yes"/>
<node CREATED="1489717797353" ID="ID_899130819" MODIFIED="1489717807068" TEXT="die ersten beiden sind un&#xf6;tig generisch"/>
<node CREATED="1489717807872" ID="ID_1209104496" MODIFIED="1489717818826" TEXT="wir bauen ohnehin den Command-Cycle fest ein"/>