123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803moduleStable=structopen!Stable_internalopen!Ppx_compare_lib.BuiltinmoduleAnons=structmoduleGrammar=structmoduleV1=structtypet=|Zero|Oneofstring|Manyoft|Maybeoft|Concatoftlist|Ad_hocofstring[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| a17fd34ec213e508db450f6469f7fe99 |}];;letrecinvariantt=Base.Invariant.invariant[%here]t[%sexp_of:t](fun()->matchtwith|Zero->()|One_->()|ManyZero->failwith"Many Zero should be just Zero"|Manyt->invariantt|MaybeZero->failwith"Maybe Zero should be just Zero"|Maybet->invariantt|Concat[]|Concat[_]->failwith"Flatten zero and one-element Concat"|Concatts->Base.List.iterts~f:invariant|Ad_hoc_->());;lett_of_sexpsexp=lett=[%of_sexp:t]sexpininvariantt;t;;letrecusage=function|Zero->""|Oneusage->usage|ManyZero->failwith"bug in command.ml"|Many(One_ast)->Base.Printf.sprintf"[%s ...]"(usaget)|Manyt->Base.Printf.sprintf"[(%s) ...]"(usaget)|MaybeZero->failwith"bug in command.ml"|Maybet->Base.Printf.sprintf"[%s]"(usaget)|Concatts->Base.String.concat~sep:" "(Base.List.mapts~f:usage)|Ad_hocusage->usage;;endmoduleModel=V1endmoduleV2=structtypet=|Usageofstring|GrammarofGrammar.V1.t[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| 081d9ec167903f8f8c49cbf8e3fb3a66 |}];;endmoduleModel=V2endmoduleFlag_info=structmoduleV1=structtypet={name:string;doc:string;aliases:stringlist}[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| bd8d6fb7a662d2c0b5e0d2026c6d2d21 |}];;endmoduleModel=V1endmoduleBase_info=structmoduleV2=structtypet={summary:string;readme:stringoption[@sexp.option];anons:Anons.V2.t;flags:Flag_info.V1.tlist}[@@derivingbin_io,compare,fields,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| 8faac1e8d9deb0baaa56ac8ebf85b498 |}];;endmoduleV1=structtypet={summary:string;readme:stringoption[@sexp.option];usage:string;flags:Flag_info.V1.tlist}[@@derivingbin_shape,sexp]letto_latest{summary;readme;usage;flags}={V2.summary;readme;anons=Usageusage;flags};;letof_latest{V2.summary;readme;anons;flags}={summary;readme;usage=(matchanonswith|Usageusage->usage|Grammargrammar->Anons.Grammar.V1.usagegrammar);flags};;endmoduleModel=V2endmoduleGroup_info=structtypea=Dummy_type_because_we_cannot_digest_type_constructors_only_concrete_types[@@derivingbin_io]moduleV2=structtype'at={summary:string;readme:stringoption[@sexp.option];subcommands:(string*'a)List.Stable.V1.tLazy.Stable.V1.t}[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:at];[%expect{| 2cc3eeb58d12d8fe4400009e592d7827 |}];;open!Baseletmapt~f={twithsubcommands=Lazy.mapt.subcommands~f:(List.Assoc.map~f)};;endmoduleModel=V2moduleV1=structtype'at={summary:string;readme:stringoption[@sexp.option];subcommands:(string*'a)List.Stable.V1.t}[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:at];[%expect{| 2cc3eeb58d12d8fe4400009e592d7827 |}];;open!Baseletmapt~f={twithsubcommands=List.Assoc.mapt.subcommands~f}letto_latest{summary;readme;subcommands}:'aModel.t={summary;readme;subcommands=Lazy.from_valsubcommands};;letof_latest({summary;readme;subcommands}:'aModel.t):'at={summary;readme;subcommands=Lazy.forcesubcommands};;endendmoduleExec_info=structletabs_path~dirpath=ifFilename.is_absolutepaththenpathelseFilename.concatdirpath;;moduleV3=structtypet={summary:string;readme:stringoption[@sexp.option];working_dir:string;path_to_exe:string;child_subcommand:stringlist}[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| c0c8256e9238cdd8f2ec1f8785e02ae0 |}];;letto_latest=Fn.idletof_latest=Fn.idendmoduleModel=V3moduleV2=structtypet={summary:string;readme:stringoption[@sexp.option];working_dir:string;path_to_exe:string}[@@derivingbin_shape,sexp]letto_v3t:V3.t={summary=t.summary;readme=t.readme;working_dir=t.working_dir;path_to_exe=t.path_to_exe;child_subcommand=[]};;letof_v3(t:V3.t)={summary=t.summary;readme=t.readme;working_dir=t.working_dir;path_to_exe=abs_path~dir:t.working_dirt.path_to_exe};;letto_latest=Fn.composeV3.to_latestto_v3letof_latest=Fn.composeof_v3V3.of_latestendmoduleV1=structtypet={summary:string;readme:stringoption[@sexp.option];(* [path_to_exe] must be absolute. *)path_to_exe:string}[@@derivingbin_shape,sexp]letto_v2t:V2.t={summary=t.summary;readme=t.readme;working_dir="/";path_to_exe=t.path_to_exe};;letof_v2(t:V2.t)={summary=t.summary;readme=t.readme;path_to_exe=abs_path~dir:t.working_dirt.path_to_exe};;letto_latest=Fn.composeV2.to_latestto_v2letof_latest=Fn.composeof_v2V2.of_latestendendmoduleFully_forced=structmoduleV1=structtypet=|BasicofBase_info.V2.t|GroupoftGroup_info.V2.t|ExecofExec_info.V3.t*t[@@derivingbin_io,compare,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| 981154ef3919437c6c822619882841d4 |}];;endmoduleModel=V1endmoduleSexpable=structmoduleV3=structtypet=|BaseofBase_info.V2.t|GroupoftGroup_info.V2.t|ExecofExec_info.V3.t|LazyoftLazy.Stable.V1.t[@@derivingbin_shape,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| d3c375548f1a43c58c71e814c04ba36a |}];;letto_latest=Fn.idletof_latest=Fn.idendmoduleModel=V3moduleV2=structtypet=|BaseofBase_info.V2.t|GroupoftGroup_info.V1.t|ExecofExec_info.V2.t[@@derivingbin_shape,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| 598d4b41ef435bc69a4886bdba0f8689 |}];;letrecto_latest:t->Model.t=function|Baseb->Baseb|Exece->Exec(Exec_info.V2.to_lateste)|Groupg->Group(Group_info.V1.to_latest(Group_info.V1.mapg~f:to_latest));;letrecof_latest:Model.t->t=function|Baseb->Baseb|Exece->Exec(Exec_info.V2.of_lateste)|Lazythunk->of_latest(Base.Lazy.forcethunk)|Groupg->Group(Group_info.V1.map(Group_info.V1.of_latestg)~f:of_latest);;endmoduleV1=structtypet=|BaseofBase_info.V1.t|GroupoftGroup_info.V1.t|ExecofExec_info.V1.t[@@derivingbin_shape,sexp]let%expect_test_=print_endline[%bin_digest:t];[%expect{| 70d20b5432ffab77a385b02b04031d2e |}];;letrecto_latest:t->Model.t=function|Baseb->Base(Base_info.V1.to_latestb)|Exece->Exec(Exec_info.V1.to_lateste)|Groupg->Group(Group_info.V1.to_latest(Group_info.V1.mapg~f:to_latest));;letrecof_latest:Model.t->t=function|Baseb->Base(Base_info.V1.of_latestb)|Exece->Exec(Exec_info.V1.of_lateste)|Lazythunk->of_latest(Base.Lazy.forcethunk)|Groupg->Group(Group_info.V1.map(Group_info.V1.of_latestg)~f:of_latest);;endmoduleVersioned=structtypet=|V1ofV1.t|V2ofV2.t|V3ofV3.t(* available at least since 2020-04 *)[@@derivingbin_shape,sexp,variants](* It's okay to change this one in place, as long as we wait long enough before
dropping support for old versions. *)let%expect_test_=print_endline[%bin_digest:t];[%expect{| 796fbf006deb25159171637c2a510bf4 |}];;letto_latest=function|V1t->V1.to_latestt|V2t->V2.to_latestt|V3t->V3.to_latestt;;letof_latest~version_to_uselatest=matchversion_to_usewith|1->V1(V1.of_latestlatest)|2->V2(V2.of_latestlatest)|3->V3(V3.of_latestlatest)|other->Std_internal.failwiths~here:[%here]"unsupported version_to_use"other[%sexp_of:int];;endendendopen!Importopen!Std_internalmoduleAnons=structmoduleGrammar=structtypet=Stable.Anons.Grammar.Model.t=|Zero|Oneofstring|Manyoft|Maybeoft|Concatoftlist|Ad_hocofstring[@@derivingbin_io,compare,sexp]letinvariant=Stable.Anons.Grammar.Model.invariantletusage=Stable.Anons.Grammar.Model.usageendtypet=Stable.Anons.Model.t=|Usageofstring|GrammarofGrammar.t[@@derivingbin_io,compare,sexp]endmoduleNum_occurrences=structtypet={at_least_once:bool;at_most_once:bool}[@@derivingcompare,enumerate,fields,sexp_of]letmaybe_missing_prefix="["letmaybe_missing_suffix="]"letmaybe_more_suffix=" ..."letto_help_stringt~flag_name=let{at_least_once;at_most_once}=tinletdescription=ifat_least_oncethenflag_nameelseString.concat[maybe_missing_prefix;flag_name;maybe_missing_suffix]inifat_most_oncethendescriptionelseString.concat[description;maybe_more_suffix];;letof_help_stringname=letat_most_once,name=matchString.chop_suffixname~suffix:maybe_more_suffixwith|None->true,name|Somename->false,nameinletat_least_once,name=matchString.chop_prefixname~prefix:maybe_missing_prefix|>Option.bind~f:(String.chop_suffix~suffix:maybe_missing_suffix)with|None->true,name|Somename->false,namein{at_least_once;at_most_once},name;;let%expect_test"to_help_string"=letflag_name="name"inList.iter[%all:t]~f:(funt->lets=to_help_stringt~flag_nameinprint_s[%message""~_:(t:t)s];lett',flag_name'=of_help_stringsinassert([%compare.equal:t]tt');assert([%compare.equal:string]flag_nameflag_name'));[%expect{|
(((at_least_once false) (at_most_once false)) "[name] ...")
(((at_least_once true) (at_most_once false)) "name ...")
(((at_least_once false) (at_most_once true)) [name])
(((at_least_once true) (at_most_once true)) name) |}];;endmoduleFlag_info=structtypet=Stable.Flag_info.Model.t={name:string;doc:string;aliases:stringlist}[@@derivingbin_io,compare,fields,sexp]letparse_namet=letnum_occurrences,flag_name=Num_occurrences.of_help_stringt.nameinmatchString.splitflag_name~on:' 'with|[flag_name]->Ok(num_occurrences,false,flag_name)|[flag_name;_arg_doc]->Ok(num_occurrences,true,flag_name)|_->error_s[%message"Unable to parse"flag_name];;(* Users are likely to call all three of these functions, in which case we will re-parse
the [name] several times. We don't expect users of these functions to care about the
inefficiency. *)letflag_namet=parse_namet|>Or_error.map~f:trd3letnum_occurrencest=parse_namet|>Or_error.map~f:fst3letrequires_argt=parse_namet|>Or_error.map~f:snd3lethelp_screen_compareab=matcha,bwith|_,"[-help]"->-1|"[-help]",_->1|_,"[-version]"->-1|"[-version]",_->1|_,"[-build-info]"->-1|"[-build-info]",_->1|_,"help"->-1|"help",_->1|_,"version"->-1|"version",_->1|_->0;;endmoduleFlag_help_display=structtypet=Flag_info.tlistletsortt=List.stable_sortt~compare:(funab->Flag_info.help_screen_comparea.Flag_info.nameb.Flag_info.name);;letword_wrap_and_striptextwidth=letchunks=String.splittext~on:'\n'inList.concat_mapchunks~f:(funtext->letwords=String.splittext~on:' '|>List.filter~f:(funword->not(String.is_emptyword))inmatchList.foldwords~init:None~f:(funaccword->Some(matchaccwith|None->[],word|Some(lines,line)->(* efficiency is not a concern for the string lengths we expect *)letline_and_word=line^" "^wordinifString.lengthline_and_word<=widththenlines,line_and_wordelseline::lines,word))with|None->[]|Some(lines,line)->List.rev(line::lines));;moduleDisplay:sigvalto_string:t->stringend=structletnum_cols=80letspaces_stringwidth=String.makewidth' 'letpad_spaces_to_suffixx~width=letslack=width-String.lengthxinx^spaces_stringslack;;letindentation=" "letindent_and_newlinex=List.concat[[indentation];x;["\n"]]letspacing_dot=". "letdot_indentation_offset=27;;letdocumentation_start_column=dot_indentation_offset+String.lengthindentationletlhs_width=documentation_start_columnletlhs_pad_width=dot_indentation_offset+String.lengthindentationletlhs_pad=spaces_stringlhs_pad_widthletlhs_pad_and_newline_terminate=List.map~f:(funv->indent_and_newline[lhs_pad;v]);;letrowsflag_name_with_aliasesdocumentation=letflag_on_its_own_line=letflag_width=String.lengthindentation+String.lengthflag_name_with_aliasesinifflag_width>=dot_indentation_offset+String.lengthspacing_dotthenindent_and_newline[flag_name_with_aliases]elseindent_and_newline[pad_spaces_to_suffix~width:dot_indentation_offsetflag_name_with_aliases;spacing_dot]inletwrapped_documentation=word_wrap_and_stripdocumentation(num_cols-lhs_width-String.lengthindentation)inmatchwrapped_documentationwith|[]->[flag_on_its_own_line]|doc_wrapped_first_line::doc_wrapped_rest_lines->letwrapped_doc_lines=lhs_pad_and_newline_terminatedoc_wrapped_rest_linesinletprefix_doc_wrapped_first_line_withx=indent_and_newline[pad_spaces_to_suffix~width:dot_indentation_offsetx;spacing_dot;doc_wrapped_first_line]inifString.lengthflag_name_with_aliases>=dot_indentation_offsetthenflag_on_its_own_line::prefix_doc_wrapped_first_line_with""::wrapped_doc_lineselseprefix_doc_wrapped_first_line_withflag_name_with_aliases::wrapped_doc_lines;;letto_stringt=List.concat_mapt~f:(funt->letflag_name_with_aliases=letflag=t.Flag_info.nameinString.concat~sep:", "(flag::t.aliases)inrowsflag_name_with_aliasest.doc|>List.concat)|>String.concat;;endletto_stringt=Display.to_stringtendmoduleKey_type=structtypet=|Subcommand|Flagletto_string=function|Subcommand->"subcommand"|Flag->"flag";;endletlookup_expandalistprefixkey_type=letis_dash=Char.equal'-'inletalist=(* no partial matches unless some non-dash char is present *)ifString.for_allprefix~f:is_dashthenList.mapalist~f:(fun(key,(data,_))->key,(data,`Full_match_required))elsealistinmatchList.filteralist~f:(function|key,(_,`Full_match_required)->String.(=)keyprefix|key,(_,`Prefix)->String.is_prefixkey~prefix)with|[(key,(data,_name_matching))]->Ok(key,data)|[]->Error(sprintf!"unknown %{Key_type} %s"key_typeprefix)|matches->(matchList.findmatches~f:(fun(key,_)->String.(=)keyprefix)with|Some(key,(data,_name_matching))->Ok(key,data)|None->letmatching_keys=List.map~f:fstmatchesinError(sprintf!"%{Key_type} %s is an ambiguous prefix: %s"key_typeprefix(String.concat~sep:", "matching_keys)));;moduleBase_info=structtypet=Stable.Base_info.Model.t={summary:string;readme:stringoption[@sexp.option];anons:Anons.t;flags:Flag_info.tlist}[@@derivingbin_io,compare,fields,sexp]letfind_flagtprefix=matchString.is_prefixprefix~prefix:"-"with|false->error_s[%message"Flags must begin with '-'"prefix]|true->let%bind.Or_errorchoices=List.mapt.flags~f:(fun(flag_info:Flag_info.t)->let%bind.Or_errorflag_name=Flag_info.flag_nameflag_infoinOk(List.map(flag_name::flag_info.aliases)~f:(funkey->key,(flag_info,`Prefix))))|>Or_error.combine_errorsinlookup_expand(List.concatchoices)prefixFlag|>Result.map_error~f:Error.of_string|>Or_error.map~f:snd;;letget_usaget=matcht.anonswith|Usageusage->usage|Grammargrammar->Stable.Anons.Grammar.V1.usagegrammar;;endmoduleGroup_info=structtype'at='aStable.Group_info.Model.t={summary:string;readme:stringoption[@sexp.option];subcommands:(string*'a)List.tLazy.t}[@@derivingbin_io,compare,fields,sexp]letfind_subcommandtprefix=matchString.is_prefixprefix~prefix:"-"with|true->error_s[%message"Subcommands must not begin with '-'"prefix]|false->letchoices=List.map(forcet.subcommands)~f:(fun(key,a)->key,(a,`Prefix))inlookup_expandchoicesprefixSubcommand|>Result.map_error~f:Error.of_string|>Or_error.map~f:snd;;letmap=Stable.Group_info.Model.mapendmoduleExec_info=structtypet=Stable.Exec_info.Model.t={summary:string;readme:stringoption[@sexp.option];working_dir:string;path_to_exe:string;child_subcommand:stringlist}[@@derivingbin_io,compare,fields,sexp]endmoduleFully_forced=structtypet=Stable.Fully_forced.Model.t=|BasicofBase_info.t|GroupoftGroup_info.t|ExecofExec_info.t*t[@@derivingbin_io,compare,sexp]letexpanded_subcommandst=letrecexpand=function|Exec(_,t)->expandt|Basic_->[[]]|Group{subcommands;_}->List.concat_map(Lazy.forcesubcommands)~f:(fun(name,t)->List.map~f:(funpath->name::path)(expandt))in(* Reversing so that the commands show up in the same order as help is output *)List.rev(expandt);;endmoduleSexpable=structtypet=Stable.Sexpable.Model.t=|BaseofBase_info.t|GroupoftGroup_info.t|ExecofExec_info.t|LazyoftLazy.t[@@derivingsexp_of]letextraction_var=Command_env_var.to_stringCOMMAND_OUTPUT_HELP_SEXPmoduleVersioned=Stable.Sexpable.Versionedletsupported_versions=letfisupported_=Set.addsupportediinVersioned.Variants.fold~init:(Set.empty(moduleInt))~v1:(f1)~v2:(f2)~v3:(f3);;letof_versioned=Versioned.to_latestletto_versionedt~version_to_use=Versioned.of_latestt~version_to_useendtypet=|BasicofBase_info.t|GroupoftGroup_info.t|ExecofExec_info.t*(unit->t)|LazyoftLazy.tletrecfully_forced:t->Fully_forced.t=function|Basicb->Basicb|Groupg->Group(Group_info.mapg~f:fully_forced)|Exec(e,f)->Exec(e,fully_forced(f()))|Lazythunk->fully_forced(Lazy.forcethunk);;letrecget_summary=function|Basicb->b.summary|Groupg->g.summary|Exec(e,_)->e.summary|Lazythunk->get_summary(Lazy.forcethunk);;lethelp_text=`Use_Command_unixmodulePrivate=structmoduleKey_type=Key_typeletabs_path=Stable.Exec_info.abs_pathlethelp_screen_compare=Flag_info.help_screen_compareletword_wrap=Flag_help_display.word_wrap_and_stripletlookup_expand=lookup_expandend