diff options
| author | DJ O'Leary <dijitol@proton.me> | 2025-11-29 20:08:11 +0100 |
|---|---|---|
| committer | DJ O'Leary <dijitol@proton.me> | 2025-11-29 20:09:11 +0100 |
| commit | 87277098e997661f432be56c27f4b54d51aa9306 (patch) | |
| tree | 83846830e5102120ef298e8ad9a552b30203fdc6 /2025/ocaml | |
| parent | 0bf49c4ec799445350c60a96a754e44ac15a2268 (diff) | |
chore: use updated template
Diffstat (limited to '2025/ocaml')
30 files changed, 282 insertions, 37 deletions
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.yml b/2025/ocaml/Taskfile.yaml index b562b3a..7496067 100644 --- a/2025/ocaml/Taskfile.yml +++ b/2025/ocaml/Taskfile.yaml @@ -9,7 +9,7 @@ tasks: - cmd: task --list-all docs: - desc: Builds documentation using ocamldoc + desc: Builds documentation preconditions: - command -v ocamldoc cmds: @@ -17,10 +17,7 @@ tasks: silent: true test: - desc: Runs the tests in the 'tests' directory - ignore_error: true - env: - OUNIT_CI: true + desc: Runs the tests preconditions: - command -v dune deps: @@ -29,13 +26,11 @@ tasks: - cmd: dune runtest {{.CLI_ARGS}} test:watch: - desc: Continuously runs the tests in the 'tests' directory + desc: Continuously runs the tests ignore_error: true sources: - lib/**/*.ml - test/**/*.ml - env: - OUNIT_CI: true preconditions: - command -v dune deps: @@ -43,6 +38,19 @@ tasks: 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: @@ -50,6 +58,13 @@ tasks: 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: @@ -65,3 +80,16 @@ tasks: - 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/advent_of_code_2025.opam b/2025/ocaml/advent_of_code.opam index 3a50035..a6395c9 100644 --- a/2025/ocaml/advent_of_code_2025.opam +++ b/2025/ocaml/advent_of_code.opam @@ -1,20 +1,28 @@ # 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" +synopsis: "advent of code solutions for 2025" +description: + "project aiming to solve the advent of code puzzles released for 2025" maintainer: ["DJ O'Leary <dijitol@proton.me>"] authors: ["DJ O'Leary <dijitol@proton.me>"] license: "Unlicense" -tags: ["Advent of Code 2025"] +tags: ["project template"] homepage: "https://github.com/djoleary/advent_of_code" -doc: - "https://github.com/djoleary/advent_of_code/blob/main/2025/ocaml/docs/index.html" +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" + "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} 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/test_advent_of_code_2025.ml b/2025/ocaml/test/application/test_example.ml index e69de29..e69de29 100644 --- a/2025/ocaml/test/test_advent_of_code_2025.ml +++ b/2025/ocaml/test/application/test_example.ml 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 --- /dev/null +++ b/2025/ocaml/test/domain/test_example.ml 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 --- /dev/null +++ b/2025/ocaml/test/infrastructure/test_example.ml 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 --- /dev/null +++ b/2025/ocaml/test/presentation/test_example.ml |
