diff --git a/.gitignore b/.gitignore index a5cc7d6..2fb26d2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ input.txt greek.csv node_modules target +_build diff --git a/ocaml/README.md b/ocaml/README.md new file mode 100644 index 0000000..db6493e --- /dev/null +++ b/ocaml/README.md @@ -0,0 +1,3 @@ +_Climbing on the camel's back._ 🐫 + +Experiments with OCaml, inspired by [Bobkonf](https://bobkonf.de) 2026. diff --git a/ocaml/dune b/ocaml/dune new file mode 100644 index 0000000..09870ad --- /dev/null +++ b/ocaml/dune @@ -0,0 +1,5 @@ +(executable + (name main) + (modes js) + (libraries js_of_ocaml) + (preprocess (pps js_of_ocaml-ppx))) diff --git a/ocaml/dune-project b/ocaml/dune-project new file mode 100644 index 0000000..0f0bb91 --- /dev/null +++ b/ocaml/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.10) +(name ocaml_js_demo) diff --git a/ocaml/flake.lock b/ocaml/flake.lock new file mode 100644 index 0000000..88ab73f --- /dev/null +++ b/ocaml/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1773282481, + "narHash": "sha256-b/GV2ysM8mKHhinse2wz+uP37epUrSE+sAKXy/xvBY4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fe416aaedd397cacb33a610b33d60ff2b431b127", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/ocaml/flake.nix b/ocaml/flake.nix new file mode 100644 index 0000000..cbae36a --- /dev/null +++ b/ocaml/flake.nix @@ -0,0 +1,73 @@ +{ + description = "OCaml -> JavaScript demo using js_of_ocaml"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { self, nixpkgs }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + in + { + devShells.${system}.default = pkgs.mkShell { + packages = with pkgs; [ + ocaml + dune_3 + ocamlPackages.js_of_ocaml + ocamlPackages.js_of_ocaml-compiler + nodejs + tmux + ocamlPackages.ocaml-lsp + ocamlPackages.ocamlformat + (pkgs.writeShellApplication { + name = "dev"; + runtimeInputs = [ dune nodejs tmux ]; + text = '' + SESSION=ocaml-js + + tmux new-session -d -s "$SESSION" + + tmux new-window -t "$SESSION" -n build + tmux send-keys -t "$SESSION:0" "dune build main.bc.js --watch" C-m + + tmux new-window -t "$SESSION" -n server + tmux send-keys -t "$SESSION:1" "npx live-server result" C-m + + tmux attach -t "$SESSION" + ''; + }) + ]; + shellHook = '' + echo "Run 'dev' to start tmux dev environment." + ''; + }; + + packages.${system}.default = pkgs.stdenv.mkDerivation { + pname = "ocaml-js-demo"; + version = "0.1"; + + src = ./.; + + nativeBuildInputs = with pkgs; [ + ocaml + dune_3 + ocamlPackages.js_of_ocaml + ocamlPackages.js_of_ocaml-compiler + ocamlPackages.js_of_ocaml-ppx + ]; + + buildPhase = '' + dune build main.bc.js + ''; + + installPhase = '' + mkdir -p $out + cp _build/default/main.bc.js $out/ + cp index.html $out/ + ''; + }; + }; +} diff --git a/ocaml/index.html b/ocaml/index.html new file mode 100644 index 0000000..aa90baa --- /dev/null +++ b/ocaml/index.html @@ -0,0 +1,15 @@ + + + + + OCaml DOM demo + + + +

OCaml DOM Demo

+ +

+ + + + diff --git a/ocaml/main.ml b/ocaml/main.ml new file mode 100644 index 0000000..f739e7a --- /dev/null +++ b/ocaml/main.ml @@ -0,0 +1,23 @@ +open Js_of_ocaml +(* open Js_of_ocaml.Dom_html *) + +let document = Dom_html.document + +let by_id id = + Js.Opt.get + (document##getElementById (Js.string id)) + (fun () -> failwith ("Missing element: " ^ id)) + +let () = + let button = by_id "btn" in + let output = by_id "output" in + + let clicks = ref 0 in + + button##.onclick := + Dom_html.handler (fun _ -> + incr clicks; + output##.textContent := + Js.some (Js.string ("Clicked " ^ string_of_int !clicks ^ " times")); + Js._false + )