重要的
該倉庫已移至 https://github.com/dart-lang/core/tree/main/pkgs/args
將原始命令列參數解析為一組選項和值。
該程式庫支援 GNU 和 POSIX 樣式選項,並且適用於伺服器端和用戶端應用程式。
首先創建一個 ArgParser:
var parser = ArgParser();
然後使用 addOption() 和 addFlag() 在該解析器上定義一組選項。這是建立名為“name”的選項的最小方法:
parser.addOption('name');
當選項只能設定或取消設定(而非採用字串值)時,請使用標誌:
parser. addFlag ( 'name' );
預設情況下,標誌選項接受“no-”前綴來否定該選項。您可以使用negatable
參數停用“no-”前綴:
parser. addFlag ( 'name' , negatable : false );
注意:從現在開始,「選項」指的是常規選項和標誌。在區分很重要的情況下,我們將使用「非標誌選項」。
選項可以有一個可選的單字元縮寫,用abbr
參數指定:
parser. addOption ( 'mode' , abbr : 'm' );
parser. addFlag ( 'verbose' , abbr : 'v' );
選項還可以有一個預設值,透過defaultsTo
參數指定。當參數未指定選項時,將使用預設值。
parser. addOption ( 'mode' , defaultsTo : 'debug' );
parser. addFlag ( 'verbose' , defaultsTo : false );
非標誌選項的預設值可以是任何字串。對於標誌,它必須是bool
。
若要驗證非標誌選項,您可以使用allowed
參數來提供允許的值集。當您這樣做時,如果選項的值不在允許的集合中,解析器將拋出ArgParserException
。以下是指定允許值的範例:
parser. addOption ( 'mode' , allowed : [ 'debug' , 'release' ]);
您可以使用callback
參數將函數與選項關聯。稍後,當進行解析時,將使用選項的值呼叫回調函數:
parser. addOption ( 'mode' , callback : (mode) => print ( 'Got mode $ mode ' ));
parser. addFlag ( 'verbose' , callback : (verbose) {
if (verbose) print ( 'Verbose' );
});
每當解析一組參數時,就會呼叫所有選項的回呼。如果參數中未提供選項,則其回呼將傳遞預設值;如果未設定預設值,則傳遞null
。
如果某個選項是mandatory
但未提供,則結果物件在檢索時會拋出 [ ArgumentError
][ArgumentError]。
parser. addOption ( 'mode' , mandatory : true );
一旦你用一些選項和標誌設定了 ArgParser,你就可以透過使用一組參數來呼叫 ArgParser.parse() 來使用它:
var results = parser. parse ([ 'some' , 'command' , 'line' , 'args' ]);
這些參數通常來自main()
參數。例如:
main(List<String> args) {
// ...
var results = parser.parse(args);
}
但是,您可以傳入任何字串列表。 parse()
方法傳回 ArgResults 的實例,這是一個類似地圖的對象,包含已解析選項的值。
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
預設情況下, parse()
方法允許在位置參數之後傳遞附加標誌和選項,除非使用--
來指示所有其他參數都將是位置參數。位置參數進入 ArgResults.rest。
print (results.rest); // ['something', 'else']
若要在找到位置參數後立即停止解析選項,請在建立 ArgParser 時allowTrailingOptions: false
。
若要實際在命令列上傳遞選項和標誌,請使用 GNU 或 POSIX 風格。考慮這個選項:
parser. addOption ( 'name' , abbr : 'n' );
您可以使用以下任意命令在命令列上指定其值:
--name=somevalue
--name somevalue
-nsomevalue
-n somevalue
考慮這個標誌:
parser. addFlag ( 'name' , abbr : 'n' );
您可以使用下列方法之一將其設為 true:
--name
-n
您可以使用以下命令將其設定為 false:
--no-name
多個標誌縮寫可以折疊成一個參數。假設您定義了這些標誌:
parser
.. addFlag ( 'verbose' , abbr : 'v' )
.. addFlag ( 'french' , abbr : 'f' )
.. addFlag ( 'iambic-pentameter' , abbr : 'i' );
您可以一次設定所有三個標誌:
-vfi
預設情況下,一個選項只有一個值,後面的選項值會覆寫前面的選項值;例如:
var parser = ArgParser ();
parser. addOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on' , '--mode' , 'off' ]);
print (results. option ( 'mode' )); // prints 'off'
可以使用addMultiOption()
解析多個值。使用此方法,一個選項可以出現多次,並且parse()
方法會傳回一個值清單:
var parser = ArgParser ();
parser. addMultiOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on' , '--mode' , 'off' ]);
print (results. multiOption ( 'mode' )); // prints '[on, off]'
預設情況下,多值選項的值也可以用逗號分隔:
var parser = ArgParser ();
parser. addMultiOption ( 'mode' );
var results = parser. parse ([ '--mode' , 'on,off' ]);
print (results. multiOption ( 'mode' )); // prints '[on, off]'
可以透過傳遞splitCommas: false
來停用此功能。
除了選項之外,您還可以定義命令。指令是一個命名參數,有自己的一組選項。例如,考慮以下 shell 指令:
$ git commit -a
可執行檔是git
,指令是commit
, -a
選項是傳遞給指令的選項。您可以使用 addCommand 方法新增命令:
var parser = ArgParser ();
var command = parser. addCommand ( 'commit' );
它會傳回另一個 ArgParser,然後您可以使用它來定義特定於該命令的選項。如果您已經有一個用於命令選項的 ArgParser,則可以將其傳入:
var parser = ArgParser ();
var command = ArgParser ();
parser. addCommand ( 'commit' , command);
命令的 ArgParser 然後可以定義選項或標誌:
command. addFlag ( 'all' , abbr : 'a' );
您可以將多個命令新增到同一個解析器,以便使用者可以從一系列可能的命令中選擇一個。解析參數清單時,您可以確定輸入了哪個命令以及為其提供了哪些選項。
var results = parser. parse ([ 'commit' , '-a' ]);
print (results.command.name); // "commit"
print (results.command[ 'all' ]); // true
命令的選項必須出現在參數清單中的命令之後。例如,給定上述解析器, "git -a commit"
無效。解析器嘗試找到最右邊接受選項的指令。例如:
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
在這裡,頂級解析器和"commit"
命令都可以接受"-a"
(誠然,這可能是一個糟糕的命令列介面)。在這種情況下,當"-a"
出現在"commit"
之後時,它將應用於該命令。如果它出現在"commit"
的左側,則將其提供給頂級解析器。
如果您正在編寫基於命令的應用程序,則可以使用 CommandRunner 和 Command 類別來幫助建立它。 CommandRunner 內建支援依據命令列參數分派指令,以及處理--help
標誌和無效參數。
使用 CommandRunner 時,它會取代 ArgParser。
在下面的範例中,我們建立了一個名為dgit
的 dart 應用程序,它接受命令commit
和stash
。
CommandRunner 採用executableName
名稱,用於產生說明訊息。
例如dgit commit -a
dgit.dart
void main ( List < String > args) {
var runner = CommandRunner ( "dgit" , "A dart implementation of distributed version control." )
.. addCommand ( CommitCommand ())
.. addCommand ( StashCommand ())
.. run (args);
}
當上面的run(args)
行執行時,它會解析命令列 args 來尋找命令之一( commit
或stash
)。
如果 CommandRunner 找到符合的命令,則 CommandRunner 會對符合的命令呼叫重寫的run()
方法(例如 CommitCommand().run)。
命令是透過擴展 Command 類別來定義的。例如:
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' ));
}
}
CommandRunner 可讓您指定全域參數以及命令特定參數(甚至子命令特定參數)。
直接向 CommandRunner 新增參數以指定全域參數:
新增全域參數
var runner = CommandRunner ( 'dgit' , "A dart implementation of distributed version control." );
// add global flag
runner.argParser. addFlag ( 'verbose' , abbr : 'v' , help : 'increase logging' );
向每個命令新增參數以指定命令特定的參數。
CommitCommand () {
// we can add command specific arguments here.
// [argParser] is automatically created by the parent class.
argParser. addFlag ( 'all' , abbr : 'a' );
}
指令也可以有子指令,使用 addSubcommand 新增子指令。帶有子命令的命令不能運行自己的程式碼,因此不需要實作 run 。例如:
class StashCommand extends Command {
final String name = "stash" ;
final String description = "Stash changes in the working directory." ;
StashCommand () {
addSubcommand ( StashSaveCommand ());
addSubcommand ( StashListCommand ());
}
}
CommandRunner 自動新增一個help
命令,顯示命令的使用訊息,並支援所有命令的--help
標誌。如果它在解析參數或處理命令時遇到錯誤,則會拋出UsageException;你的main()
方法應該要捕捉這些並適當地列印它們。例如:
runner. run (arguments). catchError ((error) {
if (error is ! UsageException ) throw error;
print (error);
exit ( 64 ); // Exit code 64 indicates a usage error.
});
您可以自動產生漂亮的幫助文本,適合用作--help
的輸出。為了顯示良好的使用信息,您應該在創建選項時提供一些幫助文字。
若要定義整個選項的說明文本,請使用help:
參數:
parser. addOption ( 'mode' , help : 'The compiler configuration' ,
allowed : [ 'debug' , 'release' ]);
parser. addFlag ( 'verbose' , help : 'Show additional diagnostic info' );
對於非標誌選項,您還可以為參數提供幫助字串:
parser. addOption ( 'out' , help : 'The output path' , valueHelp : 'path' ,
allowed : [ 'debug' , 'release' ]);
對於非標誌選項,您還可以使用allowedHelp:
參數為每個期望值提供詳細協助:
parser. addOption ( 'arch' , help : 'The architecture to compile for' ,
allowedHelp : {
'ia32' : 'Intel x86' ,
'arm' : 'ARM Holding 32-bit chip'
});
若要顯示幫助,請使用用法 getter:
print (parser.usage);
結果字串看起來像這樣:
--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