สำคัญ
repo นี้ได้ถูกย้ายไปที่https://github.com/dart-lang/core/tree/main/pkgs/args
แยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่งดิบเป็นชุดของตัวเลือกและค่า
ไลบรารีนี้รองรับตัวเลือกสไตล์ GNU และ POSIX และทำงานได้ทั้งในแอปฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์
ขั้นแรกให้สร้าง ArgParser:
var parser = ArgParser();
จากนั้นกำหนดชุดตัวเลือกบน parser นั้นโดยใช้ addOption() และ addFlag() ต่อไปนี้เป็นวิธีขั้นต่ำในการสร้างตัวเลือกชื่อ "ชื่อ":
parser.addOption('name');
เมื่อตัวเลือกสามารถตั้งค่าหรือยกเลิกการตั้งค่าได้เท่านั้น (ซึ่งตรงข้ามกับการรับค่าสตริง) ให้ใช้แฟล็ก:
parser. addFlag ( 'name' );
ตัวเลือกการตั้งค่าสถานะ ตามค่าเริ่มต้น ยอมรับคำนำหน้า 'ไม่-' เพื่อปฏิเสธตัวเลือก คุณสามารถปิดการใช้งานคำนำหน้า 'no-' ได้โดยใช้พารามิเตอร์ negatable
:
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
เพื่อจัดเตรียมชุดค่าที่อนุญาตได้ เมื่อคุณดำเนินการ parser จะส่ง 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' );
});
การเรียกกลับสำหรับตัวเลือกทั้งหมดจะถูกเรียกเมื่อใดก็ตามที่ชุดของอาร์กิวเมนต์ถูกแยกวิเคราะห์ หากไม่มีการระบุตัวเลือกไว้ใน args การเรียกกลับจะถูกส่งผ่านค่าเริ่มต้น หรือ 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']
หากต้องการหยุดการแยกวิเคราะห์ตัวเลือกทันทีที่พบอาร์กิวเมนต์ตำแหน่ง allowTrailingOptions: false
เมื่อสร้าง ArgParser
หากต้องการส่งผ่านตัวเลือกและแฟล็กบนบรรทัดคำสั่ง ให้ใช้สไตล์ GNU หรือ POSIX พิจารณาตัวเลือกนี้:
parser. addOption ( 'name' , abbr : 'n' );
คุณสามารถระบุค่าของมันบนบรรทัดคำสั่งโดยใช้สิ่งใดสิ่งหนึ่งต่อไปนี้:
--name=somevalue
--name somevalue
-nsomevalue
-n somevalue
พิจารณาธงนี้:
parser. addFlag ( 'name' , abbr : 'n' );
คุณสามารถตั้งค่าเป็นจริงได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้:
--name
-n
คุณสามารถตั้งค่าเป็นเท็จได้โดยใช้สิ่งต่อไปนี้:
--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
นอกจาก ตัวเลือก แล้ว คุณยังสามารถกำหนด คำสั่ง ได้ด้วย คำสั่งคืออาร์กิวเมนต์ที่มีชื่อซึ่งมีชุดตัวเลือกของตัวเอง ตัวอย่างเช่น ลองพิจารณาคำสั่งเชลล์นี้:
$ 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' );
คุณสามารถเพิ่มหลายคำสั่งลงใน parser เดียวกันได้ เพื่อให้ผู้ใช้สามารถเลือกหนึ่งคำสั่งจากช่วงของคำสั่งที่เป็นไปได้ เมื่อแยกวิเคราะห์รายการอาร์กิวเมนต์ คุณสามารถกำหนดได้ว่าคำสั่งใดถูกป้อนและมีตัวเลือกใดให้ไว้
var results = parser. parse ([ 'commit' , '-a' ]);
print (results.command.name); // "commit"
print (results.command[ 'all' ]); // true
ตัวเลือกสำหรับคำสั่งจะต้องปรากฏหลังคำสั่งในรายการอาร์กิวเมนต์ ตัวอย่างเช่น เมื่อพิจารณาจาก parser ข้างต้น "git -a commit"
ไม่ ถูกต้อง parser พยายามค้นหาคำสั่งที่ถูกต้องที่สุดที่ยอมรับตัวเลือก ตัวอย่างเช่น:
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
ที่นี่ ทั้ง parser ระดับบนสุดและคำสั่ง "commit"
สามารถยอมรับ "-a"
ได้ (ซึ่งเป็นที่ยอมรับกันว่าอาจเป็นอินเทอร์เฟซบรรทัดคำสั่งที่ไม่ดี) ในกรณีนั้น เมื่อ "-a"
ปรากฏหลัง "commit"
แสดงว่าคำสั่งนั้นถูกนำไปใช้กับคำสั่งนั้น หากปรากฏทางด้านซ้ายของ "commit"
ว่าถูกกำหนดให้กับ parser ระดับบนสุด
หากคุณกำลังเขียนแอปพลิเคชันแบบใช้คำสั่ง คุณสามารถใช้คลาส CommandRunner และ Command เพื่อช่วยจัดโครงสร้างได้ CommandRunner มีการสนับสนุนในตัวสำหรับการส่งไปยังคำสั่งตามอาร์กิวเมนต์บรรทัดคำสั่ง รวมถึงการจัดการแฟล็ก --help
และอาร์กิวเมนต์ที่ไม่ถูกต้อง
เมื่อใช้ CommandRunner จะแทนที่ ArgParser
ในตัวอย่างต่อไปนี้ เราสร้างแอปพลิเคชัน dart ชื่อ dgit
ซึ่งรับคำสั่ง 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 จะเรียกใช้เมธอด overridden 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 ช่วยให้คุณสามารถระบุทั้ง args ส่วนกลางและอาร์กิวเมนต์เฉพาะคำสั่ง (และแม้แต่อาร์กิวเมนต์เฉพาะคำสั่งย่อย)
เพิ่มอาร์กิวเมนต์ลงใน CommandRunner โดยตรงเพื่อระบุอาร์กิวเมนต์ส่วนกลาง:
การเพิ่มข้อโต้แย้งทั่วโลก
var runner = CommandRunner ( 'dgit' , "A dart implementation of distributed version control." );
// add global flag
runner.argParser. addFlag ( 'verbose' , abbr : 'v' , help : 'increase logging' );
เพิ่มอาร์กิวเมนต์ให้กับแต่ละ Command เพื่อระบุอาร์กิวเมนต์เฉพาะของ Command
CommitCommand () {
// we can add command specific arguments here.
// [argParser] is automatically created by the parent class.
argParser. addFlag ( 'all' , abbr : 'a' );
}
คำสั่งยังสามารถมีคำสั่งย่อย ซึ่งเพิ่มด้วยคำสั่ง addSubcommand คำสั่งที่มีคำสั่งย่อยไม่สามารถรันโค้ดของตัวเองได้ ดังนั้นจึงไม่จำเป็นต้องดำเนินการรัน ตัวอย่างเช่น:
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
สำหรับคำสั่งทั้งหมด หากพบข้อผิดพลาดในการแยกวิเคราะห์อาร์กิวเมนต์หรือการประมวลผลคำสั่ง ระบบจะส่ง UseException; วิธีการ 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