123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Helpers for Format} *)type'aiter=('a->unit)->unitincludeFormattypet=Format.formattertype-'aprinter=t->'a->unit(** {2 Combinators} *)letsilent_fmt_=()letreturnfmt_strout()=Format.fprintfout"%(%)"fmt_strletunitfmt()=Format.pp_print_stringfmt"()"letintfmti=Format.pp_print_stringfmt(string_of_inti)letstring=Format.pp_print_stringletbool=Format.pp_print_boolletfloat3fmtf=Format.fprintffmt"%.3f"fletfloatfmtf=Format.pp_print_stringfmt(string_of_floatf)letchar=Format.pp_print_charletint32fmtn=Format.fprintffmt"%ld"nletint64fmtn=Format.fprintffmt"%Ld"nletnativeintfmtn=Format.fprintffmt"%nd"nletstring_quotedfmts=Format.fprintffmt"\"%s\""sletflush=Format.pp_print_flushletspace=Format.pp_print_spaceletcut=Format.pp_print_cutletbreakfmt(m,n)=Format.pp_print_breakfmtmnletnewline=Format.pp_force_newlineletsubstringout(s,i,len):unit=stringout(String.subsilen)lettext=Format.pp_print_textletstring_linesout(s:string):unit=fprintfout"@[<v>";leti=ref0inletn=String.lengthsinwhile!i<ndoletj=tryString.index_froms!i'\n'withNot_found->ninif!i>0thenfprintfout"@,";substringout(s,!i,j-!i);i:=j+1done;fprintfout"@]"letlist?(sep=return",@ ")ppfmtl=letrecpp_listl=matchlwith|x::(_::_asl)->ppfmtx;sepfmt();pp_listl|[x]->ppfmtx|[]->()inpp_listlletarray?(sep=return",@ ")ppfmta=fori=0toArray.lengtha-1doifi>0thensepfmt();ppfmta.(i)doneletarrayi?(sep=return",@ ")ppfmta=fori=0toArray.lengtha-1doifi>0thensepfmt();ppfmt(i,a.(i))doneletseq?(sep=return",@ ")ppfmtseq=letfirst=reftrueinCCSeq.iter(funx->if!firstthenfirst:=falseelsesepfmt();ppfmtx)seqletiter?(sep=return",@ ")ppfmtseq=letfirst=reftrueinseq(funx->if!firstthenfirst:=falseelsesepfmt();ppfmtx)letoptppfmtx=matchxwith|None->Format.pp_print_stringfmt"none"|Somex->Format.fprintffmt"some %a"ppxletpair?(sep=return",@ ")ppappbfmt(a,b)=Format.fprintffmt"%a%a%a"ppaasep()ppbblettriple?(sep=return",@ ")ppappbppcfmt(a,b,c)=Format.fprintffmt"%a%a%a%a%a"ppaasep()ppbbsep()ppccletquad?(sep=return",@ ")ppappbppcppdfmt(a,b,c,d)=Format.fprintffmt"%a%a%a%a%a%a%a"ppaasep()ppbbsep()ppccsep()ppddletappendppappbfmt()=ppafmt();ppbfmt()letappend_lpplfmt()=List.iter(funpp->ppfmt())pplletwithinabpoutx=stringouta;poutx;stringoutbletmapfppfmtx=ppfmt(fx);()letvbox?(i=0)ppoutx=Format.pp_open_vboxouti;ppoutx;Format.pp_close_boxout()lethovbox?(i=0)ppoutx=Format.pp_open_hovboxouti;ppoutx;Format.pp_close_boxout()lethvbox?(i=0)ppoutx=Format.pp_open_hvboxouti;ppoutx;Format.pp_close_boxout()lethboxppoutx=Format.pp_open_hboxout();ppoutx;Format.pp_close_boxout()letof_to_stringfoutx=Format.pp_print_stringout(fx)letexn=of_to_stringPrintexc.to_stringletconstppxout()=ppoutxletsomeppout=function|None->()|Somex->ppoutxletconst_stringsout_=stringoutsletopaqueout_=stringout"opaque"letlazy_forceppout(lazyx)=ppoutxletlazy_or?(default=return"<lazy>")ppoutx=ifLazy.is_valxthenppout(Lazy.forcex)elsedefaultout()(** {2 IO} *)letoutputfmtppx=ppfmtxletto_stringppx=letbuf=Buffer.create64inletfmt=Format.formatter_of_bufferbufinppfmtx;Format.pp_print_flushfmt();Buffer.contentsbufletfprintf=Format.fprintfletstdout=Format.std_formatterletstderr=Format.err_formatterletof_chan=Format.formatter_of_out_channelletwith_out_chanocf=letfmt=of_chanocintryletx=ffmtinFormat.pp_print_flushfmt();xwithe->Format.pp_print_flushfmt();raiseeletteeab=letfa=Format.pp_get_formatter_out_functionsa()inletfb=Format.pp_get_formatter_out_functionsb()inFormat.make_formatter(funstrilen->fa.Format.out_stringstrilen;fb.Format.out_stringstrilen)(fun()->fa.Format.out_flush();fb.Format.out_flush())letto_filefilenameformat=letoc=open_outfilenameinletfmt=Format.formatter_of_out_channelocinFormat.kfprintf(funfmt->Format.pp_print_flushfmt();close_out_noerroc)fmtformatmoduleANSI_codes=structtypecolor=[`Black|`Red|`Yellow|`Green|`Blue|`Magenta|`Cyan|`White]letint_of_color_=function|`Black->0|`Red->1|`Green->2|`Yellow->3|`Blue->4|`Magenta->5|`Cyan->6|`White->7typestyle=[`FGofcolor(* foreground *)|`BGofcolor(* background *)|`Bold|`Reset]letcode_of_style:style->int=function|`FGc->30+int_of_color_c|`BGc->40+int_of_color_c|`Bold->1|`Reset->0letstring_of_stylea=Printf.sprintf"\x1b[%dm"(code_of_stylea)letclear_line="\x1b[2K\r"letreset=string_of_style`Resetletstring_of_style_list=function|[]->reset|[a]->string_of_stylea|[a;b]->Printf.sprintf"\x1b[%d;%dm"(code_of_stylea)(code_of_styleb)|[a;b;c]->Printf.sprintf"\x1b[%d;%d;%dm"(code_of_stylea)(code_of_styleb)(code_of_stylec)|l->letbuf=Buffer.create32inletpp_numc=Buffer.add_stringbuf(string_of_int(code_of_stylec))inBuffer.add_stringbuf"\x1b[";List.iteri(funic->ifi>0thenBuffer.add_charbuf';';pp_numc)l;Buffer.add_stringbuf"m";Buffer.contentsbufexceptionNo_such_style(* parse a string tag. *)letstyle_of_tag_s=matchString.trimswith|"reset"->[`Reset]|"black"->[`FG`Black]|"red"->[`FG`Red]|"green"->[`FG`Green]|"yellow"->[`FG`Yellow]|"blue"->[`FG`Blue]|"magenta"->[`FG`Magenta]|"cyan"->[`FG`Cyan]|"white"->[`FG`White]|"bold"->[`Bold]|"Black"->[`FG`Black;`Bold]|"Red"->[`FG`Red;`Bold]|"Green"->[`FG`Green;`Bold]|"Yellow"->[`FG`Yellow;`Bold]|"Blue"->[`FG`Blue;`Bold]|"Magenta"->[`FG`Magenta;`Bold]|"Cyan"->[`FG`Cyan;`Bold]|"White"->[`FG`White;`Bold]|_->raiseNo_such_styleendletcolor_enabled=reffalseletmark_open_styleststyle=Stack.pushstylest;if!color_enabledthenANSI_codes.string_of_style_liststyleelse""letmark_close_stylest:string=letstyle=tryignore(Stack.popst);(* pop current style (if well-scoped …) *)Stack.topst(* look at previous style *)withStack.Empty->[`Reset]inif!color_enabledthenANSI_codes.string_of_style_liststyleelse""typestag+=StyleofANSI_codes.stylelistletpp_open_tagouts=pp_open_stagout(String_tags)letpp_close_tagout()=pp_close_stagout()(* either prints the tag of [s] or delegate to [or_else] *)letmark_open_stagst~or_else(tag:stag):string=matchtagwith|Stylestyle->mark_open_styleststyle|String_tags->letopenANSI_codesin(tryletstyle=style_of_tag_sinmark_open_styleststylewithNo_such_style->or_elsetag)|_->or_elsetagletmark_close_stagst~or_else(tag:stag):string=matchtagwith|Style_->mark_close_stylest|String_tags->letopenANSI_codesin(* check if it's indeed about color *)(matchstyle_of_tag_swith|_->mark_close_stylest|exceptionNo_such_style->or_elsetag)|_->or_elsetagletwith_stylingstloutf=pp_open_stagout(Stylestl);tryletx=f()inpp_close_stagout();xwithe->pp_close_stagout();raiseeletstylingstlppoutx=with_stylingstlout@@fun()->ppoutx(* add color handling to formatter [ppf] *)letset_color_tag_handlingppf=letst=Stack.create()in(* stack of styles *)pp_set_mark_tagsppftrue;(* enable tags *)letfuns=pp_get_formatter_stag_functionsppf()inletfuns'={funswithmark_open_stag=mark_open_stagst~or_else:funs.mark_open_stag;mark_close_stag=mark_close_stagst~or_else:funs.mark_close_stag;}inpp_set_formatter_stag_functionsppffuns'letset_color_default=letfirst=reftrueinfunb->ifb&¬!color_enabledthen(color_enabled:=true;if!firstthen(first:=false;set_color_tag_handlingstdout;set_color_tag_handlingstderr))elseif(notb)&&!color_enabledthencolor_enabled:=falseletwith_colorsppoutx=pp_open_tagouts;ppoutx;pp_close_tagout()letwith_colorfsoutfmt=pp_open_tagouts;Format.kfprintf(funout->pp_close_tagout())outfmt(* c: whether colors are enabled *)letsprintf_cformat=letbuf=Buffer.create64inletfmt=Format.formatter_of_bufferbufinifc&&!color_enabledthenset_color_tag_handlingfmt;Format.kfprintf(fun_fmt->Format.pp_print_flushfmt();Buffer.contentsbuf)fmtformatletwith_color_ksf~fsfmt=letbuf=Buffer.create64inletout=Format.formatter_of_bufferbufinif!color_enabledthenset_color_tag_handlingout;pp_open_tagouts;Format.kfprintf(funout->pp_close_tagout();Format.pp_print_flushout();f(Buffer.contentsbuf))outfmtletwith_color_sfsfmt=with_color_ksf~f:(funs->s)sfmtletsprintffmt=sprintf_truefmtletsprintf_no_colorfmt=sprintf_falsefmtletsprintf_dyn_color~colorsfmt=sprintf_colorsfmtletfprintf_dyn_color~colorsoutfmt=letold_tags=Format.pp_get_mark_tagsout()inFormat.pp_set_mark_tagsoutcolors;(* enable/disable tags *)Format.kfprintf(funout->Format.pp_set_mark_tagsoutold_tags)outfmtletksprintf?margin~ffmt=letbuf=Buffer.create32inletout=Format.formatter_of_bufferbufinif!color_enabledthenset_color_tag_handlingout;(matchmarginwith|None->()|Somem->pp_set_marginoutm);Format.kfprintf(fun_->Format.pp_print_flushout();f(Buffer.contentsbuf))outfmtmoduleDump=structtype'at='aprinterletunit=unitletint=intletstring=string_quotedletbool=boolletfloat=floatletchar=charletint32=int32letint64=int64letnativeint=nativeintletlistpp=within"[""]"(hovbox(list~sep:(return";@,")pp))letarraypp=within"[|""|]"(hovbox(array~sep:(return";@,")pp))letoptionppoutx=matchxwith|None->Format.pp_print_stringout"None"|Somex->Format.fprintfout"Some %a"ppxletpairp1p2=within"("")"(hovbox(pairp1p2))lettriplep1p2p3=within"("")"(hovbox(triplep1p2p3))letquadp1p2p3p4=within"("")"(hovbox(quadp1p2p3p4))letresult'pokperrorout=function|Okx->Format.fprintfout"(@[Ok %a@])"pokx|Errore->Format.fprintfout"(@[Error %a@])"perroreletresultpok=result'pokstringletto_string=to_stringendmoduleInfix=structlet(++)=appendendincludeInfix