Polir seu aplicativo CLI
Melhore o HelpCommand para fornecer informações mais detalhadas e adicione um argumento onOutput para tratamento flexível da saída.
Neste capítulo, você vai dar os toques finais no pacote command_runner.
Você vai refinar o HelpCommand para fornecer informações de uso mais detalhadas e
adicionar um argumento onOutput para um tratamento de saída mais flexível.
Isso finaliza o pacote CommandRunner e o prepara para uso em
cenários mais complexos.
O que você vai realizar
Pré-requisitos
#Antes de começar este capítulo, certifique-se de que você:
-
Completou o Capítulo 8 e tem um ambiente de desenvolvimento Dart funcionando
com o projeto
dartpedia. - Está familiarizado com conceitos básicos de programação, como variáveis, funções e controle de fluxo.
- Entende os conceitos de pacotes e bibliotecas no Dart.
- Está familiarizado com princípios de programação orientada a objetos, como herança e classes abstratas.
Tarefas
#
Você vai polir o pacote command_runner para torná-lo mais robusto e
amigável ao usuário.
Tarefa 1 Melhore a saída do HelpCommand
#
Aprimore o HelpCommand para fornecer informações de uso mais detalhadas,
incluindo opções e suas descrições.
Isso facilitará para os usuários
entenderem como usar seu aplicativo CLI.
Abra o arquivo
command_runner/lib/src/help_command.dart.-
Adicione imports para
console.darteexceptions.dartno topo do arquivo. Você precisa deles para usar as extensões de cor e para lançar umaArgumentException.command_runner/lib/src/help_command.dartdartimport 'dart:async'; import 'package:command_runner/command_runner.dart'; import 'console.dart'; import 'exceptions.dart'; -
Substitua o método
runexistente pelo seguinte. Esta nova versão usa umStringBufferpara construir a string de ajuda de forma eficiente e inclui lógica para tratar a saída detalhada.command_runner/lib/src/help_command.dartdart@override FutureOr<String> run(ArgResults args) async { final buffer = StringBuffer(); buffer.writeln(runner.usage.titleText); if (args.flag('verbose')) { for (var cmd in runner.commands) { buffer.write(_renderCommandVerbose(cmd)); } return buffer.toString(); } if (args.hasOption('command')) { var (:option, :input) = args.getOption('command'); var cmd = runner.commands.firstWhere( (command) => command.name == input, orElse: () { throw ArgumentException( 'Input $input is not a known command.', name, ); }, ); return _renderCommandVerbose(cmd); } // Verbose is false and no arg was passed in, so print basic usage. for (var command in runner.commands) { buffer.writeln(command.usage); } return buffer.toString(); }StringBufferé uma classe Dart que permite construir strings de forma eficiente. Ela tem mais desempenho do que usar o operador+, especialmente ao fazer muitas concatenações dentro de um loop. -
Adicione o método auxiliar privado
_renderCommandVerboseà classeHelpCommand. Este método formata a saída detalhada de um único comando.command_runner/lib/src/help_command.dartdartString _renderCommandVerbose(Command cmd) { final indent = ' ' * 10; final buffer = StringBuffer(); buffer.writeln(cmd.usage.instructionText); //abbr, name: description buffer.writeln('$indent ${cmd.help}'); if (cmd.valueHelp != null) { buffer.writeln( '$indent [Argument] Required? ${cmd.requiresArgument}, Type: ${cmd.valueHelp}, Default: ${cmd.defaultValue ?? 'none'}', ); } buffer.writeln('$indent Options:'); for (var option in cmd.options) { buffer.writeln('$indent ${option.usage}'); } return buffer.toString(); }
Tarefa 2 Adicione um callback onOutput
#
Em seguida, adicione um argumento onOutput ao CommandRunner para permitir
um tratamento de saída flexível.
Abra o arquivo
command_runner/lib/src/command_runner_base.dart.-
Adicione o argumento
onOutputao construtorCommandRunnere adicione o membroonOutputcorrespondente à classe.command_runner/lib/src/command_runner_base.dartdartclass CommandRunner { CommandRunner({this.onOutput, this.onError}); /// If not null, this method is used to handle output. Useful if you want to /// execute code before the output is printed to the console, or if you /// want to do something other than print output the console. /// If null, the onInput method will [print] the output. FutureOr<void> Function(String)? onOutput; FutureOr<void> Function(Object)? onError; // ... rest of the class } -
Atualize o método
runpara usar o argumentoonOutput.command_runner/lib/src/command_runner_base.dartdartFuture<void> run(List<String> input) async { try { final ArgResults results = parse(input); if (results.command != null) { Object? output = await results.command!.run(results); if (onOutput != null) { await onOutput!(output.toString()); } else { print(output.toString()); } } } on Exception catch (exception) { if (onError != null) { onError!(exception); } else { rethrow; } } }Isso atualiza o método
runpara usar a funçãoonOutput, caso ela seja fornecida. Caso contrário, o padrão é imprimir no console.
Tarefa 3 Use o callback onOutput
#
Por fim, atualize seu aplicativo principal para usar o novo recurso onOutput.
Abra o arquivo
cli/bin/cli.dart.-
Atualize a função
mainpara passar a funçãoonOutputaoCommandRunner. Você também precisará adicionar um import paraconsole.dartpara deixar a funçãowritedisponível.cli/bin/cli.dartdartimport 'package:command_runner/command_runner.dart'; const version = '0.0.1'; void main(List<String> arguments) { var commandRunner = CommandRunner( onOutput: (String output) async { await write(output); }, onError: (Object error) { if (error is Error) { throw error; } if (error is Exception) { print(error); } }, )..addCommand(HelpCommand()); commandRunner.run(arguments); }
Tarefa 4 Teste as mudanças
#Teste o HelpCommand aprimorado e o callback onOutput.
Abra seu terminal e navegue até o diretório
cli.-
Execute o comando
dart run bin/cli.dart help --verbose.Você deve ver informações de uso detalhadas para o comando
help, impressas usando a funçãowritepersonalizada.
Revisão
#O que você concluiu
Aqui está um resumo do que você construiu e aprendeu nesta lição.Usou StringBuffer para construir strings de forma eficiente
Você substituiu a concatenação de strings por um StringBuffer, que pode ser mais eficiente para construir strings em loops. Métodos como
writeln() e write() acrescentam conteúdo, enquanto toString() produz a string final.
Aprimorou o HelpCommand com saída detalhada
Você melhorou o sistema de ajuda para mostrar informações de uso detalhadas, incluindo opções, valores padrão e descrições. A flag
--verbose e a opção --command dão aos usuários controle sobre o nível de detalhe.
Adicionou um argumento de callback onOutput para tratamento flexível
Você adicionou onOutput ao CommandRunner, permitindo que quem usa a biblioteca personalize como a saída é exibida. Esse padrão torna seu pacote mais flexível e adaptável, possibilitando impressão atrasada, logging ou redirecionamento da saída.
Quiz
#Check your understanding
1 / 2StringBuffer em Dart?
-
Para montar strings de forma eficiente, acrescentando várias partes.
Isso mesmo!
StringBufferoferece concatenação de strings eficiente ao evitar a criação de objetos string intermediários durante várias concatenações sucessivas. -
Para armazenar uma string de tamanho fixo.
Não exatamente.
Strings em Dart são imutáveis e não têm o conceito de tamanho fixo.
StringBuffertem outra finalidade, relacionada à criação de strings. -
Para criptografar strings.
Não exatamente.
Criptografia exige bibliotecas especializadas de criptografia.
StringBufferé um utilitário de uso geral, não relacionado à segurança. -
Para comparar duas strings quanto à igualdade.
Não exatamente.
A comparação de strings é feita com
==oucompareTo().StringBuffertem outra finalidade.
onOutput da classe CommandRunner permite fazer?
-
Personalizar o tratamento da saída de um comando.
Isso mesmo!
onOutputpermite definir um comportamento próprio para a saída do comando, como formatação, logging ou gravação em destinos diferentes. -
Especificar a entrada de um comando.
Não exatamente.
A entrada vem dos argumentos de linha de comando passados para
run(). O nomeonOutputsugere que ele trata de outra coisa. -
Definir a mensagem de erro de um comando.
Não exatamente.
O tratamento de erros tem mecanismo próprio (
onError).onOutputserve para outro tipo de resultado. -
Definir o nome de um comando.
Não exatamente.
Nomes de comando são definidos no getter
nameda classeCommand.onOutputtem outra finalidade.
Próxima lição
#Na próxima lição, você vai se preparar para a parte da Wikipedia do aplicativo.
Salvo indicação em contrário, a documentação neste site reflete Dart 3.13.7. Página atualizada pela última vez em 2026-11-12. Ver código-fonte ou relatar um problema.
Encontrou essa página sem tradução ou que precisa de correção? Abra uma issue e nos ajude a manter esse site em PT-BR para ajudar pessoas como você.