package spin

  1. Overview
  2. Docs

Source file cli.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
(* Generated by: ocaml-crunch
   Creation date: Sat, 17 May 2025 12:17:08 GMT *)

module Internal = struct
  let d_126c106439ecef414cc16ef9a17ba51b = "# This file is generated by dune, edit dune-project instead\nopam-version: \"2.0\"\nsynopsis: \"{{ project_description }}\"\ndescription: \"\"\"\n{{ project_description }}\n\"\"\"\nmaintainer: [\"{{ author_name }}{% if author_email %} <{{ author_email }}>{% endif %}\"]\nauthors: [\"{{ author_name }}{% if author_email %} <{{ author_email }}>{% endif %}\"]\nlicense: \"ISC\"\n{%- if github_username %}\nhomepage: \"https://github.com/{{ github_username }}/{{ project_slug }}\"\ndoc: \"https://{{ github_username }}.github.io/{{ project_slug }}\"\nbug-reports: \"https://github.com/{{ github_username }}/{{ project_slug }}/issues\"{% endif %}\ndepends: [\n  \"ocaml\" {>= \"4.08.0\"}\n  \"dune\" {>= \"2.0\"}\n  {% if test_framework == 'Alcotest' -%}\n  \"alcotest\" {with-test}\n  {% endif -%}\n  \"odoc\" {with-doc}\n  \"cmdliner\"\n  \"logs\"\n  \"fmt\"\n]\nbuild: [\n  [\"dune\" \"subst\"] {dev}\n  [\n    \"dune\"\n    \"build\"\n    \"-p\"\n    name\n    \"-j\"\n    jobs\n    \"@install\"\n    \"@runtest\" {with-test}\n    \"@doc\" {with-doc}\n  ]\n]\n{%- if github_username %}\ndev-repo: \"git+https://github.com/{{ github_username }}/{{ project_slug }}.git\"{% endif %}\n"

  let d_22f1e8d2bd4fd0a290ac82c907d71189 = "open Cmdliner\n\nmodule Syntax = struct\n  let ( let+ ) t f = Term.(const f $ t)\n\n  let ( and+ ) a b = Term.(const (fun x y -> x, y) $ a $ b)\nend\n\nopen Syntax\n\nlet envs =\n  [ Term.env_info\n      \"{{ project_snake | upper }}_CACHE_DIR\"\n      ~doc:\n        \"The directory where the application data is stored.\"\n  ; Term.env_info\n      \"{{ project_snake | upper }}_CONFIG_DIR\"\n      ~doc:\"The directory where the configuration files are stored.\"\n  ]\n\nlet term =\n  let+ log_level =\n    let env = Arg.env_var \"{{ project_snake | upper }}_VERBOSITY\" in\n    Logs_cli.level ~docs:Manpage.s_common_options ~env ()\n  in\n  Fmt_tty.setup_std_outputs ();\n  Logs.set_level log_level;\n  Logs.set_reporter (Logs_fmt.reporter ~app:Fmt.stdout ());\n  0\n\nlet error_to_code = function `Missing_env_var _ -> 4\n\nlet handle_errors = function\n  | Ok () ->\n    if Logs.err_count () > 0 then 3 else 0\n  | Error err ->\n    Logs.err (fun m -> m \"%s\" ({{ project_snake | capitalize }}.Error.to_string err));\n    error_to_code err\n\nlet exits =\n  Term.exit_info 3 ~doc:\"on indiscriminate errors reported on stderr.\"\n  :: Term.exit_info 4 ~doc:\"on missing required environment variable.\"\n  :: Term.default_exits\n"

  let d_2318656bdaa033c87c91d116c51fd3af = "# cli\n\nCommand Line Interface releasable on Opam.\n\n```bash\nspin new cli\n```\n\n## Acknowledgments\n\nThis template is inspired by these awesome projects:\n\n- [fnm](https://github.com/Schniz/fnm) - Fast and simple Node.js version manager, built in native ReasonML\n"

  let d_232f8de0122b147e7511bfc39bc622be = "val config_dir : (string, Error.t) Result.t\n\nval cache_dir : (string, Error.t) Result.t\n"

  let d_3699b1b25bf8d1f82822212e726b8623 = "(** {{ project_description }} *)\n\nmodule Config = Config\nmodule Error = Error\n\nval greet : string -> string\n(** Returns a greeting message.\n\n    {4 Examples}\n\n    {[ print_endline @@ greet \"Jane\" ]} *)\n"

  let d_3ab7b4fdeb295bfdf7a00bba957c1829 = "# Contributing\n\n## Setup your development environment\n\nYou need Opam, you can install it by following [Opam's documentation](https://opam.ocaml.org/doc/Install.html).\n\nWith Opam installed, you can install the dependencies with:\n\nWith Opam installed, you can install the dependencies in a new local switch with:\n\n```bash\nmake switch\n```\n\nOr globally, with:\n\n```bash\nmake deps\n```\n\nThen, build the project with:\n\n```bash\nmake build\n```\n\n### Running Binary\n\nAfter building the project, you can run the main binary that is produced.\n\n```bash\nmake start\n```\n\n### Running Tests\n\nYou can run the test compiled executable:\n\n```bash\nmake test\n```\n\n### Building documentation\n\nDocumentation for the libraries in the project can be generated with:\n\n```bash\nmake doc\nmake servedoc\n```\n\n### Releasing\n\nTo create a release and publish it on Opam, first update the `CHANGES.md` file with the last changes and the version that you want to release.\nThe, you can run the script `script/release.sh`. The script will perform the following actions:\n\n- Create a tag with the version found in `{{ project_slug }}.opam`, and push it to your repository.\n- Create the distribution archive.\n- Publish the distribution archive to a GitHub Release.\n- Submit a PR on Opam's repository.\n\nWhen the release is published on GitHub, the CI/CD will trigger the `Release` workflow which will compile binaries for all supported platforms and add them to the GitHub Release as assets.\n\n### Repository Structure\n\nThe following snippet describes {{ project_name }}'s repository structure.\n\n```text\n.\n\226\148\156\226\148\128\226\148\128 .github/\n|   Contains GitHub specific files such as actions definitions and issue templates.\n\226\148\130\n\226\148\156\226\148\128\226\148\128 bin/\n|   Source for {{ project_name }}'s binary. This links to the library defined in `lib/`.\n\226\148\130\n\226\148\156\226\148\128\226\148\128 lib/\n|   Source for {{ project_name }}'s library. Contains {{ project_name }}'s core functionnalities.\n\226\148\130\n\226\148\156\226\148\128\226\148\128 test/\n|   Unit tests and integration tests for {{ project_name }}.\n\226\148\130\n\226\148\156\226\148\128\226\148\128 dune-project\n|   Dune file used to mark the root of the project and define project-wide parameters.\n|   For the documentation of the syntax, see https://dune.readthedocs.io/en/stable/dune-files.html#dune-project\n\226\148\130\n\226\148\156\226\148\128\226\148\128 LICENSE\n\226\148\130\n\226\148\156\226\148\128\226\148\128 Makefile\n|   Make file containing common development command.\n\226\148\130\n\226\148\156\226\148\128\226\148\128 README.md\n\226\148\130\n\226\148\148\226\148\128\226\148\128 {{ project_slug }}.opam\n    Opam package definition.\n    To know more about creating and publishing opam packages, see https://opam.ocaml.org/doc/Packaging.html.\n```\n"

  let d_3c6b83be7e6bc15adf1c7f44c7b5a92d = "(executable\n (name main)\n (public_name {{ project_slug }})\n (libraries {{ project_snake }} cmdliner fmt fmt.tty logs.fmt logs.cli))\n\n(include_subdirs unqualified)\n"

  let d_4a6b717262c929df20917921147a80fb = "type t = [ `Missing_env_var of string ]\n\nlet to_string = function\n  | `Missing_env_var s ->\n    Printf.sprintf\n      \"The environment variable %S is needed, but could not be found in \\\n       your environment.\\n\\\n       Hint: Try setting it and run the program again.\"\n      s\n\nlet missing_env env = `Missing_env_var env\n"

  let d_5514c79426ac805d4ce99f659478ddec = ".DEFAULT_GOAL := all\n\nARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))\n$(eval $(ARGS):;@:)\n\n.PHONY: all\nall:\n\topam exec -- dune build --root . @install\n\n.PHONY: deps\ndeps: ## Install development dependencies\n\topam install -y dune-release ocamlformat utop ocaml-lsp-server\n\topam install --deps-only --with-test --with-doc -y .\n\n.PHONY: create_switch\ncreate_switch: ## Create an opam switch without any dependency\n\topam switch create . --no-install -y\n\n.PHONY: switch\nswitch: ## Create an opam switch and install development dependencies\n\topam install . --deps-only --with-doc --with-test\n\topam install -y dune-release ocamlformat utop ocaml-lsp-server\n\n.PHONY: lock\nlock: ## Generate a lock file\n\topam lock -y .\n\n.PHONY: build\nbuild: ## Build the project, including non installable libraries and executables\n\topam exec -- dune build --root .\n\n.PHONY: install\ninstall: all ## Install the packages on the system\n\topam exec -- dune install --root .\n\n.PHONY: start\nstart: all ## Run the produced executable\n\topam exec -- dune exec --root . bin/main.exe $(ARGS)\n\n.PHONY: test\ntest: ## Run the unit tests\n\topam exec -- dune runtest --root .\n\n.PHONY: clean\nclean: ## Clean build artifacts and other generated files\n\topam exec -- dune clean --root .\n\n.PHONY: doc\ndoc: ## Generate odoc documentation\n\topam exec -- dune build --root . @doc\n\n.PHONY: servedoc\nservedoc: doc ## Open odoc documentation with default web browser\n\topen _build/default/_doc/_html/index.html\n\n.PHONY: fmt\nfmt: ## Format the codebase with ocamlformat\n\topam exec -- dune build --root . --auto-promote @fmt\n\n.PHONY: watch\nwatch: ## Watch for the filesystem and rebuild on every change\n\topam exec -- dune build --root . --watch\n\n.PHONY: utop\nutop: ## Run a REPL and link with the project's libraries\n\topam exec -- dune utop --root . lib -- -implicit-bindings\n\n.PHONY: release\nrelease: all ## Run the release script \n\topam exec -- dune-release tag\n\topam exec -- dune-release distrib\n\topam exec -- dune-release publish distrib -y\n\topam exec -- dune-release opam pkg\n\topam exec -- dune-release opam submit --no-auto-open -y\n"

  let d_5756996243218d65c8e4e6d829d9af5e = "open Cmdliner\n\nlet cmds = [ Cmd_hello.cmd ]\n\n(* Command line interface *)\n\nlet doc = \"{{ project_description }}\"\n\nlet sdocs = Manpage.s_common_options\n\nlet exits = Common.exits\n\nlet envs = Common.envs\n\nlet man =\n  [ `S Manpage.s_description\n  ; `P \"{{ project_description }}\"\n  ; `S Manpage.s_commands\n  ; `S Manpage.s_common_options\n  ; `S Manpage.s_exit_status\n  ; `P \"These environment variables affect the execution of $(mname):\"\n  ; `S Manpage.s_environment\n  ; `S Manpage.s_bugs\n  ; `P \"File bug reports at $(i,%%{% raw %}PKG_ISSUE{% endraw %}S%%)\"\n  ; `S Manpage.s_authors\n  {%- if github_username %}\n  ; `P \"{{ author_name }}, $(i,https://github.com/{{ github_username }})\"\n  {%- endif %}\n  ]\n\nlet default_cmd =\n  let term =\n    let open Common.Syntax in\n    Term.ret\n    @@ let+ _ = Common.term in\n       `Help (`Pager, None)\n  in\n  let info = Term.info \"{{ project_slug }}\" ~version:\"%%{% raw %}VERSION{% endraw %}%%\" ~doc ~sdocs ~exits ~man ~envs in\n  term, info\n\nlet () = Term.(exit_status @@ eval_choice default_cmd cmds)\n"

  let d_5764f2d054d97724a34a02acb8013f44 = "val term : int Cmdliner.Term.t\n\nval handle_errors : (unit, {{ project_snake | capitalize }}.Error.t) Result.t -> int\n\nval envs : Cmdliner.Term.env_info list\n\nval exits : Cmdliner.Term.exit_info list\n\nmodule Syntax : sig\n  val ( let+ ) : 'a Cmdliner.Term.t -> ('a -> 'b) -> 'b Cmdliner.Term.t\n\n  val ( and+ )\n    :  'a Cmdliner.Term.t\n    -> 'b Cmdliner.Term.t\n    -> ('a * 'b) Cmdliner.Term.t\nend\n"

  let d_62699c3200122adae9b1c8d730e6437a = "# {{ project_name }}\n\n{%- if ci_cd == 'GitHub' and github_username %}\n\n[![Actions Status](https://github.com/{{ github_username }}/{{ project_slug }}/workflows/CI/badge.svg)](https://github.com/{{ github_username }}/{{ project_slug }}/actions)\n{%- endif %}\n\n{%- if project_description %}\n\n{{ project_description }}\n{%- endif %}\n\n## Features\n\n- Available on all major platform (Windows, Linux and Windows)\n\n## Installation\n\n### Using Opam\n\n```bash\nopam install {{ project_slug }}\n```\n\n### Using a script\n\n```bash\ncurl -fsSL https://github.com/{{ github_username }}/{{ project_slug }}/raw/main/script/install.sh | bash\n```\n\n## Usage\n\n### `{{ project_slug }} hello NAME`\n\nGreets the name given in argument.\n\n## Contributing\n\nTake a look at our [Contributing Guide](CONTRIBUTING.md).\n"

  let d_71238ee3cbdefc630d68a6afb8911229 = "let run ~name =\n  let greeting = {{ project_snake | capitalize }}.greet name in\n  Logs.app (fun m -> m \"%s\" greeting);\n  Ok ()\n\n(* Command line interface *)\n\nopen Cmdliner\n\nlet doc = \"Print \\\"Hello World!\\\"\"\n\nlet sdocs = Manpage.s_common_options\n\nlet exits = Common.exits\n\nlet envs = Common.envs\n\nlet man =\n  [ `S Manpage.s_description\n  ; `P \"$(tname) prints a hello world message on the standard output.\"\n  ]\n\nlet info = Term.info \"hello\" ~doc ~sdocs ~exits ~envs ~man\n\nlet term =\n  let open Common.Syntax in\n  let+ _term = Common.term\n  and+ name =\n    let doc = \"The name to greet.\" in\n    let docv = \"NAME\" in\n    Arg.(required & pos 0 (some string) None & info [] ~doc ~docv)\n  in\n  run ~name |> Common.handle_errors\n\nlet cmd = term, info\n"

  let d_bda6604583b87f0d8508780cbb13aba8 = "(lang dune 2.0)\n\n(name {{ project_slug }})\n\n{% if github_username %}(documentation \"https://{{ github_username }}.github.io/{{ project_slug }}/\"){% endif %}\n\n{% if github_username %}(source\n (github {{ github_username }}/{{ project_slug }})){% endif %}\n\n(license ISC)\n\n(authors\n  \"{{ author_name }}{% if author_email %} <{{ author_email }}>{% endif %}\")\n\n(maintainers\n  \"{{ author_name }}{% if author_email %} <{{ author_email }}>{% endif %}\")\n\n(generate_opam_files true)\n\n(package\n (name {{ project_slug }})\n (synopsis \"{{ project_description }}\")\n (description \"{{ project_description }}\")\n (depends\n  (ocaml (>= 4.08.0))\n  dune\n  {%- if test_framework == 'Alcotest' %}\n  (alcotest :with-test)\n  {%- endif %}\n  (odoc :with-doc)\n  cmdliner\n  logs\n  fmt))\n"

  let d_c5e3bc82986f12e30d922e8b8789d21c = "let home =\n  let env_var = match Sys.os_type with \"Unix\" -> \"HOME\" | _ -> \"APPDATA\" in\n  Sys.getenv_opt env_var |> Option.to_result ~none:(Error.missing_env env_var)\n\nlet default_cache_dir =\n  Result.map (fun home ->\n      \"{{ project_slug }}\" |> Filename.concat \".cache\" |> Filename.concat home) home\n\nlet default_config_dir =\n  Result.map (fun home ->\n      \"{{ project_slug }}\" |> Filename.concat \".config\" |> Filename.concat home) home\n\nlet cache_dir =\n  Sys.getenv_opt \"{{ project_snake | upper }}_CACHE_DIR\"\n  |> Option.map Result.ok\n  |> Option.value ~default:default_cache_dir\n\nlet config_dir =\n  Sys.getenv_opt \"{{ project_snake | upper }}_CONFIG_DIR\"\n  |> Option.map Result.ok\n  |> Option.value ~default:default_config_dir\n"

  let d_d13e63e3b5891ec438bbe31f895c2261 = "(inherit (official bin))\n\n(name cli)\n(description \"Command Line Interface releasable on Opam\")\n"

  let d_d84e8136c845d75740e447453ad3d396 = "module Config = Config\nmodule Error = Error\n\nlet greet name = \"Hello \" ^ name ^ \"!\"\n"

  let d_fcade8234f18f97bc2f9849f18a6bbc0 = "type t = [ `Missing_env_var of string ]\n\nval to_string : t -> string\n\nval missing_env : string -> t\n"

  let file_chunks = function
    | "README.md" | "/README.md" -> Some [ d_2318656bdaa033c87c91d116c51fd3af; ]
    | "spin" | "/spin" -> Some [ d_d13e63e3b5891ec438bbe31f895c2261; ]
    | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some [ d_3ab7b4fdeb295bfdf7a00bba957c1829; ]
    | "template/Makefile" | "/template/Makefile" -> Some [ d_5514c79426ac805d4ce99f659478ddec; ]
    | "template/README.md" | "/template/README.md" -> Some [ d_62699c3200122adae9b1c8d730e6437a; ]
    | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some [ d_71238ee3cbdefc630d68a6afb8911229; ]
    | "template/bin/common.ml" | "/template/bin/common.ml" -> Some [ d_22f1e8d2bd4fd0a290ac82c907d71189; ]
    | "template/bin/common.mli" | "/template/bin/common.mli" -> Some [ d_5764f2d054d97724a34a02acb8013f44; ]
    | "template/bin/dune" | "/template/bin/dune" -> Some [ d_3c6b83be7e6bc15adf1c7f44c7b5a92d; ]
    | "template/bin/main.ml" | "/template/bin/main.ml" -> Some [ d_5756996243218d65c8e4e6d829d9af5e; ]
    | "template/dune-project" | "/template/dune-project" -> Some [ d_bda6604583b87f0d8508780cbb13aba8; ]
    | "template/lib/config.ml" | "/template/lib/config.ml" -> Some [ d_c5e3bc82986f12e30d922e8b8789d21c; ]
    | "template/lib/config.mli" | "/template/lib/config.mli" -> Some [ d_232f8de0122b147e7511bfc39bc622be; ]
    | "template/lib/error.ml" | "/template/lib/error.ml" -> Some [ d_4a6b717262c929df20917921147a80fb; ]
    | "template/lib/error.mli" | "/template/lib/error.mli" -> Some [ d_fcade8234f18f97bc2f9849f18a6bbc0; ]
    | "template/lib/{{ project_snake }}.ml" | "/template/lib/{{ project_snake }}.ml" -> Some [ d_d84e8136c845d75740e447453ad3d396; ]
    | "template/lib/{{ project_snake }}.mli" | "/template/lib/{{ project_snake }}.mli" -> Some [ d_3699b1b25bf8d1f82822212e726b8623; ]
    | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some [ d_126c106439ecef414cc16ef9a17ba51b; ]
    | _ -> None

  let file_list = [ "README.md"; "spin"; "template/CONTRIBUTING.md"; "template/Makefile"; "template/README.md"; "template/bin/commands/cmd_hello.ml"; "template/bin/common.ml"; "template/bin/common.mli"; "template/bin/dune"; "template/bin/main.ml"; "template/dune-project"; "template/lib/config.ml"; "template/lib/config.mli"; "template/lib/error.ml"; "template/lib/error.mli"; "template/lib/{{ project_snake }}.ml"; "template/lib/{{ project_snake }}.mli"; "template/{{ project_slug }}.opam"; ]
