| 
									
										
										
										
											2016-08-23 17:21:35 +03:00
										 |  |  | # Features / Actions
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  | The Feature / Action couple is meta-programming library that helps with: | 
					
						
							|  |  |  | - extending and calling methods (Actions) on object inheritance chains | 
					
						
							|  |  |  | - managing and applying sets of methods (Features) to objects (a-la _mixin_) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 17:21:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Actions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Actions are an extension to the JavaScript object model tailored for | 
					
						
							|  |  |  | a set of specific tasks. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:42:38 +03:00
										 |  |  | By design this tool-set promotes a _cooperative_ model and makes it | 
					
						
							|  |  |  | hard to change/modify existing signatures / _contracts_ in _extending_  | 
					
						
							|  |  |  | code. | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:42:38 +03:00
										 |  |  | ### Functionality:
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:28:06 +03:00
										 |  |  | - **Call _extended_ actions automatically**   | 
					
						
							|  |  |  |   All actions (methods) in a chain are guaranteed to get called if the  | 
					
						
							|  |  |  |   action is called. | 
					
						
							|  |  |  | - **Thread arguments up the call chain**   | 
					
						
							|  |  |  |   All actions in a chain will get the set of arguments passed to the  | 
					
						
							|  |  |  |   action when called. | 
					
						
							|  |  |  | - **Thread the return value down the call chain**   | 
					
						
							|  |  |  |   The return value will get passed through all the actions in a chain  | 
					
						
							|  |  |  |   before returning to the action caller. | 
					
						
							| 
									
										
										
										
											2016-08-23 18:42:38 +03:00
										 |  |  | - **Organise and apply actions to objects** | 
					
						
							| 
									
										
										
										
											2016-08-23 18:28:06 +03:00
										 |  |  | - **Unified way to document actions** | 
					
						
							|  |  |  | - **Introspection and inspection API** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:42:38 +03:00
										 |  |  | ### Restrictions comparing to native JavaScript:
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  | - **No method shadowing**   | 
					
						
							|  |  |  |   The _extending_ action can not "shadow" the _extended_ action in a  | 
					
						
							| 
									
										
										
										
											2016-08-23 18:10:59 +03:00
										 |  |  |   non destructive manner (e.g. via a `throw`), all actions in a chain are  | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  |   guaranteed to be called, unless a fatal error condition. | 
					
						
							|  |  |  | - **No argument shadowing**   | 
					
						
							|  |  |  |   The _extending_ has access to all the arguments that the user passed | 
					
						
							|  |  |  |   but can not modify or reformat them before the _extended_ action gets | 
					
						
							|  |  |  |   them. | 
					
						
							|  |  |  | - **No return shadowing**   | 
					
						
							|  |  |  |   The _extending_ action can not replace the object returned by the  | 
					
						
							| 
									
										
										
										
											2016-08-23 18:10:59 +03:00
										 |  |  |   _extended_ action, though it can _cooperatively_ update/modify it if  | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  |   needed | 
					
						
							| 
									
										
										
										
											2016-08-23 18:28:06 +03:00
										 |  |  | - **Single return point**   | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  |   Only the _root_ action can return a value, any other returns by  | 
					
						
							|  |  |  |   _extending_ actions are ignored | 
					
						
							| 
									
										
										
										
											2016-08-23 18:28:06 +03:00
										 |  |  | - **Return `this` by default** | 
					
						
							| 
									
										
										
										
											2016-08-23 17:21:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:10:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 18:42:38 +03:00
										 |  |  |   <action-set>.getHandlerDocStr(<action-name>) | 
					
						
							| 
									
										
										
										
											2016-08-23 17:25:55 +03:00
										 |  |  |       -> 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 17:21:35 +03:00
										 |  |  | ## Features
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 18:04:43 +03:00
										 |  |  | Features is a module that helps build _features_ out of sets of actions | 
					
						
							|  |  |  | and manage sets of features according to external criteria and  | 
					
						
							|  |  |  | feature-feature dependencies. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Goals:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | XXX | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### The main entities:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **Feature** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | XXX | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **FeatureSet (Features)** | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 17:21:35 +03:00
										 |  |  | XXX | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <!-- vim:set ts=4 sw=4 spell : --> |