Skip to content

Commit

Permalink
feat: Add new methods to CommandStorage to support more arguments (#3035
Browse files Browse the repository at this point in the history
)

Added new **addCommand4** and **addCommand5** methods to the
_CommandStorage_ class from the Jenny package.
  • Loading branch information
frantovar committed Feb 14, 2024
1 parent d2e62bd commit 2192262
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 4 deletions.
8 changes: 7 additions & 1 deletion doc/other_modules/jenny/runtime/command_storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In order to register a function as a yarn command, the function must satisfy sev
`<<walk>>`, `<<moveCamera>>`, or `<<prompt>>`.
- The function's arguments must be of types that are known to Yarn: `String`, `num`, `int`,
`double`, or `bool`. All arguments must be positional, with no defaults.
- In order to register the function, use methods `addCommand0()` ... `addCommand3()`, according to
- In order to register the function, use methods `addCommand0()` ... `addCommand5()`, according to
the number of function's arguments.
- If the function's signature has 1 or more booleans at the end, then those arguments will be
considered optional and will default to `false`.
Expand All @@ -38,6 +38,12 @@ In order to register a function as a yarn command, the function must satisfy sev
**addCommand3**(`String name`, `FutureOr<void> Function(T1, T2, T3) fn`)
: Registers a three-argument function `fn` as the command `name`.

**addCommand4**(`String name`, `FutureOr<void> Function(T1, T2, T3, T4) fn`)
: Registers a four-argument function `fn` as the command `name`.

**addCommand5**(`String name`, `FutureOr<void> Function(T1, T2, T3, T4, T5) fn`)
: Registers a five-argument function `fn` as the command `name`.

**addOrphanedCommand**(`name`)
: Registers a command `name` which is not backed by any Dart function. Such command will still be
delivered to [DialogueView]s via the `onCommand()` callback, but its arguments will not be parsed.
Expand Down
44 changes: 41 additions & 3 deletions packages/flame_jenny/jenny/lib/src/command_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import 'package:meta/meta.dart';
/// YarnProject.
///
/// This repository is populated by the user, using commands [addCommand0],
/// [addCommand1], [addCommand2], [addCommand3], and [addOrphanedCommand],
/// depending on the arity of the function that needs to be invoked. All user-
/// defined commands need to be declared before parsing any Yarn scripts.
/// [addCommand1], [addCommand2], [addCommand3], [addCommand4], [addCommand5],
/// and [addOrphanedCommand], depending on the arity of the function
/// that needs to be invoked. All user-defined commands need to be declared
/// before parsing any Yarn scripts.
class CommandStorage {
CommandStorage() : _commands = {};

Expand Down Expand Up @@ -58,6 +59,43 @@ class CommandStorage {
);
}

/// Registers a 4-arguments function [fn] as a custom yarn command [name].
void addCommand4<T1, T2, T3, T4>(
String name,
FutureOr<void> Function(T1, T2, T3, T4) fn,
) {
_checkName(name);
_commands[name] = _Cmd(
name,
[T1, T2, T3, T4],
(List args) => fn(
args[0] as T1,
args[1] as T2,
args[2] as T3,
args[3] as T4,
),
);
}

/// Registers a 5-arguments function [fn] as a custom yarn command [name].
void addCommand5<T1, T2, T3, T4, T5>(
String name,
FutureOr<void> Function(T1, T2, T3, T4, T5) fn,
) {
_checkName(name);
_commands[name] = _Cmd(
name,
[T1, T2, T3, T4, T5],
(List args) => fn(
args[0] as T1,
args[1] as T2,
args[2] as T3,
args[3] as T4,
args[4] as T5,
),
);
}

/// Registers a command [name] which is not backed by any Dart function.
/// Instead, this command will be delivered directly to the dialogue views.
void addOrphanedCommand(String name) {
Expand Down
71 changes: 71 additions & 0 deletions packages/flame_jenny/jenny/test/command_storage_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,77 @@ void main() {
);
});

test('A four-argument command', () {
num value1 = 0;
num value2 = 0;
num value3 = 0;
num value4 = 0;
final storage = CommandStorage();
storage.addCommand4('four', (num w, num x, num y, num z) {
value1 = w;
value2 = x;
value3 = y;
value4 = z;
});
expect(storage.hasCommand('four'), true);

void check(String args, num v1, num v2, num v3, num v4) {
storage.runCommand(UserDefinedCommand('four', LineContent(args)));
expect(value1, v1);
expect(value2, v2);
expect(value3, v3);
expect(value4, v4);
}

check('1 2 3 4', 1, 2, 3, 4);
check('1.1 2.2 3.3 4.4', 1.1, 2.2, 3.3, 4.4);
check('Infinity -0.0 333 1.2', double.infinity, 0, 333, 1.2);
expect(
() => check('0 0 0 error', 0, 0, 0, 0),
hasTypeError(
'TypeError: Argument 4 for command <<four>> has value "error", '
'which is not numeric',
),
);
});

test('A five-argument command', () {
num value1 = 0;
num value2 = 0;
num value3 = 0;
num value4 = 0;
num value5 = 0;
final storage = CommandStorage();
storage.addCommand5('five', (num v, num w, num x, num y, num z) {
value1 = v;
value2 = w;
value3 = x;
value4 = y;
value5 = z;
});
expect(storage.hasCommand('five'), true);

void check(String args, num v1, num v2, num v3, num v4, num v5) {
storage.runCommand(UserDefinedCommand('five', LineContent(args)));
expect(value1, v1);
expect(value2, v2);
expect(value3, v3);
expect(value4, v4);
expect(value5, v5);
}

check('1 2 3 4 5', 1, 2, 3, 4, 5);
check('1.1 2.2 3.3 4.4 5.5', 1.1, 2.2, 3.3, 4.4, 5.5);
check('Infinity -0.0 333 1.2 -2', double.infinity, 0, 333, 1.2, -2);
expect(
() => check('0 0 0 0 error', 0, 0, 0, 0, 0),
hasTypeError(
'TypeError: Argument 5 for command <<five>> has value "error", '
'which is not numeric',
),
);
});

test('Command with trailing booleans', () {
var value1 = false;
var value2 = false;
Expand Down

0 comments on commit 2192262

Please sign in to comment.