end

let file_list = Internal.file_list

let read name =
  match Internal.file_chunks name with
  | None -> None
  | Some c -> Some (String.concat "" c)

let hash = function
  | "README.md" | "/README.md" -> Some "2318656bdaa033c87c91d116c51fd3af"
  | "spin" | "/spin" -> Some "d13e63e3b5891ec438bbe31f895c2261"
  | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some "3ab7b4fdeb295bfdf7a00bba957c1829"
  | "template/Makefile" | "/template/Makefile" -> Some "5514c79426ac805d4ce99f659478ddec"
  | "template/README.md" | "/template/README.md" -> Some "62699c3200122adae9b1c8d730e6437a"
  | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some "71238ee3cbdefc630d68a6afb8911229"
  | "template/bin/common.ml" | "/template/bin/common.ml" -> Some "22f1e8d2bd4fd0a290ac82c907d71189"
  | "template/bin/common.mli" | "/template/bin/common.mli" -> Some "5764f2d054d97724a34a02acb8013f44"
  | "template/bin/dune" | "/template/bin/dune" -> Some "3c6b83be7e6bc15adf1c7f44c7b5a92d"
  | "template/bin/main.ml" | "/template/bin/main.ml" -> Some "5756996243218d65c8e4e6d829d9af5e"
  | "template/dune-project" | "/template/dune-project" -> Some "bda6604583b87f0d8508780cbb13aba8"
  | "template/lib/config.ml" | "/template/lib/config.ml" -> Some "c5e3bc82986f12e30d922e8b8789d21c"
  | "template/lib/config.mli" | "/template/lib/config.mli" -> Some "232f8de0122b147e7511bfc39bc622be"
  | "template/lib/error.ml" | "/template/lib/error.ml" -> Some "4a6b717262c929df20917921147a80fb"
  | "template/lib/error.mli" | "/template/lib/error.mli" -> Some "fcade8234f18f97bc2f9849f18a6bbc0"
  | "template/lib/{{ project_snake }}.ml" | "/template/lib/{{ project_snake }}.ml" -> Some "d84e8136c845d75740e447453ad3d396"
  | "template/lib/{{ project_snake }}.mli" | "/template/lib/{{ project_snake }}.mli" -> Some "3699b1b25bf8d1f82822212e726b8623"
  | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some "126c106439ecef414cc16ef9a17ba51b"
  | _ -> None

