2016-08-23 17:21:35 +03:00
|
|
|
# Features / Actions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Actions
|
|
|
|
|
|
|
|
|
|
Actions are an extension to the JavaScript object model tailored for
|
|
|
|
|
a set of specific tasks.
|
|
|
|
|
|
|
|
|
|
### Goals:
|
2016-08-23 17:25:55 +03:00
|
|
|
- provide a unified mechanism to define and manage user API's for
|
|
|
|
|
use in UI-hooks, keyboard mappings, scripting, ... etc.
|
|
|
|
|
- a means to generate configuration UI's
|
|
|
|
|
- a means to generate documentation
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
### The main entities:
|
|
|
|
|
|
|
|
|
|
**Action set**
|
|
|
|
|
- an object containing a number of actions,
|
2016-08-23 17:31:06 +03:00
|
|
|
- optionally, directly or indirectly inherited from `MetaActions`
|
2016-08-23 17:21:35 +03:00
|
|
|
and/or other action sets,
|
2016-08-23 17:31:06 +03:00
|
|
|
- the action handlers are bound relative to it (`._action_handlers`)
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
**Action**
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
+ pre + pre + + post + post +
|
|
|
|
|
Action event handler: o-------x o-------x
|
|
|
|
|
v ^
|
|
|
|
|
Actions o-------x o-------x
|
|
|
|
|
v ^
|
|
|
|
|
Root Action o---|---x
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
- a method, created by `Action(..)`,
|
2016-08-23 17:21:35 +03:00
|
|
|
- calls all the shadowed/overloaded actions in the inheritance
|
|
|
|
|
chain in sequence implicitly,
|
|
|
|
|
NOTE: there is no way to prevent an action in the chain from
|
|
|
|
|
running, this is by design, i.e. no way to fully shadow.
|
|
|
|
|
- actions that do not shadow anything are called root actions.
|
|
|
|
|
- returns the action set by default (for call chaining),
|
|
|
|
|
- the base/root action can return any value.
|
|
|
|
|
NOTE: if undefined is returned, it will be replaced by the
|
|
|
|
|
action context/action set.
|
|
|
|
|
NOTE: there is no distinction between root and other actions
|
|
|
|
|
other than that root action's return values are not
|
|
|
|
|
ignored.
|
|
|
|
|
- can consist of two parts: the first is called before the
|
|
|
|
|
shadowed action (pre-callback) and the second after (post-callback).
|
|
|
|
|
- post-callback has access to the return value and can modify it
|
|
|
|
|
but not replace it.
|
|
|
|
|
- can be bound to, a-la an event, calling the handlers when it is
|
|
|
|
|
called,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Action (event) handler**
|
|
|
|
|
- a function,
|
|
|
|
|
- can be bound to run before and/or after the action itself,
|
|
|
|
|
- is local to an action set it was bound via,
|
|
|
|
|
- when an action is triggered from an action set, all the pre
|
|
|
|
|
handlers in its inheritance chain will be called before the
|
|
|
|
|
respective actions they are bound to and all the post handlers
|
|
|
|
|
are called directly after.
|
|
|
|
|
- pre handlers are passed the same arguments the original actions
|
|
|
|
|
got when it was called.
|
|
|
|
|
- post action handlers will get the root action result as first
|
|
|
|
|
argument succeeded by the action arguments.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### The action system main protocols:
|
|
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
1. Documentation generation and introspection (`MetaActions`)
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
```
|
|
|
|
|
<action>.toString()
|
|
|
|
|
-> code of original action function
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
<action-set>.getDoc()
|
|
|
|
|
<action-set>.getDoc(<action-name>[, ..])
|
|
|
|
|
-> dict of action-name, doc
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
<action-set>.a.getHandlerDocStr(<action-name>)
|
|
|
|
|
-> formated string of action handlers
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
<action-set>.actions
|
|
|
|
|
-> list of action names
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
<action-set>.length
|
|
|
|
|
-> number of actions
|
|
|
|
|
```
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
2. Event-like callbacks for actions (`MetaActions`, `Action`)
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
```
|
|
|
|
|
<action-set>.on('action', function(){ ... })
|
|
|
|
|
<action-set>.on('action.post', function(){ ... })
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
<action-set>.on('action.pre', function(){ ... })
|
|
|
|
|
```
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
3. A mechanism to define and extend already defined actions
|
2016-08-23 17:21:35 +03:00
|
|
|
This replaces / complements the standard JavaScript overloading
|
2016-08-23 17:31:06 +03:00
|
|
|
mechanisms (`Action`, `Actions`)
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
```
|
|
|
|
|
// Actions...
|
|
|
|
|
var X = Actions({
|
|
|
|
|
m: [function(){ console.log('m') }]
|
|
|
|
|
})
|
|
|
|
|
var O = Actions(X, {
|
|
|
|
|
m: [function(){
|
|
|
|
|
console.log('pre')
|
|
|
|
|
return function(res){
|
|
|
|
|
console.log('post')
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
})
|
|
|
|
|
```
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
**Notes:**
|
|
|
|
|
- what is done here is similar to calling `O.__proto__.m.call(..)`
|
2016-08-23 17:25:55 +03:00
|
|
|
but is implicit, and not dependant on the original containing
|
2016-08-23 17:31:06 +03:00
|
|
|
object name/reference (`O`), thus enabling an action to be
|
2016-08-23 17:25:55 +03:00
|
|
|
referenced and called from any object and still chain correctly.
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Secondary action protocols:
|
|
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
1. A mechanism to manually call the pre/post stages of an action
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
Pre phase...
|
|
|
|
|
```
|
|
|
|
|
<action>.pre(<context>)
|
|
|
|
|
<action>.pre(<context>, [<arg>, ..])
|
|
|
|
|
-> <call-data>
|
|
|
|
|
```
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
Post phase...
|
|
|
|
|
```
|
|
|
|
|
<action>.post(<context>, <call-data>)
|
|
|
|
|
-> <result>
|
|
|
|
|
```
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
This is internally used to implement the action call as well as the
|
|
|
|
|
chaining callbacks (see below).
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
All action protocol details apply.
|
2016-08-23 17:21:35 +03:00
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
**Notes:**
|
|
|
|
|
- there is not reliable way to call the post phase without first
|
2016-08-23 17:25:55 +03:00
|
|
|
calling the pre phase due to how the pre phase is defined (i.e.
|
|
|
|
|
pre phase functions can return post phase functions).
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
2. A mechanism to chain/wrap actions or an action and a function.
|
2016-08-23 17:21:35 +03:00
|
|
|
This enables us to call a callback or another action (inner) between
|
|
|
|
|
the root action's (outer) pre and post stages.
|
|
|
|
|
|
2016-08-23 17:25:55 +03:00
|
|
|
```
|
|
|
|
|
Outer action o-------x o-------x
|
|
|
|
|
v ^
|
|
|
|
|
Inner action/callback o---|---x
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
A trivial example:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
actionSet.someAction.chainApply(actionsSet,
|
|
|
|
|
function(){
|
|
|
|
|
// this gets run between someAction's pre and post
|
|
|
|
|
// stages...
|
|
|
|
|
},
|
|
|
|
|
args)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This is intended to implement protocols where a single action is
|
|
|
|
|
intended to act as a hook point (outer) and multiple different
|
|
|
|
|
implementations (inner) within a single action set can be used as
|
|
|
|
|
entry points.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
// Protocol root action (outer) definition...
|
|
|
|
|
protocolAction: [function(){}],
|
|
|
|
|
|
|
|
|
|
// Implementation actions (inner)...
|
|
|
|
|
implementationAction1: [function(){
|
|
|
|
|
return this.protocolAction.chainApply(this, function(){
|
|
|
|
|
// ...
|
|
|
|
|
}, ..)
|
|
|
|
|
}]
|
|
|
|
|
|
|
|
|
|
implementationAction2: [function(){
|
|
|
|
|
return this.protocolAction.chainApply(this, function(){
|
|
|
|
|
// ...
|
|
|
|
|
}, ..)
|
|
|
|
|
}]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Now calling any of the 'implementation' actions will execute code
|
|
|
|
|
in the following order:
|
|
|
|
|
1. pre phase of protocol action (outer)
|
|
|
|
|
2. implementation action (inner)
|
|
|
|
|
3. post phase of protocol action (outer)
|
|
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
**Notes:**
|
|
|
|
|
- this will not affect to protocol/signature of the outer action
|
2016-08-23 17:25:55 +03:00
|
|
|
in any way.
|
2016-08-23 17:31:06 +03:00
|
|
|
- both the inner and outer actions will get passed the same
|
2016-08-23 17:25:55 +03:00
|
|
|
arguments.
|
2016-08-23 17:31:06 +03:00
|
|
|
- another use-case is testing/debugging actions.
|
|
|
|
|
- this is effectively the inside-out of normal action overloading.
|
|
|
|
|
- there is intentionally no shorthand for this feature, to avoid
|
2016-08-23 17:25:55 +03:00
|
|
|
confusion and to discourage the use of this feature unless
|
|
|
|
|
really necessary.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. `.__call__` action / handler
|
2016-08-23 17:21:35 +03:00
|
|
|
|
|
|
|
|
This action if defined is called for every action called. It behaves
|
|
|
|
|
like any other action but with a fixed signature, it always receives
|
|
|
|
|
the action name as first argument and a list of action arguments as
|
|
|
|
|
the second arguments, and as normal a result on the post phase.
|
|
|
|
|
|
2016-08-23 17:31:06 +03:00
|
|
|
**Notes:**
|
|
|
|
|
- it is not necessary to define the actual action, binding to a
|
2016-08-23 17:21:35 +03:00
|
|
|
handler will also work.
|
2016-08-23 17:31:06 +03:00
|
|
|
- one should not call actions directly from within a __call__
|
2016-08-23 17:21:35 +03:00
|
|
|
handler as that will result in infinite recursion.
|
|
|
|
|
XXX need a way to prevent this...
|
2016-08-23 17:31:06 +03:00
|
|
|
- one should use this with extreme care as this will introduce
|
2016-08-23 17:21:35 +03:00
|
|
|
an overhead on all the actions if not done carefully.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
|
|
XXX
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- vim:set ts=4 sw=4 spell : -->
|