From 87277098e997661f432be56c27f4b54d51aa9306 Mon Sep 17 00:00:00 2001 From: DJ O'Leary Date: Sat, 29 Nov 2025 20:08:11 +0100 Subject: chore: use updated template --- 2025/ocaml/.env.template | 1 + 2025/ocaml/.envrc | 2 + 2025/ocaml/.githooks/commit-msg | 15 ++++ 2025/ocaml/.githooks/pre-push | 18 +++++ 2025/ocaml/.gitignore | 3 + 2025/ocaml/.ocamlformat | 2 +- 2025/ocaml/README.md | 15 ++-- 2025/ocaml/Taskfile.yaml | 95 ++++++++++++++++++++++++++ 2025/ocaml/Taskfile.yml | 67 ------------------ 2025/ocaml/advent_of_code.opam | 42 ++++++++++++ 2025/ocaml/advent_of_code_2025.opam | 34 --------- 2025/ocaml/bin/dune | 8 ++- 2025/ocaml/bin/main.ml | 4 +- 2025/ocaml/dune-project | 26 +++++-- 2025/ocaml/flake.nix | 10 ++- 2025/ocaml/lib/application/dune | 14 ++++ 2025/ocaml/lib/application/logger_sig.mli | 11 +++ 2025/ocaml/lib/domain/dune | 9 +++ 2025/ocaml/lib/dune | 3 - 2025/ocaml/lib/infrastructure/dune | 18 +++++ 2025/ocaml/lib/infrastructure/logger.ml | 31 +++++++++ 2025/ocaml/lib/presentation/cli.ml | 15 ++++ 2025/ocaml/lib/presentation/dune | 15 ++++ 2025/ocaml/test/application/dune | 7 ++ 2025/ocaml/test/application/test_example.ml | 0 2025/ocaml/test/domain/dune | 6 ++ 2025/ocaml/test/domain/test_example.ml | 0 2025/ocaml/test/dune | 3 - 2025/ocaml/test/infrastructure/dune | 8 +++ 2025/ocaml/test/infrastructure/test_example.ml | 0 2025/ocaml/test/presentation/dune | 11 +++ 2025/ocaml/test/presentation/test_example.ml | 0 2025/ocaml/test/test_advent_of_code_2025.ml | 0 33 files changed, 369 insertions(+), 124 deletions(-) create mode 100644 2025/ocaml/.env.template create mode 100755 2025/ocaml/.githooks/commit-msg create mode 100755 2025/ocaml/.githooks/pre-push create mode 100644 2025/ocaml/Taskfile.yaml delete mode 100644 2025/ocaml/Taskfile.yml create mode 100644 2025/ocaml/advent_of_code.opam delete mode 100644 2025/ocaml/advent_of_code_2025.opam create mode 100644 2025/ocaml/lib/application/dune create mode 100644 2025/ocaml/lib/application/logger_sig.mli create mode 100644 2025/ocaml/lib/domain/dune delete mode 100644 2025/ocaml/lib/dune create mode 100644 2025/ocaml/lib/infrastructure/dune create mode 100644 2025/ocaml/lib/infrastructure/logger.ml create mode 100644 2025/ocaml/lib/presentation/cli.ml create mode 100644 2025/ocaml/lib/presentation/dune create mode 100644 2025/ocaml/test/application/dune create mode 100644 2025/ocaml/test/application/test_example.ml create mode 100644 2025/ocaml/test/domain/dune create mode 100644 2025/ocaml/test/domain/test_example.ml delete mode 100644 2025/ocaml/test/dune create mode 100644 2025/ocaml/test/infrastructure/dune create mode 100644 2025/ocaml/test/infrastructure/test_example.ml create mode 100644 2025/ocaml/test/presentation/dune create mode 100644 2025/ocaml/test/presentation/test_example.ml delete mode 100644 2025/ocaml/test/test_advent_of_code_2025.ml (limited to '2025') diff --git a/2025/ocaml/.env.template b/2025/ocaml/.env.template new file mode 100644 index 0000000..3adee3e --- /dev/null +++ b/2025/ocaml/.env.template @@ -0,0 +1 @@ +LOG_LEVEL=debug diff --git a/2025/ocaml/.envrc b/2025/ocaml/.envrc index 3550a30..cf8df4b 100644 --- a/2025/ocaml/.envrc +++ b/2025/ocaml/.envrc @@ -1 +1,3 @@ +dotenv + use flake diff --git a/2025/ocaml/.githooks/commit-msg b/2025/ocaml/.githooks/commit-msg new file mode 100755 index 0000000..1c1c287 --- /dev/null +++ b/2025/ocaml/.githooks/commit-msg @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Commit message hook - enforce conventional commit format + +commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}|^fixup!' + +if ! grep -qE "$commit_regex" "$1"; then + echo "โŒ Invalid commit message format!" + echo "" + echo "Format: type(scope): description" + echo "Types: feat, fix, docs, style, refactor, test, chore" + echo "Example: feat(auth): add user login functionality" + echo "" + echo "Your message: $(cat $1)" + exit 1 +fi diff --git a/2025/ocaml/.githooks/pre-push b/2025/ocaml/.githooks/pre-push new file mode 100755 index 0000000..51a8761 --- /dev/null +++ b/2025/ocaml/.githooks/pre-push @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Pre-push hook - run tests before pushing + +set -e + +echo "๐Ÿงช Running tests before push..." + +# Run the full test suite +task test + +if [ $? -eq 0 ]; then + echo "โœ… All tests passed! Push allowed." + exit 0 +else + echo "โŒ Tests failed! Push blocked." + echo "Fix the failing tests before pushing." + exit 1 +fi diff --git a/2025/ocaml/.gitignore b/2025/ocaml/.gitignore index cb02e52..5456007 100644 --- a/2025/ocaml/.gitignore +++ b/2025/ocaml/.gitignore @@ -38,5 +38,8 @@ _opam/ # DirEnv cache .direnv/ +# Environment variables +*.env + # Taskfile cache .task/ diff --git a/2025/ocaml/.ocamlformat b/2025/ocaml/.ocamlformat index d22b51c..6fdcd22 100644 --- a/2025/ocaml/.ocamlformat +++ b/2025/ocaml/.ocamlformat @@ -1,3 +1,3 @@ -profile = default +profile = ocamlformat version = 0.28.1 diff --git a/2025/ocaml/README.md b/2025/ocaml/README.md index ef9bc42..772c76b 100644 --- a/2025/ocaml/README.md +++ b/2025/ocaml/README.md @@ -1,4 +1,12 @@ -# Advent of Code 2025 +# OCaml Template + +This is a template for OCaml projects. + +## Quick Start + +1. Fork this repository +2. Rename the repository to your project name +3. Replace all instances of `advent_of_code` with your project name, both in files and filenames themselves. ## Project Structure @@ -21,8 +29,8 @@ โ”œโ”€โ”€ dune-project # dune project configuration โ”œโ”€โ”€ flake.lock โ”œโ”€โ”€ flake.nix # nix flake configuration -โ”œโ”€โ”€ advent_of_code_2025.install # autogenerated install script -โ””โ”€โ”€ advent_of_code_2025.opam # autogenerated project description +โ”œโ”€โ”€ advent_of_code.install # autogenerated install script +โ””โ”€โ”€ advent_of_code.opam # autogenerated project description ``` ## Tools @@ -37,7 +45,6 @@ - [ocaml-lsp](https://github.com/ocaml/ocaml-lsp) - [earlybird](https://github.com/ocaml-lsp/earlybird) - [findlib](https://github.com/ocaml/ocamlfind) -- [menhir](https://github.com/ocaml-menhir/menhir) - [re2](https://github.com/janestreet/re2) - [fmt](https://erratique.ch/software/fmt) - [cmdliner](https://erratique.ch/software/cmdliner) diff --git a/2025/ocaml/Taskfile.yaml b/2025/ocaml/Taskfile.yaml new file mode 100644 index 0000000..7496067 --- /dev/null +++ b/2025/ocaml/Taskfile.yaml @@ -0,0 +1,95 @@ +# https://taskfile.dev +version: "3" + +tasks: + + default: + desc: Prints this message + cmds: + - cmd: task --list-all + + docs: + desc: Builds documentation + preconditions: + - command -v ocamldoc + cmds: + - cmd: ocamldoc -html -d docs bin/main.ml + silent: true + + test: + desc: Runs the tests + preconditions: + - command -v dune + deps: + - task: build + cmds: + - cmd: dune runtest {{.CLI_ARGS}} + + test:watch: + desc: Continuously runs the tests + ignore_error: true + sources: + - lib/**/*.ml + - test/**/*.ml + preconditions: + - command -v dune + deps: + - task: build + cmds: + - cmd: dune runtest --watch {{.CLI_ARGS}} + + test:coverage: + desc: Runs the tests and reports coverage + preconditions: + - command -v dune + - command -v bisect-ppx-report + deps: + - task: build + cmds: + - cmd: rm --recursive --force _coverage + - cmd: rm --force _build/default/test/bisect*.coverage + - cmd: dune runtest --instrument-with bisect_ppx --force {{.CLI_ARGS}} + - cmd: bisect-ppx-report html + + build: + desc: Builds the project + preconditions: + - command -v dune + cmds: + - cmd: dune build + + build:watch: + desc: Builds the project when files change + preconditions: + - command -v dune + cmds: + - cmd: dune build --watch {{.CLI_ARGS}} + + build:release: + desc: Builds a release version the project + preconditions: + - command -v dune + cmds: + - cmd: dune build --release + + run: + desc: Runs the project + preconditions: + - command -v dune + deps: + - task: build + cmds: + - cmd: dune exec -- ./bin/main.exe {{.CLI_ARGS}} + + repl: + desc: Opens a REPL for the project + interactive: true + preconditions: + - command -v dune + - command -v utop + cmds: + - cmd: dune utop + + git:hooks: + desc: sets up the githooks for the project + cmd: git config core.hooksPath .githooks diff --git a/2025/ocaml/Taskfile.yml b/2025/ocaml/Taskfile.yml deleted file mode 100644 index b562b3a..0000000 --- a/2025/ocaml/Taskfile.yml +++ /dev/null @@ -1,67 +0,0 @@ -# https://taskfile.dev -version: "3" - -tasks: - - default: - desc: Prints this message - cmds: - - cmd: task --list-all - - docs: - desc: Builds documentation using ocamldoc - preconditions: - - command -v ocamldoc - cmds: - - cmd: ocamldoc -html -d docs bin/main.ml - silent: true - - test: - desc: Runs the tests in the 'tests' directory - ignore_error: true - env: - OUNIT_CI: true - preconditions: - - command -v dune - deps: - - task: build - cmds: - - cmd: dune runtest {{.CLI_ARGS}} - - test:watch: - desc: Continuously runs the tests in the 'tests' directory - ignore_error: true - sources: - - lib/**/*.ml - - test/**/*.ml - env: - OUNIT_CI: true - preconditions: - - command -v dune - deps: - - task: build - cmds: - - cmd: dune runtest --watch {{.CLI_ARGS}} - - build: - desc: Builds the project - preconditions: - - command -v dune - cmds: - - cmd: dune build - - build:release: - desc: Builds a release version the project - preconditions: - - command -v dune - cmds: - - cmd: dune build --release - - run: - desc: Runs the project - preconditions: - - command -v dune - deps: - - task: build - cmds: - - cmd: dune exec -- ./bin/main.exe {{.CLI_ARGS}} diff --git a/2025/ocaml/advent_of_code.opam b/2025/ocaml/advent_of_code.opam new file mode 100644 index 0000000..a6395c9 --- /dev/null +++ b/2025/ocaml/advent_of_code.opam @@ -0,0 +1,42 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "advent of code solutions for 2025" +description: + "project aiming to solve the advent of code puzzles released for 2025" +maintainer: ["DJ O'Leary "] +authors: ["DJ O'Leary "] +license: "Unlicense" +tags: ["project template"] +homepage: "https://github.com/djoleary/advent_of_code" +doc: "https://github.com/djoleary/advent_of_code/2025/ocaml/docs/index.html" +bug-reports: "https://github.com/djoleary/advent_of_code/issues" +depends: [ + "dune" {>= "3.20"} + "ocaml" {>= "5.2"} + "ppx_deriving" {build} + "alcotest" {with-test} + "qcheck" {with-test} + "bisect_ppx" {with-test} + "ppx_inline_test" {with-test} + "ppx_expect" {with-test} + "odoc" {with-doc} + "cmdliner" + "fmt" + "re2" +] +build: [ + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] +dev-repo: "git+https://github.com/djoleary/advent_of_code.git" +x-maintenance-intent: ["(latest)"] diff --git a/2025/ocaml/advent_of_code_2025.opam b/2025/ocaml/advent_of_code_2025.opam deleted file mode 100644 index 3a50035..0000000 --- a/2025/ocaml/advent_of_code_2025.opam +++ /dev/null @@ -1,34 +0,0 @@ -# This file is generated by dune, edit dune-project instead -opam-version: "2.0" -synopsis: "Advent of Code 2025" -description: "Solutions to the puzzles from Advent of Code 2025" -maintainer: ["DJ O'Leary "] -authors: ["DJ O'Leary "] -license: "Unlicense" -tags: ["Advent of Code 2025"] -homepage: "https://github.com/djoleary/advent_of_code" -doc: - "https://github.com/djoleary/advent_of_code/blob/main/2025/ocaml/docs/index.html" -bug-reports: "https://github.com/djoleary/advent_of_code/issues" -depends: [ - "dune" {>= "3.20"} - "ocaml" - "alcotest" {with-test} - "odoc" {with-doc} -] -build: [ - ["dune" "subst"] {dev} - [ - "dune" - "build" - "-p" - name - "-j" - jobs - "@install" - "@runtest" {with-test} - "@doc" {with-doc} - ] -] -dev-repo: "git+https://github.com/djoleary/advent_of_code.git" -x-maintenance-intent: ["(latest)"] diff --git a/2025/ocaml/bin/dune b/2025/ocaml/bin/dune index a912fd0..49a288c 100644 --- a/2025/ocaml/bin/dune +++ b/2025/ocaml/bin/dune @@ -1,4 +1,8 @@ (executable - (public_name advent_of_code_2025) + (public_name advent_of_code) (name main) - (libraries advent_of_code_2025)) + (libraries + domain + application + infrastructure + presentation)) diff --git a/2025/ocaml/bin/main.ml b/2025/ocaml/bin/main.ml index 7bf6048..f34d5ef 100644 --- a/2025/ocaml/bin/main.ml +++ b/2025/ocaml/bin/main.ml @@ -1 +1,3 @@ -let () = print_endline "Hello, World!" +let main () = Presentation.Cli.run () + +let () = if !Sys.interactive then () else exit (main ()) diff --git a/2025/ocaml/dune-project b/2025/ocaml/dune-project index 649d68f..a46e495 100644 --- a/2025/ocaml/dune-project +++ b/2025/ocaml/dune-project @@ -1,6 +1,6 @@ (lang dune 3.20) -(name advent_of_code_2025) +(name advent_of_code) (generate_opam_files true) @@ -13,14 +13,26 @@ (license Unlicense) -(documentation https://github.com/djoleary/advent_of_code/blob/main/2025/ocaml/docs/index.html) +(documentation https://github.com/djoleary/advent_of_code/2025/ocaml/docs/index.html) (package - (name advent_of_code_2025) - (synopsis "Advent of Code 2025") - (description "Solutions to the puzzles from Advent of Code 2025") - (depends ocaml (alcotest :with-test)) + (name advent_of_code) + (synopsis "advent of code solutions for 2025") + (description "project aiming to solve the advent of code puzzles released for 2025") + (depends + (ocaml (>= 5.2)) + (ppx_deriving :build) + (alcotest :with-test) + (qcheck :with-test) + (bisect_ppx :with-test) + (ppx_inline_test :with-test) + (ppx_expect :with-test) + (odoc :with-doc) + cmdliner + fmt + re2 + ) (tags - ("Advent of Code 2025"))) + ("project template"))) ; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html diff --git a/2025/ocaml/flake.nix b/2025/ocaml/flake.nix index 163e41e..54d7b3f 100644 --- a/2025/ocaml/flake.nix +++ b/2025/ocaml/flake.nix @@ -25,14 +25,20 @@ utop # REPL + odoc # documentation generator + alcotest # unit test framework bisect_ppx # test coverage - - odoc # documentation generator + qcheck-core # property-based testing + qcheck-alcotest # property-based testing + janeStreet.ppx_inline_test # inline test library + janeStreet.ppx_expect # inline test library janeStreet.re2 # regular expression library fmt # pretty printing library cmdliner # command line library + ppx_deriving # derivers + logs # logging library ]; sysTools = with pkgs; [ go-task diff --git a/2025/ocaml/lib/application/dune b/2025/ocaml/lib/application/dune new file mode 100644 index 0000000..f73f950 --- /dev/null +++ b/2025/ocaml/lib/application/dune @@ -0,0 +1,14 @@ +(library + (name application) + (libraries + domain + fmt + logs) + (inline_tests) + (preprocess + (pps + ppx_deriving.show + ppx_deriving.eq + ppx_deriving.ord + ppx_expect)) + (modules_without_implementation logger_sig)) diff --git a/2025/ocaml/lib/application/logger_sig.mli b/2025/ocaml/lib/application/logger_sig.mli new file mode 100644 index 0000000..ac84747 --- /dev/null +++ b/2025/ocaml/lib/application/logger_sig.mli @@ -0,0 +1,11 @@ +module type Logger = sig + val app : string -> unit + + val err : string -> unit + + val warn : string -> unit + + val info : string -> unit + + val debug : string -> unit +end diff --git a/2025/ocaml/lib/domain/dune b/2025/ocaml/lib/domain/dune new file mode 100644 index 0000000..f23b247 --- /dev/null +++ b/2025/ocaml/lib/domain/dune @@ -0,0 +1,9 @@ +(library + (name domain) + (inline_tests) + (preprocess + (pps + ppx_deriving.show + ppx_deriving.eq + ppx_deriving.ord + ppx_expect))) diff --git a/2025/ocaml/lib/dune b/2025/ocaml/lib/dune deleted file mode 100644 index 215ce47..0000000 --- a/2025/ocaml/lib/dune +++ /dev/null @@ -1,3 +0,0 @@ -(library - (name advent_of_code_2025) - (libraries re2 fmt cmdliner)) diff --git a/2025/ocaml/lib/infrastructure/dune b/2025/ocaml/lib/infrastructure/dune new file mode 100644 index 0000000..9857fbb --- /dev/null +++ b/2025/ocaml/lib/infrastructure/dune @@ -0,0 +1,18 @@ +(library + (name infrastructure) + (libraries + application + domain + fmt + fmt.cli + fmt.tty + logs + logs.cli + logs.fmt) + (inline_tests) + (preprocess + (pps + ppx_deriving.show + ppx_deriving.eq + ppx_deriving.ord + ppx_expect))) diff --git a/2025/ocaml/lib/infrastructure/logger.ml b/2025/ocaml/lib/infrastructure/logger.ml new file mode 100644 index 0000000..d0d37a3 --- /dev/null +++ b/2025/ocaml/lib/infrastructure/logger.ml @@ -0,0 +1,31 @@ +module type Configurable_Logger = sig + include Application.Logger_sig.Logger + + val configure_logger : level:Logs.level option -> unit + + val parse_level : + env:Cmdliner.Cmd.Env.info -> Logs.level option Cmdliner.Term.t + + val configure_renderer : style_renderer:Fmt.style_renderer option -> unit +end + +module CLI_Logger : Configurable_Logger = struct + let configure_logger ~level = + Logs.set_level level ; + Logs.set_reporter (Logs_fmt.reporter ()) + + let parse_level ~env = Logs_cli.level ~env () + + let configure_renderer ~style_renderer = + Fmt_tty.setup_std_outputs ?style_renderer () + + let app msg = Logs.app (fun m -> m "%s" msg) + + let err msg = Logs.err (fun m -> m "%s" msg) + + let warn msg = Logs.warn (fun m -> m "%s" msg) + + let info msg = Logs.info (fun m -> m "%s" msg) + + let debug msg = Logs.debug (fun m -> m "%s" msg) +end diff --git a/2025/ocaml/lib/presentation/cli.ml b/2025/ocaml/lib/presentation/cli.ml new file mode 100644 index 0000000..c306ad2 --- /dev/null +++ b/2025/ocaml/lib/presentation/cli.ml @@ -0,0 +1,15 @@ +open Cmdliner +open Cmdliner.Term.Syntax + +let logger () = + let env = Cmd.Env.info "LOG_LEVEL" in + let+ level = Infrastructure.Logger.CLI_Logger.parse_level ~env + and+ style_renderer = Fmt_cli.style_renderer () in + Infrastructure.Logger.CLI_Logger.configure_logger ~level ; + Fmt_tty.setup_std_outputs ?style_renderer () ; + let result_code = 0 in + result_code + +let cmd = Cmd.v (Cmd.info "tool") @@ logger () + +let run () = Cmd.eval' cmd diff --git a/2025/ocaml/lib/presentation/dune b/2025/ocaml/lib/presentation/dune new file mode 100644 index 0000000..a37ca0c --- /dev/null +++ b/2025/ocaml/lib/presentation/dune @@ -0,0 +1,15 @@ +(library + (name presentation) + (libraries + application + domain + infrastructure + cmdliner + fmt.cli) + (inline_tests) + (preprocess + (pps + ppx_deriving.show + ppx_deriving.eq + ppx_deriving.ord + ppx_expect))) diff --git a/2025/ocaml/test/application/dune b/2025/ocaml/test/application/dune new file mode 100644 index 0000000..785d27e --- /dev/null +++ b/2025/ocaml/test/application/dune @@ -0,0 +1,7 @@ +(tests + (names + test_example) + (libraries + application + domain + alcotest)) diff --git a/2025/ocaml/test/application/test_example.ml b/2025/ocaml/test/application/test_example.ml new file mode 100644 index 0000000..e69de29 diff --git a/2025/ocaml/test/domain/dune b/2025/ocaml/test/domain/dune new file mode 100644 index 0000000..8bd0a52 --- /dev/null +++ b/2025/ocaml/test/domain/dune @@ -0,0 +1,6 @@ +(tests + (names + test_example) + (libraries + domain + alcotest)) diff --git a/2025/ocaml/test/domain/test_example.ml b/2025/ocaml/test/domain/test_example.ml new file mode 100644 index 0000000..e69de29 diff --git a/2025/ocaml/test/dune b/2025/ocaml/test/dune deleted file mode 100644 index c90f542..0000000 --- a/2025/ocaml/test/dune +++ /dev/null @@ -1,3 +0,0 @@ -(test - (libraries alcotest) - (name test_advent_of_code_2025)) diff --git a/2025/ocaml/test/infrastructure/dune b/2025/ocaml/test/infrastructure/dune new file mode 100644 index 0000000..5d493d9 --- /dev/null +++ b/2025/ocaml/test/infrastructure/dune @@ -0,0 +1,8 @@ +(tests + (names + test_example) + (libraries + application + domain + infrastructure + alcotest)) diff --git a/2025/ocaml/test/infrastructure/test_example.ml b/2025/ocaml/test/infrastructure/test_example.ml new file mode 100644 index 0000000..e69de29 diff --git a/2025/ocaml/test/presentation/dune b/2025/ocaml/test/presentation/dune new file mode 100644 index 0000000..e34e56f --- /dev/null +++ b/2025/ocaml/test/presentation/dune @@ -0,0 +1,11 @@ +(tests + (names + test_example) + (libraries + application + domain + infrastructure + presentation + alcotest + qcheck-core + qcheck-alcotest)) diff --git a/2025/ocaml/test/presentation/test_example.ml b/2025/ocaml/test/presentation/test_example.ml new file mode 100644 index 0000000..e69de29 diff --git a/2025/ocaml/test/test_advent_of_code_2025.ml b/2025/ocaml/test/test_advent_of_code_2025.ml deleted file mode 100644 index e69de29..0000000 -- cgit v1.2.3