Source file File_system.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
let project_root_witness = [".git"; ".hg"; "dune-project"]
let is_project_root ~root dir =
match root with
| Some root -> Fpath.equal dir root
| None ->
List.exists project_root_witness ~f:(fun name ->
Fpath.(exists (dir / name)) )
let dot_ocp_indent = ".ocp-indent"
let dot_ocamlformat = ".ocamlformat"
let dot_ocamlformat_ignore = ".ocamlformat-ignore"
let dot_ocamlformat_enable = ".ocamlformat-enable"
type configuration_file = Ocamlformat of Fpath.t | Ocp_indent of Fpath.t
let root_ocamlformat_file ~root =
let root = Option.value root ~default:(Fpath.cwd ()) in
Fpath.(root / dot_ocamlformat)
let xdg_config () =
let xdg_config_home =
match Stdlib.Sys.getenv_opt "XDG_CONFIG_HOME" with
| None | Some "" -> (
match Stdlib.Sys.getenv_opt "HOME" with
| None | Some "" -> None
| Some home -> Some Fpath.(v home / ".config") )
| Some xdg_config_home -> Some (Fpath.v xdg_config_home)
in
match xdg_config_home with
| Some xdg_config_home ->
let filename = Fpath.(xdg_config_home / "ocamlformat") in
if Fpath.exists filename then Some filename else None
| None -> None
type t =
{ ignore_files: Fpath.t list
; enable_files: Fpath.t list
; configuration_files: configuration_file list
; project_root: Fpath.t option }
let make ~enable_outside_detected_project ~disable_conf_files
~ocp_indent_config ~root ~file =
let dir = Fpath.(file |> split_base |> fst) in
let volume, dir = Fpath.split_volume dir in
let segs = Fpath.segs dir |> List.rev in
let rec aux fs ~segs =
match segs with
| [] | [""] ->
assert (Option.is_none fs.project_root) ;
if
List.is_empty fs.configuration_files
&& enable_outside_detected_project
then
match xdg_config () with
| Some xdg -> {fs with configuration_files= [Ocamlformat xdg]}
| None -> fs
else fs
| "" :: upper_segs -> aux fs ~segs:upper_segs
| _ :: upper_segs ->
let sep = Fpath.dir_sep in
let dir = Fpath.v (volume ^ String.concat ~sep (List.rev segs)) in
let fs =
{ fs with
ignore_files=
(let filename = Fpath.(dir / dot_ocamlformat_ignore) in
if Fpath.exists filename then filename :: fs.ignore_files
else fs.ignore_files )
; enable_files=
(let filename = Fpath.(dir / dot_ocamlformat_enable) in
if Fpath.exists filename then filename :: fs.enable_files
else fs.enable_files )
; configuration_files=
( if disable_conf_files then []
else
let f_1 = Fpath.(dir / dot_ocamlformat) in
let files =
if Fpath.exists f_1 then
Ocamlformat f_1 :: fs.configuration_files
else fs.configuration_files
in
if ocp_indent_config then
let f_2 = Fpath.(dir / dot_ocp_indent) in
if Fpath.exists f_2 then Ocp_indent f_2 :: files
else files
else files ) }
in
if is_project_root ~root dir then {fs with project_root= Some dir}
else aux fs ~segs:upper_segs
in
aux ~segs
{ ignore_files= []
; enable_files= []
; configuration_files= []
; project_root= None }
let has_ocamlformat_file fs =
List.exists fs.configuration_files ~f:(function
| Ocamlformat _ -> true
| Ocp_indent _ -> false )