123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107(*********************************************************************************)(* Dunolint - A tool to lint and help manage files in dune projects *)(* Copyright (C) 2024-2025 Mathieu Barbin <mathieu.barbin@gmail.com> *)(* *)(* This file is part of Dunolint. *)(* *)(* Dunolint is free software; you can redistribute it and/or modify it *)(* under the terms of the GNU Lesser General Public License as published by *)(* the Free Software Foundation either version 3 of the License, or any later *)(* version, with the LGPL-3.0 Linking Exception. *)(* *)(* Dunolint is distributed in the hope that it will be useful, but WITHOUT *)(* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *)(* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *)(* and the file `NOTICE.md` at the root of this repository for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* and the LGPL-3.0 Linking Exception along with this library. If not, see *)(* <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively. *)(*********************************************************************************)letsexpable_param(typea)(moduleM:Sexpable.Swithtypet=a)=letmoduleValidate=structtypet=aletof_stringstr=tryOk(Parsexp.Single.parse_string_exnstr|>M.t_of_sexp)with|exn->Error(`Msg(Exn.to_stringexn));;letto_stringt=(* This would be used to print default value, currently not exercised. *)Sexp.to_string_mach(M.sexp_of_tt)[@coverageoff];;endinCommand.Param.validated_string(moduleValidate);;letbelow~doc=letopenCommand.StdinArg.named_opt["below"](Param.validated_string(moduleFpath))~docv:"PATH"~doc;;letskip_subtrees~globs=List.concat[List.mapglobs~f:Dunolint.Glob.v;List.concat_map~f:(funpat->[Dunolint.Glob.v("**/"^pat);Dunolint.Glob.vpat])[".git/";".hg/";"_build/";"_opam/";"_coverage/";"node_modules/";"doc/build/";".docusaurus/";"*.t/"]];;letdefault_skip_paths_config()=Dunolint.Config.V1.create[`skip_paths(skip_subtrees~globs:[])]|>Dunolint.Config.v1;;letenforce_rules_config~rules=matchruleswith|[]->None|_::_->Some(Dunolint.Config.V1.create(List.maprules~f:(funrule->`rulerule))|>Dunolint.Config.v1);;letroot=letopenCommand.Stdinlet+root=Arg.named_opt["root"](Param.validated_string(moduleFpath))~docv:"DIR"~doc:"Use this directory as dune workspace root instead of guessing it."inOption.maproot~f:(funroot->matchFpath.classifyrootwith|`Absolutepath->path|`Relativepath->letcwd=Unix.getcwd()|>Absolute_path.vinAbsolute_path.appendcwdpath);;letrelativize~workspace_root~cwd~path=letpath=Absolute_path.relativize~root:cwdpathinmatchAbsolute_path.chop_prefixpath~prefix:(workspace_root|>Workspace_root.path)with|Somerelative_path->relative_path|None->Err.raisePp.O.[Pp.text"Path "++Pp_tty.path(moduleAbsolute_path)path++Pp.text" is not in dune workspace."];;