let size = function
  | "README.md" | "/README.md" -> Some 258
  | "spin" | "/spin" -> Some 95
  | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some 2496
  | "template/Makefile" | "/template/Makefile" -> Some 2095
  | "template/README.md" | "/template/README.md" -> Some 780
  | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some 745
  | "template/bin/common.ml" | "/template/bin/common.ml" -> Some 1176
  | "template/bin/common.mli" | "/template/bin/common.mli" -> Some 397
  | "template/bin/dune" | "/template/bin/dune" -> Some 163
  | "template/bin/main.ml" | "/template/bin/main.ml" -> Some 1035
  | "template/dune-project" | "/template/dune-project" -> Some 756
  | "template/lib/config.ml" | "/template/lib/config.ml" -> Some 733
  | "template/lib/config.mli" | "/template/lib/config.mli" -> Some 88
  | "template/lib/error.ml" | "/template/lib/error.ml" -> Some 321
  | "template/lib/error.mli" | "/template/lib/error.mli" -> Some 100
  | "template/lib/{{ project_snake }}.ml" | "/template/lib/{{ project_snake }}.ml" -> Some 84
  | "template/lib/{{ project_snake }}.mli" | "/template/lib/{{ project_snake }}.mli" -> Some 202
  | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some 1080
  | _ -> None
OCaml

Innovation. Community. Security.