123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120(**************************************************************************)(* *)(* OCamlFormat *)(* *)(* Copyright (c) Facebook, Inc. and its affiliates. *)(* *)(* This source code is licensed under the MIT license found in *)(* the LICENSE file in the root directory of this source tree. *)(* *)(**************************************************************************)letproject_root_witness=[".git";".hg";"dune-project"]letis_project_root~rootdir=matchrootwith|Someroot->Fpath.equaldirroot|None->List.existsproject_root_witness~f:(funname->Fpath.(exists(dir/name)))letdot_ocp_indent=".ocp-indent"letdot_ocamlformat=".ocamlformat"letdot_ocamlformat_ignore=".ocamlformat-ignore"letdot_ocamlformat_enable=".ocamlformat-enable"typeconfiguration_file=OcamlformatofFpath.t|Ocp_indentofFpath.tletroot_ocamlformat_file~root=letroot=Option.valueroot~default:(Fpath.cwd())inFpath.(root/dot_ocamlformat)letxdg_config()=letxdg_config_home=matchStdlib.Sys.getenv_opt"XDG_CONFIG_HOME"with|None|Some""->(matchStdlib.Sys.getenv_opt"HOME"with|None|Some""->None|Somehome->SomeFpath.(vhome/".config"))|Somexdg_config_home->Some(Fpath.vxdg_config_home)inmatchxdg_config_homewith|Somexdg_config_home->letfilename=Fpath.(xdg_config_home/"ocamlformat")inifFpath.existsfilenamethenSomefilenameelseNone|None->Nonetypet={ignore_files:Fpath.tlist;enable_files:Fpath.tlist;configuration_files:configuration_filelist;project_root:Fpath.toption}letmake~enable_outside_detected_project~disable_conf_files~ocp_indent_config~root~file=letdir=Fpath.(file|>split_base|>fst)inletvolume,dir=Fpath.split_volumedirinletsegs=Fpath.segsdir|>List.revinletrecauxfs~segs=matchsegswith|[]|[""]->(* Outside of a detected project, only apply the global config file
when [--enable-outside-detected-project] is set and no
[.ocamlformat] file has been found. *)assert(Option.is_nonefs.project_root);ifList.is_emptyfs.configuration_files&&enable_outside_detected_projectthenmatchxdg_config()with|Somexdg->{fswithconfiguration_files=[Ocamlformatxdg]}|None->fselsefs|""::upper_segs->auxfs~segs:upper_segs|_::upper_segs->letsep=Fpath.dir_sepinletdir=Fpath.v(volume^String.concat~sep(List.revsegs))inletfs={fswithignore_files=(letfilename=Fpath.(dir/dot_ocamlformat_ignore)inifFpath.existsfilenamethenfilename::fs.ignore_fileselsefs.ignore_files);enable_files=(letfilename=Fpath.(dir/dot_ocamlformat_enable)inifFpath.existsfilenamethenfilename::fs.enable_fileselsefs.enable_files);configuration_files=(ifdisable_conf_filesthen[]elseletf_1=Fpath.(dir/dot_ocamlformat)inletfiles=ifFpath.existsf_1thenOcamlformatf_1::fs.configuration_fileselsefs.configuration_filesinifocp_indent_configthenletf_2=Fpath.(dir/dot_ocp_indent)inifFpath.existsf_2thenOcp_indentf_2::fileselsefileselsefiles)}in(* Inside a detected project, configs are applied in top-down
starting from the project root (i.e. excluding the global config
file). *)ifis_project_root~rootdirthen{fswithproject_root=Somedir}elseauxfs~segs:upper_segsinaux~segs{ignore_files=[];enable_files=[];configuration_files=[];project_root=None}lethas_ocamlformat_filefs=List.existsfs.configuration_files~f:(function|Ocamlformat_->true|Ocp_indent_->false)