123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481# 5 "caml_format_doc.cppo.ml"(**************************************************************************)(* *)(* OCaml *)(* *)(* Florian Angeletti, projet Cambium, Inria Paris *)(* *)(* Copyright 2021 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)moduleDoc=structtypebox_type=|H|V|HV|HoV|Btypestag=Format.stagtypeelement=|Textofstring|With_sizeofint|Open_boxof{kind:box_type;indent:int}|Close_box|Open_tagofFormat.stag|Close_tag|Open_tbox|Tab_breakof{width:int;offset:int}|Set_tab|Close_tbox|Simple_breakof{spaces:int;indent:int}|Breakof{fits:string*int*stringas'a;breaks:'a}|Flushof{newline:bool}|Newline|If_newline|Deprecatedof(Format.formatter->unit)typet={rev:elementlist}[@@unboxed]letempty={rev=[]}letto_listdoc=List.revdoc.revletadddocx={rev=x::doc.rev}letfoldfaccdoc=List.fold_leftfacc(to_listdoc)letappendleftright={rev=right.rev@left.rev}letformat_open_box_genppfkindindent=matchkindwith|H->Format.pp_open_hboxppf()|V->Format.pp_open_vboxppfindent|HV->Format.pp_open_hvboxppfindent|HoV->Format.pp_open_hovboxppfindent|B->Format.pp_open_boxppfindentletinterpret_eltppf=function|Textx->Format.pp_print_stringppfx|Open_box{kind;indent}->format_open_box_genppfkindindent|Close_box->Format.pp_close_boxppf()|Open_tagtag->Format.pp_open_stagppftag|Close_tag->Format.pp_close_stagppf()|Open_tbox->Format.pp_open_tboxppf()|Tab_break{width;offset}->Format.pp_print_tbreakppfwidthoffset|Set_tab->Format.pp_set_tabppf()|Close_tbox->Format.pp_close_tboxppf()|Simple_break{spaces;indent}->Format.pp_print_breakppfspacesindent|Break{fits;breaks}->Format.pp_print_custom_breakppf~fits~breaks|Flush{newline=true}->Format.pp_print_newlineppf()|Flush{newline=false}->Format.pp_print_flushppf()|Newline->Format.pp_force_newlineppf()|If_newline->Format.pp_print_if_newlineppf()|With_size_->()|Deprecatedpr->prppfletrecinterpretppf=function|[]->()|With_sizesize::Texttext::l->Format.pp_print_asppfsizetext;interpretppfl|x::l->interpret_eltppfx;interpretppflletformatppfdoc=interpretppf(to_listdoc)letopen_boxkindindentdoc=adddoc(Open_box{kind;indent})letclose_boxdoc=adddocClose_boxletstringsdoc=adddoc(Texts)letbytesbdoc=adddoc(Text(Bytes.to_stringb))letwith_sizesizedoc=adddoc(With_sizesize)letintndoc=adddoc(Text(string_of_intn))letfloatfdoc=adddoc(Text(string_of_floatf))letcharcdoc=adddoc(Text(String.make1c))letboolcdoc=adddoc(Text(Bool.to_stringc))letbreak~spaces~indentdoc=adddoc(Simple_break{spaces;indent})letspacedoc=break~spaces:1~indent:0docletcut=break~spaces:0~indent:0letcustom_break~fits~breaksdoc=adddoc(Break{fits;breaks})letforce_newlinedoc=adddocNewlineletif_newlinedoc=adddocIf_newlineletflushdoc=adddoc(Flush{newline=false})letforce_stopdoc=adddoc(Flush{newline=true})letopen_tboxdoc=adddocOpen_tboxletset_tabdoc=adddocSet_tablettab_break~width~offsetdoc=adddoc(Tab_break{width;offset})lettabdoc=tab_break~width:0~offset:0docletclose_tboxdoc=adddocClose_tboxletopen_tagstagdoc=adddoc(Open_tagstag)letclose_tagdoc=adddocClose_tagletiter?(sep=Fun.id)~iter:iteratoreltldoc=letfirst=reftrueinletrdoc=refdocinletprintx=if!firstthen(first:=false;rdoc:=eltx!rdoc)elserdoc:=!rdoc|>sep|>eltxiniteratorprintl;!rdocletreclist?(sep=Fun.id)eltldoc=matchlwith|[]->doc|[a]->eltadoc|a::((_::_)asq)->doc|>elta|>sep|>list~sepeltqletarray?sepeltadoc=iter?sep~iter:Array.itereltadocletseq?sepeltsdoc=iter?sep~iter:Seq.itereltsdocletoption?(none=Fun.id)eltodoc=matchowith|None->nonedoc|Somex->eltxdoc# 163 "caml_format_doc.cppo.ml"letresult~ok~errorxdoc=matchxwith|Okx->okxdoc|Errorx->errorxdoc(* To format free-flowing text *)letrecsubtextlenleftrightsdoc=letflushdoc=doc|>string(String.subsleft(right-left))inletafter_flushdoc=subtextlen(right+1)(right+1)sdocinifright=lenthenifleft<>lenthenflushdocelsedocelsematchs.[right]with|'\n'->doc|>flush|>force_newline|>after_flush|' '->doc|>flush|>space|>after_flush(* there is no specific support for '\t'
as it is unclear what a right semantics would be *)|_->subtextlenleft(right+1)sdoclettextsdoc=subtext(String.lengths)00sdoctype('a,'b)fmt=('a,t,t,'b)format4typeprinter0=t->ttype'aprinter='a->printer0letoutput_formatting_litfmting_litdoc=letopenCamlinternalFormatBasicsinmatchfmting_litwith|Close_box->close_boxdoc|Close_tag->close_tagdoc|Break(_,width,offset)->break~spaces:width~indent:offsetdoc|FFlush->flushdoc|Force_newline->force_newlinedoc|Flush_newline->force_stopdoc|Magic_size(_,n)->with_sizendoc|Escaped_at->char'@'doc|Escaped_percent->char'%'doc|Scan_indicc->doc|>char'@'|>charcletto_stringdoc=letb=Buffer.create20inletconvert=function|Texts->Buffer.add_stringbs|_->()infold(fun()x->convertx)()doc;Buffer.contentsbletbox_type=letopenCamlinternalFormatBasicsinfunction|Pp_fits->H|Pp_hbox->H|Pp_vbox->V|Pp_hovbox->HoV|Pp_hvbox->HV|Pp_box->Bletreccompose_accaccdoc=letopenCamlinternalFormatinmatchaccwith|CamlinternalFormat.Acc_formatting_lit(p,f)->doc|>compose_accp|>output_formatting_litf|Acc_formatting_gen(p,Acc_open_tagacc')->lettag=to_string(compose_accacc'empty)inletdoc=compose_accpdocindoc|>open_tag(Format.String_tagtag)|Acc_formatting_gen(p,Acc_open_boxacc')->letdoc=compose_accpdocinletbox=to_string(compose_accacc'empty)inlet(indent,bty)=CamlinternalFormat.open_box_of_stringboxindoc|>open_box(box_typebty)indent|Acc_string_literal(p,s)|Acc_data_string(p,s)->doc|>compose_accp|>strings|Acc_char_literal(p,c)|Acc_data_char(p,c)->doc|>compose_accp|>charc|Acc_delay(p,f)->doc|>compose_accp|>f|Acc_flushp->doc|>compose_accp|>flush|Acc_invalid_arg(_p,msg)->invalid_argmsg;|End_of_acc->docletkprintfk(CamlinternalFormatBasics.Format(fmt,_))=CamlinternalFormat.make_printf(funaccdoc->doc|>compose_accacc|>k)End_of_accfmtletprintfdoc=kprintfFun.iddocletkmsgk(CamlinternalFormatBasics.Format(fmt,_))=CamlinternalFormat.make_printf(funacc->k(compose_accaccempty))End_of_accfmtletmsgfmt=kmsgFun.idfmtend(** Compatibility interface *)typedoc=Doc.ttypet=doctypeformatter=docreftype'aprinter=formatter->'a->unitletformatterd=d(** {1 Primitive functions }*)letpp_print_stringppfs=ppf:=Doc.strings!ppfletpp_print_asppfsizes=ppf:=!ppf|>Doc.with_sizesize|>Doc.stringsletpp_print_substring~pos~lenppfs=ppf:=Doc.string(String.subsposlen)!ppfletpp_print_substring_as~pos~lenppfsizes=ppf:=!ppf|>Doc.with_sizesize|>Doc.string(String.subsposlen)letpp_print_bytesppfs=ppf:=Doc.string(Bytes.to_strings)!ppfletpp_print_textppfs=ppf:=Doc.texts!ppfletpp_print_charppfc=ppf:=Doc.charc!ppfletpp_print_intppfc=ppf:=Doc.intc!ppfletpp_print_floatppff=ppf:=Doc.floatf!ppfletpp_print_boolppfb=ppf:=Doc.boolb!ppfletpp_print_nothing__=()letpp_close_boxppf()=ppf:=Doc.close_box!ppfletpp_close_stagppf()=ppf:=Doc.close_tag!ppfletpp_print_breakppfspacesindent=ppf:=Doc.break~spaces~indent!ppfletpp_print_custom_breakppf~fits~breaks=ppf:=Doc.custom_break~fits~breaks!ppfletpp_print_spaceppf()=pp_print_breakppf10letpp_print_cutppf()=pp_print_breakppf00letpp_print_flushppf()=ppf:=Doc.flush!ppfletpp_force_newlineppf()=ppf:=Doc.force_newline!ppfletpp_print_newlineppf()=ppf:=Doc.force_stop!ppfletpp_print_if_newlineppf()=ppf:=Doc.if_newline!ppfletpp_open_stagppfstag=ppf:=!ppf|>Doc.open_tagstagletpp_open_box_genppfindentbxty=letbox_type=Doc.box_typebxtyinppf:=!ppf|>Doc.open_boxbox_typeindentletpp_open_boxppfindent=pp_open_box_genppfindentPp_boxletpp_open_tboxppf()=ppf:=!ppf|>Doc.open_tboxletpp_close_tboxppf()=ppf:=!ppf|>Doc.close_tboxletpp_set_tabppf()=ppf:=!ppf|>Doc.set_tabletpp_print_tabppf()=ppf:=!ppf|>Doc.tabletpp_print_tbreakppfwidthoffset=ppf:=!ppf|>Doc.tab_break~width~offsetletpp_docppfdoc=ppf:=Doc.append!ppfdocmoduleDriver=struct(* Interpret a formatting entity on a formatter. *)letoutput_formatting_litppf(fmting_lit:CamlinternalFormatBasics.formatting_lit)=matchfmting_litwith|Close_box->pp_close_boxppf()|Close_tag->pp_close_stagppf()|Break(_,width,offset)->pp_print_breakppfwidthoffset|FFlush->pp_print_flushppf()|Force_newline->pp_force_newlineppf()|Flush_newline->pp_print_newlineppf()|Magic_size(_,_)->()|Escaped_at->pp_print_charppf'@'|Escaped_percent->pp_print_charppf'%'|Scan_indicc->pp_print_charppf'@';pp_print_charppfcletcompute_tagoutputtag_acc=letbuf=Buffer.create16inletbuf_fmt=Format.formatter_of_bufferbufinletppf=refDoc.emptyinoutputppftag_acc;pp_print_flushppf();Doc.formatbuf_fmt!ppf;letlen=Buffer.lengthbufiniflen<2thenBuffer.contentsbufelseBuffer.subbuf1(len-2)(* Recursively output an "accumulator" containing a reversed list of
printing entities (string, char, flus, ...) in an output_stream. *)(* Differ from Printf.output_acc by the interpretation of formatting. *)(* Used as a continuation of CamlinternalFormat.make_printf. *)letrecoutput_accppf(acc:_CamlinternalFormat.acc)=matchaccwith|Acc_string_literal(Acc_formatting_lit(p,Magic_size(_,size)),s)|Acc_data_string(Acc_formatting_lit(p,Magic_size(_,size)),s)->output_accppfp;pp_print_asppfsizes;|Acc_char_literal(Acc_formatting_lit(p,Magic_size(_,size)),c)|Acc_data_char(Acc_formatting_lit(p,Magic_size(_,size)),c)->output_accppfp;pp_print_asppfsize(String.make1c);|Acc_formatting_lit(p,f)->output_accppfp;output_formatting_litppff;|Acc_formatting_gen(p,Acc_open_tagacc')->output_accppfp;pp_open_stagppf(Format.String_tag(compute_tagoutput_accacc'))|Acc_formatting_gen(p,Acc_open_boxacc')->output_accppfp;let(indent,bty)=letbox_info=compute_tagoutput_accacc'inCamlinternalFormat.open_box_of_stringbox_infoinpp_open_box_genppfindentbty|Acc_string_literal(p,s)|Acc_data_string(p,s)->output_accppfp;pp_print_stringppfs;|Acc_char_literal(p,c)|Acc_data_char(p,c)->output_accppfp;pp_print_charppfc;|Acc_delay(p,f)->output_accppfp;fppf;|Acc_flushp->output_accppfp;pp_print_flushppf();|Acc_invalid_arg(p,msg)->output_accppfp;invalid_argmsg;|End_of_acc->()endletkfprintfkppf(CamlinternalFormatBasics.Format(fmt,_))=CamlinternalFormat.make_printf(funacc->Driver.output_accppfacc;kppf)End_of_accfmtletfprintfdocfmt=kfprintfignoredocfmtletkdprintfk(CamlinternalFormatBasics.Format(fmt,_))=CamlinternalFormat.make_printf(funacc->k(funppf->Driver.output_accppfacc))End_of_accfmtletdprintffmt=kdprintf(funi->i)fmtletdoc_printffmt=letppf=refDoc.emptyinkfprintf(fun_->letdoc=!ppfinppf:=Doc.empty;doc)ppffmtletkdoc_printfkfmt=letppf=refDoc.emptyinkfprintf(funppf->letdoc=!ppfinppf:=Doc.empty;kdoc)ppffmtletdoc_printerfxdoc=letr=refdocinfrx;!rtype'aformat_printer=Format.formatter->'a->unitletformat_printerfppfx=letdoc=doc_printerfxDoc.emptyinDoc.formatppfdocletcompat=format_printerletcompat1fp1=compat(fp1)letcompat2fp1p2=compat(fp1p2)letkasprintfkfmt=kdoc_printf(fundoc->k(Format.asprintf"%a"Doc.formatdoc))fmtletasprintffmt=kasprintfFun.idfmtletpp_print_iter?(pp_sep=pp_print_cut)itereltppfc=letsep=doc_printerpp_sep()inppf:=Doc.iter~sep~iter(doc_printerelt)c!ppfletpp_print_list?(pp_sep=pp_print_cut)eltppfl=ppf:=Doc.list~sep:(doc_printerpp_sep())(doc_printerelt)l!ppfletpp_print_array?pp_sepeltppfa=pp_print_iter?pp_sepArray.itereltppfaletpp_print_seq?pp_sepeltppfs=pp_print_iter?pp_sepSeq.itereltppfsletpp_print_option?(none=fun_()->())eltppfo=ppf:=Doc.option~none:(doc_printernone())(doc_printerelt)o!ppfletpp_print_result~ok~errorppfr=ppf:=Doc.result~ok:(doc_printerok)~error:(doc_printererror)r!ppf# 467 "caml_format_doc.cppo.ml"letcommappf()=fprintfppf",@ "letpp_two_columns?(sep="|")?max_linesppf(lines:(string*string)list)=letleft_column_size=List.fold_left(funacc(s,_)->maxacc(String.lengths))0linesinletlines_nb=List.lengthlinesinletellipsed_first,ellipsed_last=matchmax_lineswith|Somemax_lineswhenlines_nb>max_lines->letprinted_lines=max_lines-1in(* the ellipsis uses one line *)letlines_before=printed_lines/2+printed_linesmod2inletlines_after=printed_lines/2in(lines_before,lines_nb-lines_after-1)|_->(-1,-1)infprintfppf"@[<v>";List.iteri(funk(line_l,line_r)->ifk=ellipsed_firstthenfprintfppf"...@,";ifellipsed_first<=k&&k<=ellipsed_lastthen()elsefprintfppf"%*s %s %s@,"left_column_sizeline_lsepline_r)lines;fprintfppf"@]"letdeprecated_printerprppf=ppf:=Doc.add!ppf(Doc.Deprecatedpr)