Importante
Este repositório foi movido para https://github.com/dart-lang/core/tree/main/pkgs/args
Analisa argumentos brutos de linha de comando em um conjunto de opções e valores.
Esta biblioteca oferece suporte a opções de estilo GNU e POSIX e funciona em aplicativos do lado do servidor e do lado do cliente.
Primeiro crie um ArgParser:
var parser = ArgParser();
Em seguida, defina um conjunto de opções nesse analisador usando addOption() e addFlag(). Esta é a maneira mínima de criar uma opção chamada "nome":
parser.addOption('name');
Quando uma opção só pode ser definida ou desativada (em vez de usar um valor de string), use um sinalizador:
parser. addFlag ( 'name' );
As opções de sinalização, por padrão, aceitam um prefixo 'no-' para negar a opção. Você pode desativar o prefixo 'no-' usando o parâmetro negatable
:
parser. addFlag ( 'name' , negatable : false );
Nota: De agora em diante, "opção" refere-se tanto a opções regulares quanto a sinalizadores. Nos casos em que a distinção é importante, usaremos a "opção sem sinalização".
As opções podem ter uma abreviatura opcional de um caractere, especificada com o parâmetro abbr
:
parser. addOption ( 'mode' , abbr : 'm' );
parser. addFlag ( 'verbose' , abbr : 'v' );
As opções também podem ter um valor padrão, especificado com o parâmetro defaultsTo
. O valor padrão é usado quando os argumentos não especificam a opção.
parser. addOption ( 'mode' , defaultsTo : 'debug' );
parser. addFlag ( 'verbose' , defaultsTo : false );
O valor padrão para opções sem sinalização pode ser qualquer string. Para sinalizadores, deve ser um bool
.
Para validar uma opção sem sinalização, você pode usar o parâmetro allowed
para fornecer um conjunto permitido de valores. Ao fazer isso, o analisador lança uma ArgParserException
se o valor de uma opção não estiver no conjunto permitido. Aqui está um exemplo de especificação de valores permitidos:
parser. addOption ( 'mode' , allowed : [ 'debug' , 'release' ]);
Você pode usar o parâmetro callback
para associar uma função a uma opção. Posteriormente, quando ocorre a análise, a função de retorno de chamada é invocada com o valor da opção:
parser. addOption ( 'mode' , callback : (mode) => print ( 'Got mode $ mode ' ));
parser. addFlag ( 'verbose' , callback : (verbose) {
if (verbose) print ( 'Verbose' );
});
Os retornos de chamada para todas as opções são chamados sempre que um conjunto de argumentos é analisado. Se uma opção não for fornecida nos argumentos, seu retorno de chamada receberá o valor padrão ou null
se nenhum valor padrão for definido.
Se uma opção for mandatory
, mas não fornecida, o objeto de resultados lançará um [ ArgumentError
][ArgumentError] na recuperação.
parser. addOption ( 'mode' , mandatory : true );
Depois de configurar um ArgParser com algumas opções e sinalizadores, você o usa chamando ArgParser.parse() com um conjunto de argumentos:
var results = parser. parse ([ 'some' , 'command' , 'line' , 'args' ]);
Esses argumentos geralmente vêm dos argumentos de main()
. Por exemplo:
main(List<String> args) {
// ...
var results = parser.parse(args);
}
No entanto, você pode passar qualquer lista de strings. O método parse()
retorna uma instância de ArgResults, um objeto semelhante a um mapa que contém os valores das opções analisadas.
var parser = ArgParser ();
parser. addOption ( 'mode' );
parser. addFlag ( 'verbose' , defaultsTo : true );
var results = parser. parse ([ '--mode' , 'debug' , 'something' , 'else' ]);
print (results. option ( 'mode' )); // debug
print (results. flag ( 'verbose' )); // true
Por padrão, o método parse()
permite que sinalizadores e opções adicionais sejam passados após os parâmetros posicionais, a menos que --
seja usado para indicar que todos os outros parâmetros serão posicionais. Os argumentos posicionais vão para ArgResults.rest.
print (results.rest); // ['something', 'else']
Para interromper a análise de opções assim que um argumento posicional for encontrado, allowTrailingOptions: false
ao criar o ArgParser.
Para realmente passar opções e sinalizadores na linha de comando, use o estilo GNU ou POSIX. Considere esta opção:
parser. addOption ( 'name' , abbr : 'n' );
Você pode especificar seu valor na linha de comando usando qualquer um dos seguintes:
--name=somevalue
--name somevalue
-nsomevalue
-n somevalue
Considere esta bandeira:
parser. addFlag ( 'name' , abbr : 'n' );
Você pode defini-lo como verdadeiro usando um dos seguintes:
--name
-n
Você pode defini-lo como falso usando o seguinte:
--no-name
Várias abreviações de sinalizadores podem ser resumidas em um único argumento. Digamos que você defina estes sinalizadores:
parser
.. addFlag ( 'verbose' , abbr : 'v' )
.. addFlag ( 'french' , abbr : 'f' )
.. addFlag ( 'iambic-pentameter' , abbr : 'i' );
Você pode definir todos os três sinalizadores de uma vez:
-vfi
Por padrão, uma opção tem apenas um único valor, com os valores das opções posteriores substituindo os anteriores; por exemplo:
var parser = ArgParser ();
parser. addOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on' , '--mode' , 'off' ]);
print (results. option ( 'mode' )); // prints 'off'
Vários valores podem ser analisados com addMultiOption()
. Com este método, uma opção pode ocorrer várias vezes, e o método parse()
retorna uma lista de valores:
var parser = ArgParser ();
parser. addMultiOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on' , '--mode' , 'off' ]);
print (results. multiOption ( 'mode' )); // prints '[on, off]'
Por padrão, os valores para uma opção com vários valores também podem ser separados por vírgulas:
var parser = ArgParser ();
parser. addMultiOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on,off' ]);
print (results. multiOption ( 'mode' )); // prints '[on, off]'
Isso pode ser desabilitado passando splitCommas: false
.
Além das opções , você também pode definir comandos . Um comando é um argumento nomeado que possui seu próprio conjunto de opções. Por exemplo, considere este comando shell:
$ git commit -a
O executável é git
, o comando é commit
e a opção -a
é uma opção passada para o comando. Você pode adicionar um comando usando o método addCommand:
var parser = ArgParser ();
var command = parser. addCommand ( 'commit' );
Ele retorna outro ArgParser, que você pode usar para definir opções específicas para esse comando. Se você já possui um ArgParser para as opções do comando, você pode passá-lo:
var parser = ArgParser ();
var command = ArgParser ();
parser. addCommand ( 'commit' , command);
O ArgParser de um comando pode então definir opções ou sinalizadores:
command. addFlag ( 'all' , abbr : 'a' );
Você pode adicionar vários comandos ao mesmo analisador para que um usuário possa selecionar um entre vários comandos possíveis. Ao analisar uma lista de argumentos, você pode determinar qual comando foi inserido e quais opções foram fornecidas para ele.
var results = parser. parse ([ 'commit' , '-a' ]);
print (results.command.name); // "commit"
print (results.command[ 'all' ]); // true
As opções de um comando devem aparecer após o comando na lista de argumentos. Por exemplo, dado o analisador acima, "git -a commit"
não é válido. O analisador tenta encontrar o comando mais à direita que aceita uma opção. Por exemplo:
var parser = ArgParser ();
parser. addFlag ( 'all' , abbr : 'a' );
var command = parser. addCommand ( 'commit' );
command. addFlag ( 'all' , abbr : 'a' );
var results = parser. parse ([ 'commit' , '-a' ]);
print (results.command[ 'all' ]); // true
Aqui, tanto o analisador de nível superior quanto o comando "commit"
podem aceitar um "-a"
(que provavelmente é uma interface de linha de comando ruim, é certo). Nesse caso, quando "-a"
aparecer depois de "commit"
, ele será aplicado a esse comando. Se aparecer à esquerda de "commit"
, será fornecido ao analisador de nível superior.
Se estiver escrevendo um aplicativo baseado em comando, você poderá usar as classes CommandRunner e Command para ajudar a estruturá-lo. CommandRunner tem suporte integrado para envio para comandos com base em argumentos de linha de comando, bem como manipulação de sinalizadores --help
e argumentos inválidos.
Ao usar o CommandRunner ele substitui o ArgParser.
No exemplo a seguir, construímos um aplicativo Dart chamado dgit
que recebe os comandos commit
e stash
.
O CommandRunner usa um executableName
que é usado para gerar a mensagem de ajuda.
por exemplo, dgit commit -a
Arquivo dgit.dart
void main ( List < String > args) {
var runner = CommandRunner ( "dgit" , "A dart implementation of distributed version control." )
.. addCommand ( CommitCommand ())
.. addCommand ( StashCommand ())
.. run (args);
}
Quando a linha run(args)
acima é executada, ela analisa os argumentos da linha de comando procurando por um dos comandos ( commit
ou stash
).
Se o CommandRunner encontrar um comando correspondente, então o CommandRunner chamará o método run()
substituído no comando correspondente (por exemplo, CommitCommand().run).
Os comandos são definidos estendendo a classe Command. Por exemplo:
class CommitCommand extends Command {
// The [name] and [description] properties must be defined by every
// subclass.
final name = "commit" ;
final description = "Record changes to the repository." ;
CommitCommand () {
// we can add command specific arguments here.
// [argParser] is automatically created by the parent class.
argParser. addFlag ( 'all' , abbr : 'a' );
}
// [run] may also return a Future.
void run () {
// [argResults] is set before [run()] is called and contains the flags/options
// passed to this command.
print (argResults. flag ( 'all' ));
}
}
O CommandRunner permite que você especifique argumentos globais, bem como argumentos específicos de comando (e até argumentos específicos de subcomando).
Adicione argumentos diretamente ao CommandRunner para especificar argumentos globais:
Adicionando argumentos globais
var runner = CommandRunner ( 'dgit' , "A dart implementation of distributed version control." );
// add global flag
runner.argParser. addFlag ( 'verbose' , abbr : 'v' , help : 'increase logging' );
Adicione argumentos a cada comando para especificar argumentos específicos do comando.
CommitCommand () {
// we can add command specific arguments here.
// [argParser] is automatically created by the parent class.
argParser. addFlag ( 'all' , abbr : 'a' );
}
Os comandos também podem ter subcomandos, que são adicionados com addSubcommand. Um comando com subcomandos não pode executar seu próprio código, portanto run não precisa ser implementado. Por exemplo:
class StashCommand extends Command {
final String name = "stash" ;
final String description = "Stash changes in the working directory." ;
StashCommand () {
addSubcommand ( StashSaveCommand ());
addSubcommand ( StashListCommand ());
}
}
CommandRunner adiciona automaticamente um comando help
que exibe informações de uso para comandos, bem como suporte para o sinalizador --help
para todos os comandos. Se encontrar um erro ao analisar os argumentos ou ao processar um comando, ele lançará uma UsageException; seu método main()
deve capturá-los e imprimi-los apropriadamente. Por exemplo:
runner. run (arguments). catchError ((error) {
if (error is ! UsageException ) throw error;
print (error);
exit ( 64 ); // Exit code 64 indicates a usage error.
});
Você pode gerar automaticamente um bom texto de ajuda, adequado para uso como saída de --help
. Para exibir boas informações de uso, você deve fornecer algum texto de ajuda ao criar suas opções.
Para definir o texto de ajuda para uma opção inteira, use o parâmetro help:
::
parser. addOption ( 'mode' , help : 'The compiler configuration' ,
allowed : [ 'debug' , 'release' ]);
parser. addFlag ( 'verbose' , help : 'Show additional diagnostic info' );
Para opções sem sinalização, você também pode fornecer uma string de ajuda para o parâmetro:
parser. addOption ( 'out' , help : 'The output path' , valueHelp : 'path' ,
allowed : [ 'debug' , 'release' ]);
Para opções sem sinalização, você também pode fornecer ajuda detalhada para cada valor esperado usando o parâmetro allowedHelp:
::
parser. addOption ( 'arch' , help : 'The architecture to compile for' ,
allowedHelp : {
'ia32' : 'Intel x86' ,
'arm' : 'ARM Holding 32-bit chip'
});
Para exibir a ajuda, use o getter de uso:
print (parser.usage);
A string resultante se parece com isto:
--mode The compiler configuration
[debug, release]
--out=<path> The output path
--[no-]verbose Show additional diagnostic info
--arch The architecture to compile for
[arm] ARM Holding 32-bit chip
[ia32] Intel x86