ocaml-ppx / ocamlformat

Auto-formatter for OCaml code
MIT License
621 stars 174 forks source link

No support for default custom config? #2534

Open dunric opened 6 months ago

dunric commented 6 months ago

How can I have my default (fallback) configuration settings for ocamlformat when no per-project's one is present?

I may be missing something or it has been chosen some weird logic for ocamlformat behavior, but it seems when it detects project's root - even a false one by a sole presence of .git or .hg subdir - it doesn't pick global/default config at $XDG_CONFIG_HOME/ocamlformat or $HOME/.config/ocamlformat when local .ocamlformat is missing and --enable-outside-detected-project option is passed.

This effectively forces one to manually copy or symlink global config for each and every project to use his preferred formatting options, which I would consider tedious and unreasonable practice.

Likely related issues #2039 and #2223 .

dunric commented 6 months ago

Hmm, it is somehow silent here …

A quick-hack solution follows, for cases when a project's root is "detected" and none project's configuration file is found. Equivalent to undetected project's root (and no config file found).

diff --git a/lib/bin_conf/File_system.ml b/lib/bin_conf/File_system.ml
index 7e1cb5f..10e8991 100644
--- a/lib/bin_conf/File_system.ml
+++ b/lib/bin_conf/File_system.ml
@@ -64,7 +64,6 @@ let make ~enable_outside_detected_project ~disable_conf_files
         (* 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_none fs.project_root) ;
         if
           List.is_empty fs.configuration_files
           && enable_outside_detected_project
@@ -104,8 +103,11 @@ let make ~enable_outside_detected_project ~disable_conf_files
         in
         (* Inside a detected project, configs are applied in top-down
            starting from the project root (i.e. excluding the global config
-           file). *)
-        if is_project_root ~root dir then {fs with project_root= Some dir}
+           file).
+           In case of none config detected, attempt to fall back to a global
+           one. *)
+        if is_project_root ~root dir then
+          aux {fs with project_root= Some dir} ~segs:[]
         else aux fs ~segs:upper_segs
   in
   aux ~segs

I'm quite new to OCaml and don't quite understand some design decisions, like why anyone would need multiple per-directory formatting options and merge them together instead of a single per-project one. Similar with dune build system and questionable benefits to specify separate build stanzas instead of writing one, common for a project.