package spin

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(* Generated by: ocaml-crunch
   Creation date: Sat, 17 May 2025 18:04:16 GMT *)

module Internal = struct
  let d_02ef1536addcb2e5f1f36b2fcd537fb1 = "#!/usr/bin/env node\n\nconst path = require(\"path\");\nconst cp = require(\"child_process\");\nconst fs = require(\"fs\");\n\nconst platform = process.platform;\n\nconst binariesToCopy = [\n  \"{{ project_slug }}\"\n];\n\nfunction find_arch() {\n  // The running binary is 64-bit, so the OS is clearly 64-bit.\n  if (process.arch === \"x64\") {\n    return \"x64\";\n  }\n\n  // All recent versions of Mac OS are 64-bit.\n  if (process.platform === \"darwin\") {\n    return \"x64\";\n  }\n\n  // On Windows, the most reliable way to detect a 64-bit OS from within a 32-bit\n  // app is based on the presence of a WOW64 file: %SystemRoot%\\SysNative.\n  // See: https://twitter.com/feross/status/776949077208510464\n  if (process.platform === \"win32\") {\n    var useEnv = false;\n    try {\n      useEnv = !!(process.env.SYSTEMROOT && fs.statSync(process.env.SYSTEMROOT));\n    } catch (err) { }\n\n    const sysRoot = useEnv ? process.env.SYSTEMROOT : \"C:\\\\Windows\";\n\n    // If %SystemRoot%\\SysNative exists, we are in a WOW64 FS Redirected application.\n    const isWOW64 = false;\n    try {\n      isWOW64 = !!fs.statSync(path.join(sysRoot, \"sysnative\"));\n    } catch (err) { }\n\n    return isWOW64 ? \"x64\" : \"x86\";\n  }\n\n  if (process.platform === \"linux\") {\n    const output = cp.execSync(\"getconf LONG_BIT\", { encoding: \"utf8\" });\n    return output === \"64\\n\" ? \"x64\" : \"x86\";\n  }\n\n  return \"x86\";\n}\n\n// Implementing it b/c we don\"t want to depend on fs.copyFileSync which appears only in node@8.x\nfunction copyFileSync(sourcePath, destPath) {\n  const data = fs.readFileSync(sourcePath);\n  const stat = fs.statSync(sourcePath);\n  fs.writeFileSync(destPath, data);\n  fs.chmodSync(destPath, stat.mode);\n}\n\nconst copyPlatformBinaries = platformPath => {\n  const platformBuildPath = path.join(__dirname, platformPath);\n\n  binariesToCopy.forEach(binaryPath => {\n    const sourcePath = path.join(platformBuildPath, binaryPath);\n    const destPath = path.join(__dirname, binaryPath);\n    if (fs.existsSync(destPath)) {\n      fs.unlinkSync(destPath);\n    }\n    copyFileSync(sourcePath, destPath);\n    fs.chmodSync(destPath, 0o755);\n  });\n};\n\nconst arch = find_arch();\n\nconst platformPath = \"platform-\" + platform + \"-\" + arch;\nconst supported = fs.existsSync(platformPath);\n\nif (!supported) {\n  console.error(\"{{ project_name }} does not support this platform :(\");\n  console.error(\"\");\n  console.error(\"If you want {{ project_name }} to support this platform natively,\");\n  console.error(\"please open an issue at our repository, linked above.\");\n  console.error(\"Specify that you are on the \" + platform + \" platform,\");\n  console.error(\"and on the \" + arch + \" architecture.\");\n  process.exit(1);\n}\n\ncopyPlatformBinaries(platformPath);\n"

  let d_22a4a727f14480a70c5b0ab38d5c0d99 = "(executable\n (name main)\n (public_name {{ project_slug }})\n (libraries {{ project_snake }} cmdliner fmt fmt.tty logs.fmt logs.cli)\n (flags (:standard -open StdLabels)))\n\n(include_subdirs unqualified)\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_28b54795ed6a2a415823691a9f91f984 = "ifeq (start,$(firstword $(MAKECMDGOALS)))\n  START_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))\n  $(eval $(START_ARGS):;@:)\nendif\n\n.PHONY: all\nall:\n\topam exec -- dune build @install\n\n.PHONY: dev\ndev:\n\topam install -y dune-release merlin ocamlformat utop\n\t{%- if test_framework == 'Rely' %}\n\topam pin add -y pastel https://github.com/facebookexperimental/reason-native.git\n\topam pin add -y cli https://github.com/facebookexperimental/reason-native.git\n\topam pin add -y file-context-printer https://github.com/facebookexperimental/reason-native.git\n\topam pin add -y rely https://github.com/facebookexperimental/reason-native.git\n\t{%- endif %}\n\topam install --deps-only --with-test --with-doc -y .\n\n.PHONY: build\nbuild:\n\topam exec -- dune build\n\n.PHONY: start\nstart: all\n\topam exec -- dune exec bin/main.exe $(START_ARGS)\n\n.PHONY: install\ninstall:\n\topam exec -- dune install\n\n.PHONY: test\ntest:\n\topam exec -- {% if test_framework == 'Rely' %}dune exec test/test_runner.exe{% else %}dune build @test/runtest -f{% endif %}\n\n.PHONY: clean\nclean:\n\topam exec -- dune clean\n\n.PHONY: doc\ndoc:\n\topam exec -- dune build @doc\n\n.PHONY: doc-path\ndoc-path:\n\t@echo \"_build/default/_doc/_html/index.html\"\n\n.PHONY: format\nformat:\n\topam exec -- dune build @fmt --auto-promote\n\n.PHONY: watch\nwatch:\n\topam exec -- dune build --watch\n\n.PHONY: utop\nutop:\n\topam exec -- dune utop lib -- -implicit-bindings\n\n.PHONY: release\nrelease:\n\topam exec -- sh script/release.sh\n"

  let d_4025396dfb5871ced6b8051264e10553 = "// @flow\n\nconst { execSync } = require(\"child_process\");\nconst fs = require(\"fs\");\nconst path = require(\"path\");\nconst package = require(\"../package.json\");\n\nconst filesToCopy = [\"LICENSE\", \"README.md\", \"CHANGES.md\"];\n\nfunction exec(cmd) {\n  console.log(`exec: ${cmd}`);\n  return execSync(cmd).toString();\n}\n\nfunction mkdirpSync(p) {\n  if (fs.existsSync(p)) {\n    return;\n  }\n  mkdirpSync(path.dirname(p));\n  fs.mkdirSync(p);\n}\n\nfunction removeSync(p) {\n  exec(`rm -rf \"${p}\"`);\n}\n\nconst src = path.resolve(path.join(__dirname, \"..\"));\nconst dst = path.resolve(path.join(__dirname, \"..\", \"_release\"));\n\nremoveSync(dst);\nmkdirpSync(dst);\n\nfor (const file of filesToCopy) {\n  const p = path.join(dst, file);\n  mkdirpSync(path.dirname(p));\n  fs.copyFileSync(path.join(src, file), p);\n}\n\nfs.copyFileSync(\n  path.join(src, \"scripts\", \"release-postinstall.js\"),\n  path.join(dst, \"postinstall.js\")\n);\n\nconst filesToTouch = [\n  \"{{ project_slug }}\"\n];\n\nfor (const file of filesToTouch) {\n  const p = path.join(dst, file);\n  mkdirpSync(path.dirname(p));\n  fs.writeFileSync(p, \"\");\n}\n\nconst pkgJson = {\n  name: \"@{{ npm_username }}/{{ project_slug }}\",\n  version: \"%%{% raw %}VERSION{% endraw %}%%\",\n  description: \"{{ project_description }}\",\n  author: \"{{ username }}{% if author_email %} <{{ author_email }}>{% endif %}\",\n  license: \"MIT\",\n  homepage: \"https://github.com/{{ github_username }}/{{ project_slug }}\",\n  bugs: {\n    url: \"https://github.com/{{ github_username }}/{{ project_slug }}/issues\"\n  },\n  repository: {\n    type: \"git\",\n    url: \"https://github.com/{{ github_username }}/{{ project_slug }}.git\"\n  },\n  scripts: {\n    postinstall: \"node postinstall.js\"\n  },\n  bin: {\n    {{ project_slug }}: \"{{ project_slug }}\"\n  },\n  files: [\n    \"platform-windows-x64/\",\n    \"platform-linux-x64/\",\n    \"platform-darwin-x64/\",\n    \"postinstall.js\",\n    \"{{ project_slug }}\"\n  ]\n};\n\nfs.writeFileSync(path.join(dst, \"package.json\"), JSON.stringify(pkgJson, null, 2));\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_59c6dd264f3f1cedbd780cfae987de91 = "# This file is generated by dune, edit dune-project instead\nopam-version: \"2.0\"\nsynopsis: \"{{ project_description }}\"\ndescription: \"\"\"\n{{ project_description }}\n\"\"\"\nmaintainer: [\"{{ username }}{% if author_email %} <{{ author_email }}>{% endif %}\"]\nauthors: [\"{{ username }}{% if author_email %} <{{ author_email }}>{% endif %}\"]\nlicense: \"MIT\"\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\"\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  {% if syntax == 'Reason' -%}\n  \"reason\" {build}\n  {% endif -%}\n  \"cmdliner\"\n  \"logs\"\n  \"fmt\"\n]\nbuild: [\n  [\"dune\" \"subst\"] {pinned}\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]\ndev-repo: \"git+https://github.com/{{ github_username }}/{{ project_slug }}.git\"\n"

  let d_7148e0f2df2646dae0de7bd72102d52e = "open {{ project_snake | capitalize }}\n\nlet run ~name =\n  Logs.app (fun m -> m \"Hello %s\" name);\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 \"{{ cmd_name }}\" ~doc ~sdocs ~exits ~envs ~man\n\nlet term =\n  let open Common.Let_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_71da466b0ad1679de495d5ccc69f3fc0 = "#!/bin/bash\n\nset -e\n\nif [ -d \".git\" ]; then\n  changes=$(git status --porcelain)\n  branch=$(git rev-parse --abbrev-ref HEAD)\n\n  if [ -n \"${changes}\" ]; then\n    echo \"Please commit staged files prior to bumping\"\n    exit 1\n  elif [ \"${branch}\" != \"master\" ]; then\n    echo \"Please run the release script on master\"\n    exit 1\n  else\n    {% if package_manager == 'Esy' %}esy x {% endif %}dune-release tag\n    {% if package_manager == 'Esy' %}esy x {% endif %}dune-release distrib\n    {% if package_manager == 'Esy' %}esy x {% endif %}dune-release publish distrib -y\n    {% if package_manager == 'Esy' %}esy x {% endif %}dune-release opam pkg\n    {% if package_manager == 'Esy' %}esy x {% endif %}dune-release opam submit --no-auto-open -y\n  fi\nelse\n  echo \"This project is not a git repository. Run `git init` first to be able to release.\"\n  exit 1\nfi\n"

  let d_7432831788782a1313cef2c92302d90e = "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 Let_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_7a530d2f879dd61a8fda0bb8d56eca1f = "(inherit (official bin))\n\n(name cli)\n(description \"Command Line Interface releasable on Opam\")\n\n(generator\n  (name cmd)\n  (description \"Generate a subcommand for the CLI.\")\n\n  (config cmd_name\n    (input (prompt \"Name of the subcommand\"))\n    (rules\n      (\"The command name must be a slug.\"\n        (eq :cmd_name (slugify :cmd_name)))))\n\n  (message (concat \n    \"You need to add `Cmd_\"\n    (snake_case :cmd_name)\n    \".cmd` to your list of commands in bin/main.\"\n    (if (eq OCaml :syntax) ml re)))\n\n  (post_gen\n    (actions\n      (refmt (concat bin/commands/cmd_ (snake_case :cmd_name) .ml)))\n    (enabled_if (eq :syntax Reason)))\n\n  (files\n    (main.ml (concat bin/commands/cmd_ (snake_case :cmd_name) .ml)))\n)\n"

  let d_811df803e12e793e593e57a7f773c38f = "# Contributing\n\n## Setup your development environment\n\n{% if package_manager == 'Esy' -%}\nYou need Esy, you can install the latest version from [npm](https://npmjs.com):\n\n```bash\nyarn global add esy@latest\n# Or\nnpm install -g esy@latest\n```\n\nThen run the `esy` command from this project root to install and build depenencies.\n\n```bash\nesy\n```\n\nThis project uses [Dune](https://dune.build/) as a build system, if you add a dependency in your `package.json` file, don't forget to add it to your `dune` and `dune-project` files too.\n{%- else -%}\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\n```bash\nmake dev\n```\n\nThen, build the project with:\n\n```bash\nmake build\n```\n{%- endif %}\n\n### Running Binary\n\nAfter building the project, you can run the main binary that is produced.\n\n{% if package_manager == 'Esy' -%}\n```bash\nesy start\n```\n{%- else %}\n```bash\nmake start\n```\n{%- endif %}\n\n### Running Tests\n\nYou can run the test compiled executable:\n\n{% if package_manager == 'Esy' -%}\n\n```bash\nesy test\n```\n{%- else %}\n```bash\nmake test\n```\n{%- endif %}\n\n### Building documentation\n\nDocumentation for the libraries in the project can be generated with:\n\n{% if package_manager == 'Esy' -%}\n```bash\nesy doc\nopen-cli $(esy doc-path)\n```\n\nThis assumes you have a command like [open-cli](https://github.com/sindresorhus/open-cli) installed on your system.\n\n> NOTE: On macOS, you can use the system command `open`, for instance `open $(esy doc-path)`\n{%- else %}\n```bash\nmake doc\nopen-cli $(make doc-path)\n```\n\nThis assumes you have a command like [open-cli](https://github.com/sindresorhus/open-cli) installed on your system.\n\n> NOTE: On macOS, you can use the system command `open`, for instance `open $(make doc-path)`\n{%- endif %}\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 perform the following actions\n\n- Compile binaries for all supported platforms.\n- Create an NPM release containing the pre-built binaries.\n- Publish the NPM release to the registry.\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{%- if package_manager == 'Esy' %}\n\226\148\156\226\148\128\226\148\128 package.json\n|   Esy package definition.\n|   To know more about creating Esy packages, see https://esy.sh/docs/en/configuration.html.\n{%- else %}\n\226\148\156\226\148\128\226\148\128 Makefile\n|   Make file containing common development command.\n{%- endif %}\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_82e14a8eb47f5c536aa98f7afd40af64 = "#!/bin/bash\n\nset -e\n\nINSTALL_DIR=\"/usr/local/bin\"\nRELEASE=\"latest\"\n\n# Parse Flags\nparse_args() {\n  while [[ $# -gt 0 ]]; do\n    key=\"$1\"\n\n    case $key in\n    -r | --release)\n      RELEASE=\"$2\"\n      shift # past release argument\n      shift # past release value\n      ;;\n    *)\n      echo \"Unrecognized argument $key\"\n      exit 1\n      ;;\n    esac\n  done\n}\n\nset_filename() {\n  local OS\n\n  OS=$(uname -s)\n\n  if [ \"$OS\" == \"Linux\" ]; then\n    FILENAME=\"{{ project_slug }}-linux-x64\"\n  elif [ \"$OS\" == \"Darwin\" ]; then\n    FILENAME=\"{{ project_slug }}-darwin-x64\"\n  else\n    echo \"OS $OS is not supported.\"\n    echo \"If you think that's a bug - please file an issue to https://github.com/{{ github_username }}/{{ project_slug }}/issues\"\n    exit 1\n  fi\n}\n\ndownload() {\n  if [ \"$RELEASE\" == \"latest\" ]; then\n    URL=https://github.com/{{ github_username }}/{{ project_slug }}/releases/latest/download/$FILENAME.zip\n  else\n    URL=https://github.com/{{ github_username }}/{{ project_slug }}/releases/download/$RELEASE/$FILENAME.zip\n  fi\n\n  DOWNLOAD_DIR=$(mktemp -d)\n\n  echo \"Downloading $URL...\"\n\n  mkdir -p \"$INSTALL_DIR\" &>/dev/null\n  curl --progress-bar -L \"$URL\" -o \"$DOWNLOAD_DIR/$FILENAME.zip\"\n\n  if [ 0 -ne \"$?\" ]; then\n    echo \"Download failed. Check that the release/filename are correct.\"\n    exit 1\n  fi\n\n  unzip -q \"$DOWNLOAD_DIR/$FILENAME.zip\" -d \"$DOWNLOAD_DIR\"\n  mv \"$DOWNLOAD_DIR/{{ project_slug }}\" \"$INSTALL_DIR/{{ project_slug }}\"\n  chmod u+x \"$INSTALL_DIR/{{ project_slug }}\"\n}\n\ncheck_dependencies() {\n  echo \"Checking dependencies for the installation script...\"\n\n  echo -n \"Checking availability of curl... \"\n  if hash curl 2>/dev/null; then\n    echo \"OK!\"\n  else\n    echo \"Missing!\"\n    SHOULD_EXIT=\"true\"\n  fi\n\n  echo -n \"Checking availability of unzip... \"\n  if hash unzip 2>/dev/null; then\n    echo \"OK!\"\n  else\n    echo \"Missing!\"\n    SHOULD_EXIT=\"true\"\n  fi\n\n  if [ \"$SHOULD_EXIT\" = \"true\" ]; then\n    exit 1\n  fi\n}\n\nparse_args \"$@\"\nset_filename\ncheck_dependencies\ndownload\n"

  let d_919d9d57ed6c39175671362b1df74f54 = "open {{ project_snake | capitalize }}\n\nlet run ~name =\n  let greeting = Utils.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.Let_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_97c37315b8c9a0df52581237c69c80ad = "{\n  \"name\": \"{{ project_slug }}\",\n  \"esy\": {\n    \"build\": \"dune build -p #{self.name}\",\n    {%- if syntax == 'Reason' %}\n    \"buildDev\": \"refmterr dune build --root . --only-package #{self.name}\",\n    {% else %}\n    \"buildDev\": \"dune build --root . --only-package #{self.name}\",\n    {% endif -%}\n    \"buildEnv\": {\n      \"ODOC_SYNTAX\": \"{% if syntax == 'Reason' %}re{% else %}ml{% endif %}\"\n    }\n  },\n  \"dependencies\": {\n    \"@opam/cmdliner\": \"*\",\n    \"@opam/logs\": \"*\",\n    \"@opam/fmt\": \"*\",\n    \"@opam/dune\": \">= 2.0\",\n    {%- if syntax == 'Reason' %}\n    \"@opam/reason\": \"*\",\n    {%- endif %}\n    \"ocaml\": \">= 4.8.1000\"\n  },\n  \"devDependencies\": {\n    {% if test_framework == 'Alcotest' -%}\n    \"@opam/alcotest\": \"*\",\n    {% endif -%}\n    \"@opam/dune-release\": \"*\",\n    \"@opam/merlin\": \"*\",\n    {% if syntax == 'OCaml' -%}\n    \"@opam/ocamlformat\": \"*\",\n    {% endif -%}\n    \"@opam/odoc\": \"*\",\n    \"@opam/utop\": \"*\",\n    {% if test_framework == 'Rely' -%}\n    \"@reason-native/rely\": \"*\",\n    {%- endif -%}\n    {%- if syntax == 'Reason' %}\n    \"refmterr\": \">= 3.3.0\",\n    {%- endif %}\n    \"ocaml\": \"~4.09.0\"\n  },\n  \"scripts\": {\n    \"start\": \"esy x {{ project_slug }}\",\n    \"test\": \"esy {% if test_framework == 'Rely' %}dune exec test/test_runner.exe{% else %}dune build @test/runtest -f{% endif %}\",\n    \"doc\": \"esy dune build @doc\",\n    \"doc-path\": \"esy echo #{self.target_dir}/default/_doc/_html/index.html\",\n    \"format\": \"esy dune build @fmt --auto-promote\",\n    \"watch\": \"esy dune build -p #{self.name} --watch\",\n    \"utop\": \"esy dune utop lib -- -implicit-bindings\",\n    \"release\": \"./script/release.sh\"\n  }\n}"

  let d_c039398731800b8de00d48f8772d21a8 = "open Cmdliner\n\nlet cmds = [ Cmd_hello.cmd ]\n\n(* Command line interface *)\n\nlet doc = \"Generate Reason and OCaml projects\"\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 \"{{ description }}\"\n  ; `S Manpage.s_commands\n  ; `S Manpage.s_common_options\n  ; `S Manpage.s_exit_status\n  ; `S Manpage.s_environment\n  ; `P \"These environment variables affect the execution of $(mname):\"\n  ; `S Manpage.s_bugs\n  ; `P \"File bug reports at $(i,https://github.com/tmattio/spin/issues)\"\n  ; `S Manpage.s_authors\n  ; `P \"{{ username }}, $(i,https://github.com/{{ github_username }})\"\n  ]\n\nlet default_cmd =\n  let term =\n    let open Common.Let_syntax in\n    Term.ret\n    @@ let+ _ = Common.term in\n       `Help (`Pager, None)\n  in\n  let info = Term.info \"spin\" ~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_c49a62e63737056b85280b4f492c7b80 = "open Cmdliner\n\nmodule Let_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 Let_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_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_cf7e936cd5428be266c8bd46ddd1cf81 = "# {{ project_name }}\n\n{% if ci_cd == 'Github' -%}\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[![NPM Version](https://badge.fury.io/js/%40{{ npm_username }}%2F{{ project_slug }}.svg)](https://badge.fury.io/js/%40{{ npm_username }}%2F{{ project_slug }})\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 npm\n\n```bash\nyarn global add @{{ npm_username }}/{{ project_slug }}\n# Or\nnpm -g install @{{ npm_username }}/{{ project_slug }}\n```\n\n### Using a script\n\n```bash\ncurl -fsSL https://github.com/{{ github_username }}/{{ project_slug }}/raw/master/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_f8cb2d56e2a63ac1354e4ce1aeabaf7e = "(lang dune 2.0)\n(name {{ project_slug }})\n(source (github {{ github_username }}/{{ project_slug }}))\n(license MIT)\n(authors \"{{ username }}{% if author_email %} <{{ author_email }}>{% endif %}\")\n(maintainers \"{{ username }}{% 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 \"\\\n{{ project_description }}\n\")\n (depends\n  (ocaml (>= 4.08.0))\n  (dune (>= 2.0))\n  {%- if test_framework == 'Rely' %}\n  ; Add Rely when released on Opam\n  ; (rely :with-test)\n  {%- else %}\n  (alcotest :with-test)\n  {%- endif %}\n  (odoc :with-doc)\n  {%- if syntax == 'Reason' %}\n  (reason :build)\n  {%- endif %}\n  cmdliner\n  logs\n  fmt))\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; ]
    | "generators/cmd/main.ml" | "/generators/cmd/main.ml" -> Some [ d_7148e0f2df2646dae0de7bd72102d52e; ]
    | "spin" | "/spin" -> Some [ d_7a530d2f879dd61a8fda0bb8d56eca1f; ]
    | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some [ d_811df803e12e793e593e57a7f773c38f; ]
    | "template/Makefile" | "/template/Makefile" -> Some [ d_28b54795ed6a2a415823691a9f91f984; ]
    | "template/README.md" | "/template/README.md" -> Some [ d_cf7e936cd5428be266c8bd46ddd1cf81; ]
    | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some [ d_919d9d57ed6c39175671362b1df74f54; ]
    | "template/bin/common.ml" | "/template/bin/common.ml" -> Some [ d_c49a62e63737056b85280b4f492c7b80; ]
    | "template/bin/common.mli" | "/template/bin/common.mli" -> Some [ d_7432831788782a1313cef2c92302d90e; ]
    | "template/bin/dune" | "/template/bin/dune" -> Some [ d_22a4a727f14480a70c5b0ab38d5c0d99; ]
    | "template/bin/main.ml" | "/template/bin/main.ml" -> Some [ d_c039398731800b8de00d48f8772d21a8; ]
    | "template/dune-project" | "/template/dune-project" -> Some [ d_f8cb2d56e2a63ac1354e4ce1aeabaf7e; ]
    | "template/esy.json" | "/template/esy.json" -> Some [ d_97c37315b8c9a0df52581237c69c80ad; ]
    | "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/script/install.sh" | "/template/script/install.sh" -> Some [ d_82e14a8eb47f5c536aa98f7afd40af64; ]
    | "template/script/release-make-skeleton.js" | "/template/script/release-make-skeleton.js" -> Some [ d_4025396dfb5871ced6b8051264e10553; ]
    | "template/script/release-postinstall.js" | "/template/script/release-postinstall.js" -> Some [ d_02ef1536addcb2e5f1f36b2fcd537fb1; ]
    | "template/script/release.sh" | "/template/script/release.sh" -> Some [ d_71da466b0ad1679de495d5ccc69f3fc0; ]
    | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some [ d_59c6dd264f3f1cedbd780cfae987de91; ]
    | _ -> None

  let file_list = [ "README.md"; "generators/cmd/main.ml"; "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/esy.json"; "template/lib/config.ml"; "template/lib/config.mli"; "template/lib/error.ml"; "template/lib/error.mli"; "template/script/install.sh"; "template/script/release-make-skeleton.js"; "template/script/release-postinstall.js"; "template/script/release.sh"; "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"
  | "generators/cmd/main.ml" | "/generators/cmd/main.ml" -> Some "7148e0f2df2646dae0de7bd72102d52e"
  | "spin" | "/spin" -> Some "7a530d2f879dd61a8fda0bb8d56eca1f"
  | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some "811df803e12e793e593e57a7f773c38f"
  | "template/Makefile" | "/template/Makefile" -> Some "28b54795ed6a2a415823691a9f91f984"
  | "template/README.md" | "/template/README.md" -> Some "cf7e936cd5428be266c8bd46ddd1cf81"
  | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some "919d9d57ed6c39175671362b1df74f54"
  | "template/bin/common.ml" | "/template/bin/common.ml" -> Some "c49a62e63737056b85280b4f492c7b80"
  | "template/bin/common.mli" | "/template/bin/common.mli" -> Some "7432831788782a1313cef2c92302d90e"
  | "template/bin/dune" | "/template/bin/dune" -> Some "22a4a727f14480a70c5b0ab38d5c0d99"
  | "template/bin/main.ml" | "/template/bin/main.ml" -> Some "c039398731800b8de00d48f8772d21a8"
  | "template/dune-project" | "/template/dune-project" -> Some "f8cb2d56e2a63ac1354e4ce1aeabaf7e"
  | "template/esy.json" | "/template/esy.json" -> Some "97c37315b8c9a0df52581237c69c80ad"
  | "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/script/install.sh" | "/template/script/install.sh" -> Some "82e14a8eb47f5c536aa98f7afd40af64"
  | "template/script/release-make-skeleton.js" | "/template/script/release-make-skeleton.js" -> Some "4025396dfb5871ced6b8051264e10553"
  | "template/script/release-postinstall.js" | "/template/script/release-postinstall.js" -> Some "02ef1536addcb2e5f1f36b2fcd537fb1"
  | "template/script/release.sh" | "/template/script/release.sh" -> Some "71da466b0ad1679de495d5ccc69f3fc0"
  | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some "59c6dd264f3f1cedbd780cfae987de91"
  | _ -> None

let size = function
  | "README.md" | "/README.md" -> Some 258
  | "generators/cmd/main.ml" | "/generators/cmd/main.ml" -> Some 735
  | "spin" | "/spin" -> Some 714
  | "template/CONTRIBUTING.md" | "/template/CONTRIBUTING.md" -> Some 3866
  | "template/Makefile" | "/template/Makefile" -> Some 1459
  | "template/README.md" | "/template/README.md" -> Some 1062
  | "template/bin/commands/cmd_hello.ml" | "/template/bin/commands/cmd_hello.ml" -> Some 761
  | "template/bin/common.ml" | "/template/bin/common.ml" -> Some 1184
  | "template/bin/common.mli" | "/template/bin/common.mli" -> Some 401
  | "template/bin/dune" | "/template/bin/dune" -> Some 200
  | "template/bin/main.ml" | "/template/bin/main.ml" -> Some 983
  | "template/dune-project" | "/template/dune-project" -> Some 736
  | "template/esy.json" | "/template/esy.json" -> Some 1616
  | "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/script/install.sh" | "/template/script/install.sh" -> Some 2000
  | "template/script/release-make-skeleton.js" | "/template/script/release-make-skeleton.js" -> Some 1964
  | "template/script/release-postinstall.js" | "/template/script/release-postinstall.js" -> Some 2683
  | "template/script/release.sh" | "/template/script/release.sh" -> Some 850
  | "template/{{ project_slug }}.opam" | "/template/{{ project_slug }}.opam" -> Some 1068
  | _ -> None
OCaml

Innovation. Community. Security.