├── .gitignore ├── Procfile ├── assets ├── favicon.png ├── favicon.svg └── ruudvanasseldonk.asc ├── docindex ├── build.py ├── get_stars.py ├── index.html ├── readme.md ├── repos.toml └── stars.json ├── flake.lock ├── flake.nix ├── fonts ├── extra │ ├── math-italic.sfd │ └── math-upright.sfd ├── generate.py ├── readme.md └── subset.py ├── images ├── build.ninja ├── compress.sh ├── compressed │ ├── build.svg │ ├── geomancer-move-mage.jpg │ ├── geomancer-overview.jpg │ ├── geomancer-soldier-under-attack-by-mage.jpg │ ├── ill-build-my-own-configuration-language.png │ ├── lattice.svg │ ├── rectangles.svg │ ├── richys-groceries.jpg │ ├── robigo-luculenta.jpg │ ├── subtypes.svg │ ├── the-small-bang-theory.jpg │ └── tristar-cyan.png ├── crush.sh ├── original │ ├── build.svg │ ├── geomancer-move-mage.png │ ├── geomancer-overview.png │ ├── geomancer-soldier-under-attack-by-mage.png │ ├── ill-build-my-own-configuration-language.png │ ├── lattice.svg │ ├── rectangles.svg │ ├── richys-groceries.png │ ├── robigo-luculenta.png │ ├── subtypes.svg │ ├── the-small-bang-theory.png │ └── tristar-cyan.png ├── resize.sh └── resized │ ├── geomancer-move-mage.png │ ├── geomancer-overview.png │ ├── geomancer-soldier-under-attack-by-mage.png │ ├── richys-groceries.png │ ├── robigo-luculenta.png │ ├── the-small-bang-theory.png │ └── tristar-cyan.png ├── licence ├── posts ├── a-float-walks-into-a-gradual-type-system.md ├── a-language-for-designing-slides.md ├── a-perspective-shift-on-amms-through-mev.md ├── a-reasonable-configuration-language.md ├── a-type-system-for-rcl-part-1-introduction.md ├── a-type-system-for-rcl-part-2-the-type-system.md ├── a-type-system-for-rcl-part-3-related-work.md ├── ai-alignment-starter-pack.md ├── an-algorithm-for-shuffling-playlists.md.m4 ├── an-api-for-my-christmas-tree.md ├── build-system-insights.md ├── building-elm-with-stack.md ├── continuations-revisited.md ├── csharp-await-is-the-haskell-do-notation.md ├── encryption-by-default.md ├── exceptional-results-error-handling-in-csharp-and-rust.md ├── fibonacci-numbers-in-finite-fields.md ├── geomancer-at-indigo.md ├── git-music.md ├── gits-push-url.md ├── global-game-jam-2012.md ├── global-game-jam-2014.md ├── global-game-jam-2015.md ├── implementing-a-typechecker-for-rcl-in-rust.md ├── llm-interactions.md ├── model-facts-not-your-problem-domain.md ├── neither-necessary-nor-sufficient.md ├── on-benchmarking.md ├── one-year-with-colemak.md ├── passphrase-entropy.md ├── please-put-units-in-names.md ├── the-small-bang-theory-in-san-francisco.md ├── the-task-monad-in-csharp.md ├── the-yaml-document-from-hell.md ├── working-on-a-virtualenv-without-magic.md ├── writing-a-path-tracer-in-rust-part-1.md ├── writing-a-path-tracer-in-rust-part-2-first-impressions.md ├── writing-a-path-tracer-in-rust-part-3-operators.md ├── writing-a-path-tracer-in-rust-part-4-tracing-rays.md ├── writing-a-path-tracer-in-rust-part-5-tonemapping.md ├── writing-a-path-tracer-in-rust-part-6-multithreading.md ├── writing-a-path-tracer-in-rust-part-7-conclusion.md ├── yaose-is-now-free-software.md └── zero-cost-abstractions.md ├── readme.md ├── src ├── Html.hs ├── Image.hs ├── Main.hs ├── Minification.hs ├── Post.hs ├── Template.hs └── Type.hs ├── templates ├── archive.html ├── contact.html ├── feed.xml ├── fonts.css ├── footer.html ├── head.html ├── index.html ├── math.css ├── page.css └── post.html └── tools ├── bazelsvg.py ├── grid.js ├── scale.html ├── stats.awk └── stats.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Build output 2 | /.stack-work 3 | /dist 4 | /src/*.hi 5 | /src/*.o 6 | /blog 7 | 8 | # Cabal sandbox 9 | /.cabal-sandbox 10 | /cabal.sandbox.config 11 | 12 | # Editor files 13 | *.swp 14 | *.swo 15 | 16 | # Nix build result symlink 17 | /result 18 | 19 | # Image intermediate build products 20 | .ninja_log 21 | /images/compressed/*.br 22 | /images/compressed/*.gz 23 | 24 | # Fonts, original and processed 25 | /fonts/generated 26 | /fonts/original 27 | 28 | # Generated blog output 29 | /out 30 | /docindex/index.rendered.html 31 | 32 | # Python virtualenv 33 | /venv 34 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | blog: /usr/bin/fd . posts | entr blog 2 | http: python -m http.server 8888 --bind 0.0.0.0 --directory out 3 | -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruuda/blog/bab1f438a0057239b9e0ec41007a1ed8b8dbc4b6/assets/favicon.png -------------------------------------------------------------------------------- /assets/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docindex/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2023 Ruud van Asseldonk 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License version 3. See 7 | # the licence file in the root of the repository. 8 | 9 | from datetime import datetime 10 | from typing import Dict, Iterable, List, NamedTuple, Tuple 11 | 12 | import json 13 | import toml 14 | 15 | 16 | class Repo(NamedTuple): 17 | title: str 18 | slug: str 19 | description: str 20 | stars: int 21 | 22 | 23 | def load_repos() -> Iterable[Repo]: 24 | with open("repos.toml", "r", encoding="utf-8") as f: 25 | for title, properties in toml.load(f).items(): 26 | yield Repo(title, **properties, stars=0) 27 | 28 | 29 | def load_stars() -> Tuple[datetime, Dict[str, int]]: 30 | with open("stars.json", "r", encoding="utf-8") as f: 31 | data = json.load(f) 32 | generated_at = datetime.fromisoformat(data["generated_at"]) 33 | assert generated_at.tzinfo is not None 34 | stars: Dict[str, int] = data["stars"] 35 | return generated_at, stars 36 | 37 | 38 | def render_project_card(repo: Repo) -> str: 39 | return f""" 40 |
{repo.description}
43 | 47 |