Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions example/bin/example_cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ Future<void> main(List<String> args) async {
/// exited already. This is useful to prevent Future chains from proceeding
/// after you've decided to exit.
Future<void> _flushThenExit(int status) {
return Future.wait<void>([
stdout.close(),
stderr.close(),
]).then<void>((_) => exit(status));
return Future.wait<void>([stdout.close(), stderr.close()])
.then<void>((_) => exit(status));
}
13 changes: 4 additions & 9 deletions example/lib/src/command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@ const description = 'Example for cli_completion';
/// {@endtemplate}
class ExampleCommandRunner extends CompletionCommandRunner<int> {
/// {@macro example_command_runner}
ExampleCommandRunner({
Logger? logger,
}) : _logger = logger ?? Logger(),
super(executableName, description) {
new({Logger? logger})
: _logger = logger ?? Logger(),
super(executableName, description) {
// Add root options and flags
argParser
..addFlag(
'rootFlag',
abbr: 'f',
help: 'A flag: in the root command',
)
..addFlag('rootFlag', abbr: 'f', help: 'A flag: in the root command')
..addOption('rootOption');

// Add sub commands
Expand Down
36 changes: 7 additions & 29 deletions example/lib/src/commands/some_commmand.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,19 @@ import 'package:mason_logger/mason_logger.dart';
/// receives all the common cases of option mapping: options, muilt-options,
/// flags and whatnot
class SomeCommand extends Command<int> {
SomeCommand(this._logger) {
new(this._logger) {
argParser
..addOption(
'discrete',
abbr: 'd',
help: 'A discrete option with "allowed" values (mandatory)',
allowed: ['foo', 'bar', 'faa'],
aliases: [
'allowed',
'defined-values',
],
allowedHelp: {
'foo': 'foo help',
'bar': 'bar help',
'faa': 'faa help',
},
aliases: ['allowed', 'defined-values'],
allowedHelp: {'foo': 'foo help', 'bar': 'bar help', 'faa': 'faa help'},
mandatory: true,
)
..addSeparator('yay')
..addOption(
'hidden',
hide: true,
help: 'A hidden option',
)
..addOption('hidden', hide: true, help: 'A hidden option')
..addOption(
'continuous', // intentionally, this one does not have an abbr
help: 'A continuous option: any value is allowed',
Expand Down Expand Up @@ -62,16 +51,8 @@ class SomeCommand extends Command<int> {
abbr: 'n',
help: 'An continuous option that can be passed multiple times',
)
..addFlag(
'hiddenflag',
hide: true,
help: 'A hidden flag',
)
..addFlag(
'flag',
abbr: 'f',
aliases: ['itIsAFlag'],
)
..addFlag('hiddenflag', hide: true, help: 'A hidden flag')
..addFlag('flag', abbr: 'f', aliases: ['itIsAFlag'])
..addFlag(
'inverseflag',
abbr: 'i',
Expand All @@ -95,10 +76,7 @@ class SomeCommand extends Command<int> {
String get name => 'some_command';

@override
List<String> get aliases => [
'disguised:some_commmand',
'melon',
];
List<String> get aliases => ['disguised:some_commmand', 'melon'];

@override
Future<int> run() async {
Expand Down
4 changes: 2 additions & 2 deletions example/lib/src/commands/some_other_commmand.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:mason_logger/mason_logger.dart';

/// A command that only has a sub command
class SomeOtherCommand extends Command<int> {
SomeOtherCommand(this._logger) {
new(this._logger) {
addSubcommand(_SomeSubCommand(_logger));
}

Expand All @@ -19,7 +19,7 @@ class SomeOtherCommand extends Command<int> {
/// A command under [SomeOtherCommand] that does not receive options and read
/// the "rest" field from arg results
class _SomeSubCommand extends Command<int> {
_SomeSubCommand(this._logger) {
new(this._logger) {
argParser.addFlag(
'flag',
help: 'a flag just to show we are in the subcommand',
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies:
dev_dependencies:
mocktail: ^1.0.4
test: ^1.25.8
very_good_analysis: ^10.3.0
very_good_analysis: ^11.0.0

executables:
example_cli:
97 changes: 25 additions & 72 deletions example/test/integration/completion_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,11 @@ void main() {
});

test('totally written option', () async {
await expectLater(
'example_cli --rootflag',
suggests(noSuggestions),
);
await expectLater('example_cli --rootflag', suggests(noSuggestions));
});

test('totally written option (abbr)', () async {
await expectLater(
'example_cli -f',
suggests(noSuggestions),
);
await expectLater('example_cli -f', suggests(noSuggestions));
});
});

Expand Down Expand Up @@ -147,9 +141,7 @@ void main() {
test('completes only one sub command', () async {
await expectLater(
'example_cli some_comm',
suggests({
'some_command': 'This is help for some_command',
}),
suggests({'some_command': 'This is help for some_command'}),
);
});
});
Expand All @@ -158,9 +150,7 @@ void main() {
test('completes sub commands aliases when typed', () async {
await expectLater(
'example_cli mel',
suggests({
'melon': 'This is help for some_command',
}),
suggests({'melon': 'This is help for some_command'}),
);
});

Expand Down Expand Up @@ -245,16 +235,12 @@ void main() {
);
});

test(
'options in between',
() async {
await expectLater(
'example_cli -f --rootOption yay some_command',
suggests(allOptionsInThisLevel),
);
},
tags: 'known-issues',
);
test('options in between', () async {
await expectLater(
'example_cli -f --rootOption yay some_command',
suggests(allOptionsInThisLevel),
);
}, tags: 'known-issues');

test('lots of spaces in between', () async {
await expectLater(
Expand All @@ -266,10 +252,7 @@ void main() {

group('empty (aliases)', () {
test('shows same options for alias sub command', () async {
await expectLater(
'example_cli melon',
suggests(allOptionsInThisLevel),
);
await expectLater('example_cli melon', suggests(allOptionsInThisLevel));
});

test('shows same options for alias sub command 2', () async {
Expand Down Expand Up @@ -391,21 +374,14 @@ void main() {
test('suggest possible options', () async {
await expectLater(
'example_cli some_command --discrete ',
suggests({
'foo': 'foo help',
'bar': 'bar help',
'faa': 'faa help',
}),
suggests({'foo': 'foo help', 'bar': 'bar help', 'faa': 'faa help'}),
);
});

test('suggest matching options', () async {
await expectLater(
'example_cli some_command --discrete f',
suggests({
'foo': 'foo help',
'faa': 'faa help',
}),
suggests({'foo': 'foo help', 'faa': 'faa help'}),
);
});

Expand All @@ -424,11 +400,7 @@ void main() {
test('suggest matching options for alias option when typed', () async {
await expectLater(
'example_cli some_command --allowed ',
suggests({
'foo': 'foo help',
'bar': 'bar help',
'faa': 'faa help',
}),
suggests({'foo': 'foo help', 'bar': 'bar help', 'faa': 'faa help'}),
);
});

Expand Down Expand Up @@ -462,11 +434,7 @@ void main() {
test('suggest possible options', () async {
await expectLater(
'example_cli some_command -d ',
suggests({
'foo': 'foo help',
'bar': 'bar help',
'faa': 'faa help',
}),
suggests({'foo': 'foo help', 'bar': 'bar help', 'faa': 'faa help'}),
);
});

Expand All @@ -484,20 +452,14 @@ void main() {
test('suggest matching options', () async {
await expectLater(
'example_cli some_command -d f',
suggests({
'foo': 'foo help',
'faa': 'faa help',
}),
suggests({'foo': 'foo help', 'faa': 'faa help'}),
);
});

test('suggest matching options in a joined form', () async {
await expectLater(
'example_cli some_command -df',
suggests({
'-dfoo': 'foo help',
'-dfaa': 'faa help',
}),
suggests({'-dfoo': 'foo help', '-dfaa': 'faa help'}),
);
});
});
Expand Down Expand Up @@ -626,16 +588,12 @@ void main() {
);
});

test(
'include option after it is specified (abbr joined)',
() async {
await expectLater(
'example_cli some_command -nyeahoo ',
suggests(allOptionsInThisLevel),
);
},
tags: 'known-issues',
);
test('include option after it is specified (abbr joined)', () async {
await expectLater(
'example_cli some_command -nyeahoo ',
suggests(allOptionsInThisLevel),
);
}, tags: 'known-issues');

test(
'include discrete multi option value after it is specified',
Expand Down Expand Up @@ -672,9 +630,7 @@ void main() {
test('partially written sub command', () async {
await expectLater(
'example_cli some_other_command sub',
suggests({
'subcommand': 'A sub command of some_other_command',
}),
suggests({'subcommand': 'A sub command of some_other_command'}),
);
});
});
Expand Down Expand Up @@ -721,10 +677,7 @@ void main() {

group('argument terminator bails', () {
test('between commands', () async {
await expectLater(
'example_cli -- some_command',
suggests(noSuggestions),
);
await expectLater('example_cli -- some_command', suggests(noSuggestions));
});

test('after commands', () async {
Expand Down
46 changes: 17 additions & 29 deletions example/test/integration/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,18 @@ import 'package:mocktail/mocktail.dart';

import 'package:test/test.dart';

class MockStdout extends Mock implements Stdout {}
class MockStdout extends Mock implements Stdout;

Matcher suggests(Map<String, String?> suggestions, {int? whenCursorIsAt}) =>
CliCompletionMatcher(
suggestions,
cursorIndex: whenCursorIsAt,
);
CliCompletionMatcher(suggestions, cursorIndex: whenCursorIsAt);

class CliCompletionMatcher extends CustomMatcher {
CliCompletionMatcher(
Map<String, String?> suggestions, {
this.cursorIndex,
}) : super(
'Completes with the expected suggestions',
'suggestions',
completion(suggestions),
);
new(Map<String, String?> suggestions, {this.cursorIndex})
: super(
'Completes with the expected suggestions',
'suggestions',
completion(suggestions),
);

final int? cursorIndex;

Expand All @@ -47,11 +42,7 @@ Map<String, String> prepareEnvForLineInput(String line, {int? cursorIndex}) {
}
return value;
});
return {
'COMP_LINE': line,
'COMP_POINT': '$cpoint',
'COMP_CWORD': '$cword',
};
return {'COMP_LINE': line, 'COMP_POINT': '$cpoint', 'COMP_CWORD': '$cword'};
}

Future<Map<String, String?>> runCompletionCommand(
Expand All @@ -74,17 +65,14 @@ Future<Map<String, String?>> runCompletionCommand(
map[res.first] = description;
});

await IOOverrides.runZoned(
stdout: () => stdout,
() async {
final commandRunner = ExampleCommandRunner()
..environmentOverride = {
'SHELL': '/foo/bar/zsh',
...prepareEnvForLineInput(line, cursorIndex: cursorIndex),
};
await commandRunner.run(['completion']);
},
);
await IOOverrides.runZoned(stdout: () => stdout, () async {
final commandRunner = ExampleCommandRunner()
..environmentOverride = {
'SHELL': '/foo/bar/zsh',
...prepareEnvForLineInput(line, cursorIndex: cursorIndex),
};
await commandRunner.run(['completion']);
});

return map;
}
Expand Down
Loading
Loading