<commit_before>Introduction
===

This little library provides a very simple and lightweight way for executing queued commands. `Commands` can be executed sequentially or concurrently. This is done by `CommandGroups` which in itself are `Commands`. This way `Commands` and `CommandGroups` can be nested at any depth. This can be used for scripted code execution like in game tutorials for example (tbd: reference tutorial script).

Installation
===

Tbd: Cocoapods

Usage
===

Implementing commands
---

Asynchronous commands
---

Executing several commands at once
---

Executing commands sequentially
---

Example
===

You can find an example application in the `MGCommandsExample` subfolder. Run the app in the simulator and start the command execution. 

The configured command groups looks like this:

	sequential
	{
		DelayCommand(1)
		DelayCommand(1)
		DelayCommand(1)
		PrintCommand("concurrent {")
		
		concurrent
		{
			DelayCommand(1)
			DelayCommand(1)
			DelayCommand(1)
		}
		
		PrintCommand("}")
		DelayCommand(1)
		DelayCommand(1)
		DelayCommand(1)
		PrintCommand("Finished")
	}<commit_msg>Improved documentation<commit_after>Introduction
===

This library provides a lightweight way for executing commands. `Commands` can be executed sequentially or concurrently. This is done by command groups which in itself are `Commands`. 

Because of that `Commands` and `CommandGroups` can be nested. This can be used for scripted code execution like in game tutorials for example (tbd: reference tutorial script).

Installation
===

Tbd: Cocoapods

Usage
===

There are two command types: synchronous (`MGCommand`) and asynchronous (`MGAsyncCommand`). Commands can then be executed all at once (`MGCommandGroup`) or one after the other (`MGSequentialCommandGroup`).

Synchronous command
---

A synchronous command needs to implement the `MGCommand` protocol. The `execute` method should contain the command logic. Here is a simple print command example:

```objective-c
@interface PrintCommand : NSObject <MGCommand>
{
	NSString *_message;
}

- (id)initWithMessage:(NSString *)message;

@end

@implementation PrintCommand

- (id)initWithMessage:(NSString *)message
{
	self = [super init];

	if (self)
	{
		_message = message;
	}

	return self;
}

- (void)execute
{
	NSLog(_message);
}

@end
```

Asynchronous command
---

Sometimes your command may need some more execution time. In that case you may want to use the `MGAsyncCommand`. This command will not finish until a callback method has been called. This callback method will be set by the parent `CommandGroup` before execution (see next paragraph). The following command example finishes after a given delay:

```objective-c
@interface DelayCommand : NSObject <MGAsyncCommand>
{
	NSTimeInterval _delayInSeconds;
}

@property (nonatomic, strong) CommandCallback callback;

- (id)initWithDelayInSeconds:(NSTimeInterval)aDelayInSeconds;

@end

@implementation DelayCommand

- (id)initWithDelayInSeconds:(NSTimeInterval)aDelayInSeconds
{
	self = [super init];

	if (self)
	{
		_delayInSeconds = aDelayInSeconds;
	}

	return self;
}

- (void)execute
{
	[self performSelector:@selector(finishAfterDelay)
			   withObject:nil
			   afterDelay:_delayInSeconds];
}

- (void)finishAfterDelay
{
	_callback();
}

@end
```

Executing several commands at once
---

Commands can be added to command groups (`MGCommandGroup`) which will then execute all commands. The command group itself implements the `MGAsyncCommand` protocol. It will finish it's own execution when all added commands have finished their own execution.

```objective-c
MGCommandGroup *commandGroup = [[MGCommandGroup alloc] init];

[commandGroup addCommand:[[DelayCommand alloc] initWithDelayInSeconds:1]];
[commandGroup addCommand:[[DelayCommand alloc] initWithDelayInSeconds:1]];
[commandGroup addCommand:[[DelayCommand alloc] initWithDelayInSeconds:1]];

commandGroup.callback = ^
{
	NSLog(@"execution finished");
};

[commandGroup execute];
```

Before calling the execute method on the command group, you can set a callback block. It will be executed when the command group execution finished. Note that the callbacks for added asynchronous commands will be automatically set by the group.

Executing commands sequentially
---

In case you want to have your commands being executed one after the other you can use the `MGSequentialCommandGroup`. The order you add the commands determines their execution order.

Example
===

You can find an example application in the `MGCommandsExample` subfolder. Run the app in the simulator and start the command execution. 

The configured command groups looks like this (pseudo code):

	sequential
	{
		DelayCommand(1)
		DelayCommand(1)
		DelayCommand(1)
		PrintCommand("concurrent {")
		
		concurrent
		{
			DelayCommand(1)
			DelayCommand(1)
			DelayCommand(1)
		}
		
		PrintCommand("}")
		DelayCommand(1)
		DelayCommand(1)
		DelayCommand(1)
		PrintCommand("Finished")
	}
{'fraction_non_alphanumeric': 0.08286061588330632, 'fraction_numerical': 0.0042544570502431114, 'mean_word_length': 4.926770708283313, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6452107', 'n_tokens_mistral': 1446, 'n_tokens_neox': 1335, 'n_words': 530}