option=value
ما عليك سوى تضمين argparse.hpp وستكون جاهزًا للبدء.
# include < argparse/argparse.hpp >
لبدء تحليل وسيطات سطر الأوامر، قم بإنشاء ArgumentParser
.
argparse::ArgumentParser program ( " program_name " );
ملاحظة: توجد وسيطة ثانية اختيارية لـ ArgumentParser
وهي إصدار البرنامج. مثال: argparse::ArgumentParser program("libfoo", "1.9.0");
ملاحظة: توجد وسيطتان ثالثة ورابعة اختيارية لـ ArgumentParser
والتي تتحكم في الوسائط الافتراضية. مثال: argparse::ArgumentParser program("libfoo", "1.9.0", default_arguments::help, false);
راجع الوسيطات الافتراضية أدناه.
لإضافة وسيطة جديدة، ما عليك سوى استدعاء .add_argument(...)
. يمكنك توفير قائمة متنوعة بأسماء الوسائط التي تريد تجميعها معًا، على سبيل المثال، -v
و-- --verbose
program.add_argument( " foo " );
program.add_argument( " -v " , " --verbose " ); // parameter packing
يدعم Argparse مجموعة متنوعة من أنواع الوسائط بما في ذلك الوسائط الموضعية والاختيارية والمركبة. يمكنك أدناه معرفة كيفية تكوين كل نوع من هذه الأنواع:
فيما يلي مثال على الحجة الموضعية :
# include < argparse/argparse.hpp >
int main ( int argc, char *argv[]) {
argparse::ArgumentParser program ( " program_name " );
program. add_argument ( " square " )
. help ( " display the square of a given integer " )
. scan < ' i ' , int >();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
return 1 ;
}
auto input = program. get < int >( " square " );
std::cout << (input * input) << std::endl;
return 0 ;
}
وتشغيل الكود:
foo@bar:/home/dev/ $ ./main 15
225
إليك ما يحدث:
add_argument()
لتحديد خيارات سطر الأوامر التي يرغب البرنامج في قبولها. في هذه الحالة، قمت بتسميته مربعًا بحيث يتماشى مع وظيفته..scan
لتحويل إدخال المستخدم إلى عدد صحيح.parser.get<T>(key)
. الآن، دعونا نلقي نظرة على الوسائط الاختيارية . تبدأ الوسيطات الاختيارية بـ -
أو --
، على سبيل المثال، --verbose
أو -a
. يمكن وضع الوسائط الاختيارية في أي مكان في تسلسل الإدخال.
argparse::ArgumentParser program ( " test " );
program.add_argument( " --verbose " )
.help( " increase output verbosity " )
.default_value( false )
.implicit_value( true );
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
if (program[ " --verbose " ] == true ) {
std::cout << " Verbosity enabled " << std::endl;
}
foo@bar:/home/dev/ $ ./main --verbose
Verbosity enabled
إليك ما يحدث:
--verbose
. لاحظ أنه باستخدام .default_value(false)
، إذا لم يتم استخدام الوسيطة الاختيارية، فسيتم تعيين قيمتها تلقائيًا على false..implicit_value(true)
، يحدد المستخدم أن هذا الخيار هو علامة أكثر من كونه خيارًا يتطلب قيمة. عندما يقوم المستخدم بتوفير خيار --verbose، يتم تعيين قيمته على true. عند تعريف وسيطات العلامة، يمكنك استخدام flag()
والتي هي نفسها default_value(false).implicit_value(true)
.
argparse::ArgumentParser program ( " test " );
program.add_argument( " --verbose " )
.help( " increase output verbosity " )
.flag();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
if (program[ " --verbose " ] == true ) {
std::cout << " Verbosity enabled " << std::endl;
}
هناك سيناريوهات حيث ترغب في جعل الوسيطة الاختيارية مطلوبة . كما تمت مناقشته أعلاه، تبدأ الوسائط الاختيارية بـ -
أو --
. يمكنك جعل هذه الأنواع من الوسائط مطلوبة كما يلي:
program.add_argument( " -o " , " --output " )
.required()
.help( " specify the output file. " );
إذا لم يقدم المستخدم قيمة لهذه المعلمة، فسيتم طرح استثناء.
وبدلاً من ذلك، يمكنك توفير قيمة افتراضية مثل:
program.add_argument( " -o " , " --output " )
.default_value(std::string( " - " ))
.required()
.help( " specify the output file. " );
إذا كنت تريد وجود وسيطة اختيارية ولكن ليس لديك قيمة افتراضية جيدة لها، فيمكنك الجمع بين الاختبار والوصول إلى الوسيطة على النحو التالي:
if ( auto fn = program.present( " -o " )) {
do_something_with (*fn);
}
كما هو الحال مع get
، تقبل الطريقة present
أيضًا وسيطة القالب. ولكن بدلاً من إرجاع T
، يُرجع parser.present<T>(key)
std::optional<T>
، بحيث عندما لا يقدم المستخدم قيمة لهذه المعلمة، فإن القيمة المرجعة تساوي std::nullopt
.
إذا كنت تريد معرفة ما إذا كان المستخدم قد قدم قيمة للوسيطة التي تحتوي على .default_value
، فتحقق مما إذا كانت الوسيطة .is_used()
.
program.add_argument( " --color " )
.default_value(std::string{ " orange " }) // might otherwise be type const char* leading to an error when trying program.get<std::string>
.help( " specify the cat's fur color " );
try {
program. parse_args (argc, argv); // Example: ./main --color orange
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto color = program.get<std::string>( " --color " ); // "orange"
auto explicit_color = program.is_used( " --color " ); // true, user provided orange
قد ترغب في السماح بتكرار الوسيطة الاختيارية وجمع كل القيم في مكان واحد.
program.add_argument( " --color " )
.default_value<std::vector<std::string>>({ " orange " })
.append()
.help( " specify the cat's fur color " );
try {
program. parse_args (argc, argv); // Example: ./main --color red --color green --color blue
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto colors = program.get<std::vector<std::string>>( " --color " ); // {"red", "green", "blue"}
لاحظ أنه تم إعطاء .default_value
معلمة قالب صريحة لمطابقة النوع الذي تريد الحصول عليه .get
.
النمط الشائع هو تكرار الوسيطة للإشارة إلى قيمة أكبر.
int verbosity = 0 ;
program.add_argument( " -V " , " --verbose " )
.action([&]( const auto &) { ++verbosity; })
.append()
.default_value( false )
.implicit_value( true )
.nargs( 0 );
program.parse_args(argc, argv); // Example: ./main -VVVV
std::cout << " verbose level: " << verbosity << std::endl; // verbose level: 4
قم بإنشاء مجموعة حصرية متبادلة باستخدام program.add_mutually_exclusive_group(required = false)
. سيتأكد `argparse`` من وجود وسيطة واحدة فقط في المجموعة المتبادلة في سطر الأوامر:
auto &group = program.add_mutually_exclusive_group();
group.add_argument( " --first " );
group.add_argument( " --second " );
مع الاستخدام التالي سوف يؤدي إلى خطأ:
foo@bar:/home/dev/ $ ./main --first 1 --second 2
Argument '--second VAR' not allowed with '--first VAR'
تقبل الدالة add_mutually_exclusive_group()
أيضًا وسيطة required
، للإشارة إلى أن واحدة على الأقل من الوسيطات الحصرية المتبادلة مطلوبة:
auto &group = program.add_mutually_exclusive_group( true );
group.add_argument( " --first " );
group.add_argument( " --second " );
مع الاستخدام التالي سوف يؤدي إلى خطأ:
foo@bar:/home/dev/ $ ./main
One of the arguments '--first VAR' or '--second VAR' is required
من الممكن ربط الوسائط بمتغير يخزن قيمتها، كبديل لاستدعاء program.get<T>(arg_name)
أو program[arg_name]
بشكل صريح
يتم تنفيذ هذا حاليًا لمتغيرات النوع bool
(وهذا أيضًا يستدعي ضمنيًا flag()
) و int
و double
و std::string
و std::vector<std::string>
و std::vector<int>
. إذا لم يتم تحديد الوسيطة في سطر الأوامر، فسيتم تعيين القيمة الافتراضية (إذا تم تعيينها) في المتغير.
bool flagvar = false ;
program.add_argument( " --flagvar " ).store_into(flagvar);
int intvar = 0 ;
program.add_argument( " --intvar " ).store_into(intvar);
double doublevar = 0 ;
program.add_argument( " --doublevar " ).store_into(doublevar);
std::string strvar;
program.add_argument( " --strvar " ).store_into(strvar);
std::vector<std::string> strvar_repeated;
program.add_argument( " --strvar-repeated " ).append().store_into(strvar_repeated);
std::vector<std::string> strvar_multi_valued;
program.add_argument( " --strvar-multi-valued " ).nargs( 2 ).store_into(strvar_multi_valued);
std::vector< int > intvar_repeated;
program.add_argument( " --intvar-repeated " ).append().store_into(intvar_repeated);
std::vector< int > intvar_multi_valued;
program.add_argument( " --intvar-multi-valued " ).nargs( 2 ).store_into(intvar_multi_valued);
تبدأ الوسيطات الاختيارية بـ -
. هل يمكن argparse
التعامل مع الأرقام السالبة؟ الجواب هو نعم!
argparse::ArgumentParser program;
program.add_argument( " integer " )
.help( " Input number " )
.scan< ' i ' , int >();
program.add_argument( " floats " )
.help( " Vector of floats " )
.nargs( 4 )
.scan< ' g ' , float >();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
// Some code to print arguments
foo@bar:/home/dev/ $ ./main -5 -1.1 -3.1415 -3.1e2 -4.51329E3
integer : -5
floats : -1.1 -3.1415 -310 -4513.29
كما ترون هنا، يدعم argparse
الأعداد الصحيحة السالبة والأعداد السالبة والترميز العلمي.
argparse::ArgumentParser program ( " main " );
program.add_argument( " square " )
.help( " display the square of a given number " )
.scan< ' i ' , int >();
program.add_argument( " --verbose " )
.default_value( false )
.implicit_value( true );
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
int input = program.get< int >( " square " );
if (program[ " --verbose " ] == true ) {
std::cout << " The square of " << input << " is " << (input * input) << std::endl;
}
else {
std::cout << (input * input) << std::endl;
}
foo@bar:/home/dev/ $ ./main 4
16
foo@bar:/home/dev/ $ ./main 4 --verbose
The square of 4 is 16
foo@bar:/home/dev/ $ ./main --verbose 4
The square of 4 is 16
يقوم std::cout << program
بطباعة رسالة مساعدة، بما في ذلك استخدام البرنامج ومعلومات حول الوسائط المسجلة في ArgumentParser
. بالنسبة للمثال السابق، إليك رسالة المساعدة الافتراضية:
foo@bar:/home/dev/$ ./main --help
Usage: main [-h] [--verbose] square
Positional arguments:
square display the square of a given number
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--verbose
يمكنك أيضًا الحصول على رسالة المساعدة في سلسلة عبر program.help().str()
.
سيضيف ArgumentParser::add_description
نصًا قبل معلومات الوسيطة التفصيلية. سيضيف ArgumentParser::add_epilog
نصًا بعد كل مخرجات المساعدة الأخرى.
# include < argparse/argparse.hpp >
int main ( int argc, char *argv[]) {
argparse::ArgumentParser program ( " main " );
program. add_argument ( " thing " ). help ( " Thing to use. " ). metavar ( " THING " );
program. add_argument ( " --member " ). help ( " The alias for the member to pass to. " ). metavar ( " ALIAS " );
program. add_argument ( " --verbose " ). default_value ( false ). implicit_value ( true );
program. add_description ( " Forward a thing to the next member. " );
program. add_epilog ( " Possible things include betingalw, chiz, and res. " );
program. parse_args (argc, argv);
std::cout << program << std::endl;
}
Usage: main [-h] [--member ALIAS] [--verbose] THING
Forward a thing to the next member.
Positional arguments:
THING Thing to use.
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--member ALIAS The alias for the member to pass to.
--verbose
Possible things include betingalw, chiz, and res.
عادةً ما تقوم كائنات ArgumentParser بربط وسيطة سطر أوامر واحدة بإجراء واحد يجب اتخاذه. يقوم .nargs
بربط عدد مختلف من وسيطات سطر الأوامر بإجراء واحد. عند استخدام nargs(N)
، سيتم تجميع الوسائط N من سطر الأوامر معًا في قائمة.
argparse::ArgumentParser program ( " main " );
program.add_argument( " --input_files " )
.help( " The list of input files " )
.nargs( 2 );
try {
program. parse_args (argc, argv); // Example: ./main --input_files config.yml System.xml
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto files = program.get<std::vector<std::string>>( " --input_files " ); // {"config.yml", "System.xml"}
يحتوي ArgumentParser.get<T>()
على تخصصات لـ std::vector
و std::list
. لذلك، فإن المتغير التالي، .get<std::list>
، سيعمل أيضًا.
auto files = program.get<std::list<std::string>>( " --input_files " ); // {"config.yml", "System.xml"}
باستخدام .scan
، يمكن إنشاء قائمة بأنواع القيم المطلوبة بسرعة من وسائط سطر الأوامر. هنا مثال:
argparse::ArgumentParser program ( " main " );
program.add_argument( " --query_point " )
.help( " 3D query point " )
.nargs( 3 )
.default_value(std::vector< double >{ 0.0 , 0.0 , 0.0 })
.scan< ' g ' , double >();
try {
program. parse_args (argc, argv); // Example: ./main --query_point 3.5 4.7 9.2
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto query_point = program.get<std::vector< double >>( " --query_point " ); // {3.5, 4.7, 9.2}
يمكنك أيضًا إنشاء قائمة متغيرة الطول من الوسائط باستخدام .nargs
. وفيما يلي بعض الأمثلة.
program.add_argument( " --input_files " )
.nargs( 1 , 3 ); // This accepts 1 to 3 arguments.
يتم تعريف بعض الأنماط المفيدة مثل "؟"، و"*"، و"+" في argparse في Python.
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::any); // "*" in Python. This accepts any number of arguments including 0.
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::at_least_one); // "+" in Python. This accepts one or more number of arguments.
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::optional); // "?" in Python. This accepts an argument optionally.
الوسائط المركبة هي وسائط اختيارية يتم دمجها وتوفيرها كوسيطة واحدة. على سبيل المثال: ps -aux
argparse::ArgumentParser program ( " test " );
program.add_argument( " -a " )
.default_value( false )
.implicit_value( true );
program.add_argument( " -b " )
.default_value( false )
.implicit_value( true );
program.add_argument( " -c " )
.nargs( 2 )
.default_value(std::vector< float >{ 0 . 0f , 0 . 0f })
.scan< ' g ' , float >();
try {
program. parse_args (argc, argv); // Example: ./main -abc 1.95 2.47
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto a = program.get< bool >( " -a " ); // true
auto b = program.get< bool >( " -b " ); // true
auto c = program.get<std::vector< float >>( " -c " ); // {1.95, 2.47}
// / Some code that prints parsed arguments
foo@bar:/home/dev/ $ ./main -ac 3.14 2.718
a = true
b = false
c = {3.14, 2.718}
foo@bar:/home/dev/ $ ./main -cb
a = false
b = true
c = {0.0, 0.0}
إليك ما يحدث:
-a
و -b
و -c
.-a
و -b
عبارة عن وسيطات تبديل.-c
يتطلب رقمين عائمين من سطر الأوامر.-abc
أو -bac
أو -cab
. يعمل هذا فقط مع أسماء الوسيطات القصيرة المكونة من حرف واحد.-a
و -b
يصبحان صحيحين.-c
..default_value
بالنسبة للمدخلات، يمكن للمستخدمين التعبير عن نوع بدائي للقيمة.
تحاول الطريقة .scan<Shape, T>
تحويل std::string
الواردة إلى T
بعد محدد تحويل Shape
. يتم طرح استثناء std::invalid_argument
أو std::range_error
للأخطاء.
program.add_argument( " -x " )
.scan< ' d ' , int >();
program.add_argument( " scale " )
.scan< ' g ' , double >();
يحدد Shape
الشكل الذي "يبدو عليه" الإدخال، وتحدد وسيطة قالب النوع القيمة المرجعة للإجراء المحدد مسبقًا. الأنواع المقبولة هي النقطة العائمة (على سبيل المثال، تعويم، مزدوج، طويل مزدوج) ومتكامل (أي موقع char، قصير، int، طويل، طويل طويل).
القواعد النحوية تتبع std::from_chars
، لكنها لا تكررها تمامًا. على سبيل المثال، قد تبدأ الأرقام السداسية العشرية بـ 0x
أو 0X
ويمكن التعامل مع الأرقام ذات الصفر البادئ كقيم ثماني.
شكل | تفسير |
---|---|
"أ" أو "أ" | النقطة العائمة الست عشرية |
"ه" أو "ه" | التدوين العلمي (النقطة العائمة) |
"و" أو "و" | تدوين ثابت (النقطة العائمة) |
"ز" أو "ز" | الشكل العام (سواء الثابت أو العلمي) |
'د' | عشري |
'أنا' | std::from_chars القواعد النحوية بقاعدة == 10 |
"س" | ثماني (غير موقعة) |
"أنت" | عشري (غير موقع) |
"س" أو "س" | سداسي عشري (غير موقع) |
يوفر argparse
وسيطات وإجراءات محددة مسبقًا لـ -h
/ --help
و -v
/ --version
. افتراضيًا، ستخرج هذه الإجراءات من البرنامج بعد عرض رسالة المساعدة أو الإصدار، على التوالي. هذا الخروج لا يستدعي المدمرين، ويتخطى عملية تنظيف الموارد المأخوذة.
يمكن تعطيل هذه الوسائط الافتراضية أثناء إنشاء ArgumentParser
بحيث يمكنك التعامل مع هذه الوسائط بطريقتك الخاصة. (لاحظ أنه يجب تضمين اسم البرنامج وإصداره عند اختيار الوسائط الافتراضية.)
argparse::ArgumentParser program ( " test " , " 1.0 " , default_arguments::none);
program.add_argument( " -h " , " --help " )
.action([=]( const std::string& s) {
std::cout << help (). str ();
})
.default_value( false )
.help( " shows help message " )
.implicit_value( true )
.nargs( 0 );
يُخرج مقتطف الكود أعلاه رسالة مساعدة ويستمر في التشغيل. وهو لا يدعم وسيطة --version
.
الإعداد الافتراضي هو default_arguments::all
للوسائط المضمنة. لن تتم إضافة أي وسائط افتراضية مع default_arguments::none
. سيضيف default_arguments::help
و default_arguments::version
بشكل فردي --help
و --version
.
يمكن استخدام الوسائط الافتراضية أثناء تعطيل الخروج الافتراضي باستخدام هذه الوسائط. هذه الوسيطة الرابعة إلى ArgumentParser
( exit_on_default_arguments
) هي علامة منطقية ذات قيمة حقيقية افتراضية. سيحتفظ الاستدعاء التالي --help
و --version
، لكن لن يتم الخروج عند استخدام هذه الوسائط.
argparse::ArgumentParser program ( " test " , " 1.0 " , default_arguments::all, false )
يدعم argparse
جمع الوسيطات "المتبقية" في نهاية الأمر، على سبيل المثال، لاستخدامها في المترجم:
foo@bar:/home/dev/ $ compiler file1 file2 file3
لتمكين هذا، ما عليك سوى إنشاء وسيطة ووضع علامة عليها على remaining
. يتم جمع كافة الوسائط المتبقية التي تم تمريرها إلى argparse هنا.
argparse::ArgumentParser program ( " compiler " );
program.add_argument( " files " )
.remaining();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
try {
auto files = program. get <std::vector<std::string>>( " files " );
std::cout << files. size () << " files provided " << std::endl;
for ( auto & file : files)
std::cout << file << std::endl;
} catch (std::logic_error& e) {
std::cout << " No files provided " << std::endl;
}
عندما لا يتم توفير الحجج:
foo@bar:/home/dev/ $ ./compiler
No files provided
وعندما يتم توفير وسائط متعددة:
foo@bar:/home/dev/ $ ./compiler foo.txt bar.txt baz.txt
3 files provided
foo.txt
bar.txt
baz.txt
تلعب عملية جمع الوسائط المتبقية بشكل جيد مع الوسائط الاختيارية أيضًا: