-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fd8f906
commit 2de0abd
Showing
5 changed files
with
213 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export 'src/documentation_generator/documentation_generator.dart'; |
42 changes: 42 additions & 0 deletions
42
lib/src/documentation_generator/documentation_generator.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import '../../better_command_runner.dart'; | ||
|
||
class CommandDocumentationGenerator { | ||
final BetterCommandRunner commandRunner; | ||
|
||
CommandDocumentationGenerator(this.commandRunner); | ||
|
||
Map<String, String> generateMarkdown() { | ||
var commands = commandRunner.commands.values; | ||
|
||
var files = <String, String>{}; | ||
|
||
for (var command in commands) { | ||
StringBuffer markdown = StringBuffer(); | ||
markdown.writeln('## Usage\n'); | ||
|
||
if (command.argParser.options.isNotEmpty) { | ||
markdown.writeln('```console'); | ||
markdown.writeln(command.usage); | ||
markdown.writeln('```\n'); | ||
} | ||
|
||
if (command.subcommands.isNotEmpty) { | ||
var numberOfSubcommands = command.subcommands.length; | ||
markdown.writeln('### Sub commands\n'); | ||
for (var (i, subcommand) in command.subcommands.entries.indexed) { | ||
markdown.writeln('#### `${subcommand.key}`\n'); | ||
markdown.writeln('```console'); | ||
markdown.writeln(subcommand.value.usage); | ||
markdown.writeln('```'); | ||
if (i < numberOfSubcommands - 1) { | ||
markdown.writeln(); | ||
} | ||
} | ||
} | ||
|
||
files['${command.name}.md'] = markdown.toString(); | ||
} | ||
|
||
return files; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 168 additions & 0 deletions
168
test/documentation_generator/generate_markdown_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:args/command_runner.dart'; | ||
import 'package:cli_tools/cli_tools.dart'; | ||
import 'package:cli_tools/src/documentation_generator/documentation_generator.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
class AddSpiceCommand extends Command { | ||
@override | ||
final String name = 'add'; | ||
|
||
@override | ||
final String description = 'Add something to the spice mix'; | ||
|
||
AddSpiceCommand() { | ||
argParser.addOption('curry', help: 'Include curry in the spice mix.'); | ||
argParser.addOption('pepper', help: 'Include pepper in the spice mix.'); | ||
} | ||
|
||
@override | ||
void run() { | ||
// Command logic here | ||
} | ||
} | ||
|
||
class RemoveSpiceCommand extends Command { | ||
@override | ||
final String name = 'remove'; | ||
|
||
@override | ||
final String description = 'Remove something from the spice mix'; | ||
|
||
RemoveSpiceCommand() { | ||
argParser.addOption('curry', help: 'Remove curry from the spice mix.'); | ||
argParser.addOption('pepper', help: 'Remove pepper from the spice mix.'); | ||
} | ||
|
||
@override | ||
void run() {} | ||
} | ||
|
||
class AddVegetableCommand extends Command { | ||
@override | ||
final String name = 'add'; | ||
|
||
@override | ||
final String description = 'Add a vegetable to your dish.'; | ||
|
||
AddVegetableCommand() { | ||
argParser.addOption('carrot', help: 'Adds a fresh carrot to the dish.'); | ||
} | ||
|
||
@override | ||
void run() {} | ||
} | ||
|
||
class SpiceCommand extends BetterCommand { | ||
@override | ||
final String name = 'spice'; | ||
|
||
@override | ||
final String description = 'Modifies the spice mix in your dish.'; | ||
|
||
SpiceCommand() { | ||
addSubcommand(AddSpiceCommand()); | ||
addSubcommand(RemoveSpiceCommand()); | ||
} | ||
|
||
@override | ||
void run() {} | ||
} | ||
|
||
class VegetableCommand extends BetterCommand { | ||
@override | ||
final String name = 'vegetable'; | ||
|
||
@override | ||
final String description = 'Add or remove vegatables to your dish.'; | ||
|
||
VegetableCommand() { | ||
addSubcommand(AddVegetableCommand()); | ||
} | ||
|
||
@override | ||
void run() {} | ||
} | ||
|
||
void main() { | ||
group('Given commands when generating markdown', () { | ||
late Map<String, String> output; | ||
|
||
setUpAll(() async { | ||
var commandRunner = | ||
BetterCommandRunner('cookcli', 'A cli to create wonderful dishes.') | ||
..addCommand(SpiceCommand()) | ||
..addCommand(VegetableCommand()); | ||
var generator = CommandDocumentationGenerator(commandRunner); | ||
output = generator.generateMarkdown(); | ||
}); | ||
|
||
test('then outputs each command into a separate file', () { | ||
expect(output.keys, containsAll(['vegetable.md', 'spice.md'])); | ||
for (var file in output.entries) { | ||
File('docs/${file.key}').writeAsStringSync(file.value); | ||
} | ||
}); | ||
|
||
test('then output starts with the main command', () async { | ||
var vegetableCommandOutput = output['spice.md']; | ||
|
||
expect( | ||
vegetableCommandOutput, | ||
startsWith( | ||
'## Usage\n' | ||
'\n' | ||
'```console\n' | ||
'Modifies the spice mix in your dish.\n' | ||
'\n' | ||
'Usage: cookcli spice <subcommand> [arguments]\n' | ||
'-h, --help Print this usage information.\n' | ||
'\n' | ||
'Available subcommands:\n' | ||
' add Add something to the spice mix\n' | ||
' remove Remove something from the spice mix\n' | ||
'\n' | ||
'Run "cookcli help" to see global options.\n' | ||
'```\n' | ||
'\n', | ||
)); | ||
}); | ||
|
||
test('then output ends with the sub commands', () async { | ||
var vegetableCommandOutput = output['spice.md']; | ||
|
||
expect( | ||
vegetableCommandOutput, | ||
endsWith( | ||
'### Sub commands\n' | ||
'\n' | ||
'#### `add`\n' | ||
'\n' | ||
'```console\n' | ||
'Add something to the spice mix\n' | ||
'\n' | ||
'Usage: cookcli spice add [arguments]\n' | ||
'-h, --help Print this usage information.\n' | ||
' --curry Include curry in the spice mix.\n' | ||
' --pepper Include pepper in the spice mix.\n' | ||
'\n' | ||
'Run "cookcli help" to see global options.\n' | ||
'```\n' | ||
'\n' | ||
'#### `remove`\n' | ||
'\n' | ||
'```console\n' | ||
'Remove something from the spice mix\n' | ||
'\n' | ||
'Usage: cookcli spice remove [arguments]\n' | ||
'-h, --help Print this usage information.\n' | ||
' --curry Remove curry from the spice mix.\n' | ||
' --pepper Remove pepper from the spice mix.\n' | ||
'\n' | ||
'Run "cookcli help" to see global options.\n' | ||
'```\n', | ||
)); | ||
}); | ||
}); | ||
} |