123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282(*---------------------------------------------------------------------------
Copyright (c) 2022 The cmdliner programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)type'aeval_ok=[`Okof'a|`Version|`Help]typeeval_error=[`Parse|`Term|`Exn]type'aeval_exit=[`Okof'a|`ExitofCmdliner_info.Exit.code]leterr_helps="Term error, help requested for unknown command "^sleterr_argv="argv array must have at least one element"letadd_stdoptsei=letdocs=Cmdliner_info.Cmd.stdopts_docs@@Cmdliner_info.Eval.cmdeiinletvargs,vers=matchCmdliner_info.Cmd.version@@Cmdliner_info.Eval.maineiwith|None->Cmdliner_info.Arg.Set.empty,None|Some_->letargs,_asvers=Cmdliner_arg.stdopt_version~docsinargs,Someversinlethelp=Cmdliner_arg.stdopt_help~docsinletargs=Cmdliner_info.Arg.Set.unionvargs(fsthelp)inletcmd=Cmdliner_info.Cmd.add_args(Cmdliner_info.Eval.cmdei)argsinhelp,vers,Cmdliner_info.Eval.with_cmdeicmdletparse_error_termerreicl=Error(`Parseerr)type'aeval_result=('a,[Cmdliner_term.term_escape|`Exnofexn*Printexc.raw_backtrace|`Parseofstring|`Std_helpofCmdliner_manpage.format|`Std_version])resultletrun_parser~catcheiclf=try(feicl:>'aeval_result)with|exnwhencatch->letbt=Printexc.get_raw_backtrace()inError(`Exn(exn,bt))lettry_eval_stdopts~catcheiclhelpversion=matchrun_parser~catcheicl(sndhelp)with|Ok(Somefmt)->Some(Error(`Std_helpfmt))|Error_aserr->Someerr|OkNone->matchversionwith|None->None|Someversion->matchrun_parser~catcheicl(sndversion)with|Okfalse->None|Oktrue->Some(Error(`Std_version))|Error_aserr->Someerrletdo_helphelp_ppferr_ppfeifmtcmd=letei=matchcmdwith|None(* help of main command requested *)->letenv_=assertfalseinletcmd=Cmdliner_info.Eval.maineiinletei'=Cmdliner_info.Eval.v~cmd~parents:[]~env~err_ppfinbeginmatchCmdliner_info.Eval.parentseiwith|[]->(* [ei] is an evaluation of main, [cmd] has stdopts *)ei'|_->let_,_,ei=add_stdoptsei'ineiend|Somecmd->try(* For now we simply keep backward compat. [cmd] should be
a name from main's children. *)letmain=Cmdliner_info.Eval.maineiinletis_cmdt=Cmdliner_info.Cmd.namet=cmdinletchildren=Cmdliner_info.Cmd.childrenmaininletcmd=List.findis_cmdchildreninlet_,_,ei=add_stdopts(Cmdliner_info.Eval.with_cmdeicmd)ineiwithNot_found->invalid_arg(err_helpcmd)inCmdliner_docgen.pp_man~errs:err_ppffmthelp_ppfeiletdo_resulthelp_ppferr_ppfei=function|Okv->Ok(`Okv)|Errorres->matchreswith|`Std_helpfmt->Cmdliner_docgen.pp_man~errs:err_ppffmthelp_ppfei;Ok`Help|`Std_version->Cmdliner_msg.pp_versionhelp_ppfei;Ok`Version|`Parseerr->Cmdliner_msg.pp_err_usageerr_ppfei~err_lines:false~err;Error`Parse|`Help(fmt,cmd)->do_helphelp_ppferr_ppfeifmtcmd;Ok`Help|`Exn(e,bt)->Cmdliner_msg.pp_backtraceerr_ppfeiebt;(Error`Exn)|`Error(usage,err)->(ifusagethenCmdliner_msg.pp_err_usageerr_ppfei~err_lines:true~errelseCmdliner_msg.pp_errerr_ppfei~err);(Error`Term)letcmd_name_triecmds=letaddacccmd=leti=Cmdliner_cmd.get_infocmdinletname=Cmdliner_info.Cmd.nameiinmatchCmdliner_trie.addaccnamecmdwith|`Newt->t|`Replaced(cmd',_)->leti'=Cmdliner_cmd.get_infocmd'andkind="command"ininvalid_arg@@Cmdliner_base.err_multi_def~kindnameCmdliner_info.Cmd.docii'inList.fold_leftaddCmdliner_trie.emptycmdsletcmd_name_domcmds=letcmd_namec=Cmdliner_info.Cmd.name(Cmdliner_cmd.get_infoc)inList.sortString.compare(List.rev_mapcmd_namecmds)letfind_termargscmd=letnever_term__=assertfalseinletstopargs_restargs_revparentscmd=letargs=List.rev_appendargs_revargs_restinmatch(cmd:'aCmdliner_cmd.t)with|Cmd(i,t)->args,t,i,parents,Ok()|Group(i,(Somet,children))->args,t,i,parents,Ok()|Group(i,(None,children))->letdom=cmd_name_domchildreninleterr=Cmdliner_msg.err_cmd_missing~dominargs,never_term,i,parents,Errorerrinletrecloopargs_revparentscmd=function|("--"::_|[]asrest)->stoprestargs_revparentscmd|(arg::_asrest)whenCmdliner_cline.is_optarg->stoprestargs_revparentscmd|arg::args->matchcmdwith|Cmd(i,t)->letargs=List.rev_appendargs_rev(arg::args)inargs,t,i,parents,Ok()|Group(i,(t,children))->letindex=cmd_name_triechildreninmatchCmdliner_trie.findindexargwith|`Okcmd->loopargs_rev(i::parents)cmdargs|`Not_found->letargs=List.rev_appendargs_rev(arg::args)inletall=Cmdliner_trie.ambiguitiesindex""inlethints=Cmdliner_base.suggestargallinletdom=cmd_name_domchildreninletkind="command"inleterr=Cmdliner_base.err_unknown~kind~dom~hintsarginargs,never_term,i,parents,Errorerr|`Ambiguous->letargs=List.rev_appendargs_rev(arg::args)inletambs=Cmdliner_trie.ambiguitiesindexarginletambs=List.sortcompareambsinleterr=Cmdliner_base.err_ambiguous~kind:"command"arg~ambsinargs,never_term,i,parents,Errorerrinloop[][]cmdargsletenv_defaultv=trySome(Sys.getenvv)withNot_found->Noneletremove_execargv=tryList.tl(Array.to_listargv)withFailure_->invalid_argerr_argvletdo_deprecated_msgserr_ppfclei=letcmd=Cmdliner_info.Eval.cmdeiinletmsgs=Cmdliner_cline.deprecated_msgsclinletmsgs=matchCmdliner_info.Cmd.deprecatedcmdwith|None->msgs|Somemsg->letname=Cmdliner_base.quote(Cmdliner_info.Cmd.namecmd)inString.concat""("command "::name::": "::msg::[])::msgsinifmsgs<>[]thenCmdliner_msg.pp_errerr_ppfei~err:(String.concat"\n"msgs)leteval_value?help:(help_ppf=Format.std_formatter)?err:(err_ppf=Format.err_formatter)?(catch=true)?(env=env_default)?(argv=Sys.argv)cmd=letargs,f,cmd,parents,res=find_term(remove_execargv)cmdinletei=Cmdliner_info.Eval.v~cmd~parents~env~err_ppfinlethelp,version,ei=add_stdoptseiinletterm_args=Cmdliner_info.Cmd.args@@Cmdliner_info.Eval.cmdeiinletres=matchreswith|Errormsg->(* Command lookup error, we still prioritize stdargs *)letcl=matchCmdliner_cline.createterm_argsargswith|Error(_,cl)->cl|Okcl->clinbeginmatchtry_eval_stdopts~catcheiclhelpversionwith|Somee->e|None->Error(`Error(true,msg))end|Ok()->matchCmdliner_cline.createterm_argsargswith|Error(e,cl)->beginmatchtry_eval_stdopts~catcheiclhelpversionwith|Somee->e|None->Error(`Error(true,e))end|Okcl->matchtry_eval_stdopts~catcheiclhelpversionwith|Somee->e|None->do_deprecated_msgserr_ppfclei;run_parser~catcheiclfindo_resulthelp_ppferr_ppfeiresleteval_peek_opts?(version_opt=false)?(env=env_default)?(argv=Sys.argv)t:'aoption*('aeval_ok,eval_error)result=letargs,f=tinletversion=ifversion_optthenSome"dummy"elseNoneinletcmd=Cmdliner_info.Cmd.v?version"dummy"inletcmd=Cmdliner_info.Cmd.add_argscmdargsinletnull_ppf=Format.make_formatter(fun___->())(fun()->())inletei=Cmdliner_info.Eval.v~cmd~parents:[]~env~err_ppf:null_ppfinlethelp,version,ei=add_stdoptseiinletterm_args=Cmdliner_info.Cmd.args@@Cmdliner_info.Eval.cmdeiinletcli_args=remove_execargvinletv,ret=matchCmdliner_cline.create~peek_opts:trueterm_argscli_argswith|Error(e,cl)->beginmatchtry_eval_stdopts~catch:trueeiclhelpversionwith|Somee->None,e|None->None,Error(`Error(true,e))end|Okcl->letret=run_parser~catch:trueeiclfinletv=matchretwithOkv->Somev|Error_->Noneinmatchtry_eval_stdopts~catch:trueeiclhelpversionwith|Somee->v,e|None->v,retinletret=matchretwith|Okv->Ok(`Okv)|Error`Std_help_->Ok`Help|Error`Std_version->Ok`Version|Error`Parse_->Error`Parse|Error`Help_->Ok`Help|Error`Exn_->Error`Exn|Error`Error_->Error`Termin(v,ret)letexit_status_of_result?(term_err=Cmdliner_info.Exit.cli_error)=function|Ok(`Ok_|`Help|`Version)->Cmdliner_info.Exit.ok|Error`Term->term_err|Error`Parse->Cmdliner_info.Exit.cli_error|Error`Exn->Cmdliner_info.Exit.internal_errorleteval_value'?help?err?catch?env?argv?term_errcmd=matcheval_value?help?err?catch?env?argvcmdwith|Ok(`Ok_asv)->v|ret->`Exit(exit_status_of_result?term_errret)leteval?help?err?catch?env?argv?term_errcmd=exit_status_of_result?term_err@@eval_value?help?err?catch?env?argvcmdleteval'?help?err?catch?env?argv?term_errcmd=matcheval_value?help?err?catch?env?argvcmdwith|Ok(`Okc)->c|r->exit_status_of_result?term_errrletpp_errppfcmd~msg=(* FIXME move that to Cmdliner_msgs *)letname=Cmdliner_cmd.namecmdinFormat.fprintfppf"%s: @[%a@]@."nameCmdliner_base.pp_linesmsgleteval_result?help?(err=Format.err_formatter)?catch?env?argv?term_errcmd=matcheval_value?help~err?catch?env?argvcmdwith|Ok(`Ok(Errormsg))->pp_errerrcmd~msg;Cmdliner_info.Exit.some_error|r->exit_status_of_result?term_errrleteval_result'?help?(err=Format.err_formatter)?catch?env?argv?term_errcmd=matcheval_value?help~err?catch?env?argvcmdwith|Ok(`Ok(Okc))->c|Ok(`Ok(Errormsg))->pp_errerrcmd~msg;Cmdliner_info.Exit.some_error|r->exit_status_of_result?term_errr