
技術書典 20 限定で H 言語くんフィギュアを発売します!
kakkun61 が初めて Blender のスカルプトをさわったら偶然できた気持ち悪い異形の立体化!

サポート材未取り外し、未塗装での販売です

技術書典 20 限定で H 言語くんフィギュアを発売します!
kakkun61 が初めて Blender のスカルプトをさわったら偶然できた気持ち悪い異形の立体化!

サポート材未取り外し、未塗装での販売です
買ったときはめちゃくちゃメッキ調になってすごいと思った「ガンダムマーカー EX ガンダムメッキシルバー」ですが、4 年ぐらい経って使おうとしたら全くメッキ調にならなくなりました。
新品を買ってきたので新旧比較、全然違う。

かなり使用期限の短い商品なのかも……
悲しい
技術書典 20 にオンライン&オンサイトでサークル参加します。
日時と場所は
下記の書物を持っていく予定です。
よろしくね!
Cspell というものがあります。ソースコード中の単語のスペルをチェックしてくれるツールです。うっかりタイポして面倒なエラーになるのは嫌なので自分がソースコードを書くときはチェックをしています。
それを nix flake check コマンドの中でやってしまおうというのが cspell-nix です。11 月ごろに作りました。
cspell-nix は Flake Parts のモジュールとして提供しています。
引数などはモジュール定義を見れば書いてあるのですが、わざわざそのためにソースコードを見るのは不要な部分も多いですし Commonmark などで書いてレンダーされた結果を見れるようにしたいです。しかし手でドキュメントを書いていくのはソースコードとの乖離などに注意する必要があります。そこでドキュメントを自動生成できるようにしました。
pkgs から nixosOptionsDoc という関数が定義されていて、これでドキュメントの生成ができます。できるのですが、なかなかつまづきました。
まず、nixosOptionsDoc にコメントが書かれていないためソースコードを見て使い方を推定する必要があります。ソースコードを辿ると nixpkgs/nixos/lib/make-options-doc/default.nix にコメントが書かれていてこれがヒントになります。
Generates documentation for [nix modules](https://nix.dev/tutorials/module-system/index.html). It uses the declared `options` to generate documentation in various formats. # Outputs This function returns an attribute set with the following entries. ## optionsCommonMark Documentation in CommonMark text format. ## optionsJSON All options in a JSON format suitable for further automated processing. `example.json` ```json { ... "fileSystems.<name>.options": { "declarations": ["nixos/modules/tasks/filesystems.nix"], "default": { "_type": "literalExpression", "text": "[\n \"defaults\"\n]" }, "description": "Options used to mount the file system.", "example": { "_type": "literalExpression", "text": "[\n \"data=journal\"\n]" }, "loc": ["fileSystems", "<name>", "options"], "readOnly": false, "type": "non-empty (list of string (with check: non-empty))" "relatedPackages": "- [`pkgs.tmux`](\n https://search.nixos.org/packages?show=tmux&sort=relevance&query=tmux\n )\n", }, ... } ``` ## optionsAsciiDoc Documentation rendered as AsciiDoc. This is useful for e.g. man pages. > Note: NixOS itself uses this output to to build the configuration.nix man page" ## optionsNix All options as a Nix attribute set value, with the same schema as `optionsJSON`. # Example ## Example: NixOS configuration ```nix let # Evaluate a NixOS configuration eval = import (pkgs.path + "/nixos/lib/eval-config.nix") { modules = [ ./module.nix ]; }; in pkgs.nixosOptionsDoc { inherit (eval) options; } ``` ## Example: non-NixOS modules `nixosOptionsDoc` can also be used to build documentation for non-NixOS modules. ```nix let eval = lib.evalModules { modules = [ ./module.nix ]; }; in pkgs.nixosOptionsDoc { inherit (eval) options; } ```
次に Flake モジュールを評価する必要があるのですが、flake-parts.lib.evalFlakeModule では評価後の perSystem のモジュールの options を評価するとよく分からないエラーになりました1。また、flake-parts.lib.evalFlakeModule を使用すると Flake Parts が提供するオプションまでドキュメントになってしまいます。これは要りません。なので自分のモジュールだけ単品で lib.evalModules で評価することにしました。しかし、これだと flake.apps などを参照する config の方がエラーになるので options だけのモジュールに分割して lib.evalModules に渡す必要がありました。
この辺りを乗り越えるとモジュールのオプションを Commonmark や Asciidoc に変換できるようになります。
出力したドキュメントはこんな感じになりました。

おしまい
pkgs がないというエラーなのですが、そんなことはないはず……↩例年ふりかえり記事を書いていないのですが、なんとなく書いてみるかという気になったので書いてみます。
人生で初めて入院しました。
一時的な症状でよかったですが、またなるのはこりごりです。
抗鬱薬は続けて飲んでいます。
変わらず Herp からの業務委託を受けています。
Nix を書いてることが多い感じがします。
今のペースで続けていきたいです。
妻と仲よく暮らしています。
昨年は庭できゅうりがめちゃくちゃ成りました。295 本。
屋外の水道管が破損して水漏れしました。賃借家屋なので管理会社経由で修理してもらいました。こういうとき水道局の減免制度があるから利用しよう。
『モナドドリル』を発行しました。
ドリルという性質上解説をたくさん入れるわけにはいかないので構成に頭を悩ましました。2 回はちゃぶ台返しをした気がします。
技術書典 18 と 19 で販売しました。
購入はこちらからどうぞ。
写真熱が冷めています。フィルムの期限が切れてるのでもっと撮った方がいいですね。歩くと体力も付くし。
カメラはちょっと増えました。
「ハーベストの丘」でめちゃくちゃわんちゃんにモテました。ネネちゃんというらしい。かわいい。寒かった。1 月。

「第27回プログラミングおよびプログラミング言語ワークショップ」に参加しに三谷温泉へ行きました。おもしろい話がいっぱい聞けて楽しい。温泉も入れる。3 月。

寝台特急「ウェストエクスプレス銀河」の座席が取れたので初めて出雲大社に行ってきました。「銀河」の乗客はみんな一癖ある感じ。出雲はその日だけ寒かった。帰りの HOT7000 系の一番前の座席が展望ですごくよかった。4 月。


「大阪関西万博」は 5 月に行ってきました。個別館はドイツにしか入られないぐらい混んでたんですけど、秋はもっとすごかったみたいですね。

東京の知り合いと現地合流して「静岡ホビーショー」に行ってきました。これもすごい混みようでモデラー展示はちょっとしか見られなかったです。メーカー展示は見たいところだいたい見られてよかった。5 月。

このあと 6 月に技術書典で東京に行って、5 月 6 月の遠出の疲れのせいか冒頭のめまい症になりました。
めまいから復帰し「関数型まつり」へ。来年あるなら何か話せればいいなあ。

doujin.kakkun61.com のメンテナンスをしたり、envar というツールを作ったりしました。
今年中に動くところまでできたらいいなあというツールも作っています。
鉄道模型向けの自作デジタルコマンドコントロール(DCC)の実装は中断されています。再開したい。
また、Kubernetes とか触ってみるかとサーバー用途にするために GMK Tech の G3 という Intel N150 機を買ってみました。なんとか昨日に Raspberry Pi 2 B も込みのクラスターを組めました。いやあこの辺り何も分からん。
定理証明支援系である Lean をさわり始めました。Language Server がすごくちゃんと動いていてすごいです。Haskell Language Server も安定して使えたらいいのになという思いが強くなりました。
ゼロから始めるLean言語入門 ― 手を動かして学ぶ形式数学ライブラリ開発
鉄道模型がまた増えました。なんで……? せめて部屋の線路を開通させねばならないです。一旦は開通させたものの出入りが難しくなるので跳ね上げ式にしようとした結果走れない状態になっています。Z ゲージのショーティー用のジオラマを作ったのは、小さくても満足感あるなという発見がありました。
プラモデルを組むのはいいけど塗装をしようとすると急に腰が重くなるので、それが簡単になるようなんかしくみを作りたいですね。
幸運であれば娘が生まれる予定で、しかも染色体異常があることが分かっているため、生まれた場合どういう生活になるのかまだ分からず、いろいろと予定が立てづらい状況です。無事に生まれてくれるといいなあ。
それでもこれらぐらいはしたいなと思っています。
2026 年もよろしくお願いします。
Envar というコマンドラインツールを作りました。
これは環境変数の値をディレクトリーごとに切り替えるツールです。
例えば FOO という環境変数について、ディレクトリー path/to/A では hoge という値にして、ディレクトリー path/to/B では fuga という値にする、ということができます。下記のような vars.yaml ファイルでその設定をします。
FOO: path/to/A: hoge path/to/B: fuga
また、環境変数の値を別のコマンドの出力値にするということもできます。
この例は自分が使っている設定ファイルから抜粋したもので、gh コマンドで使用するアカウントを私用・しごとで切り替えるものです。
# vars.yaml GH_TOKEN: /home/kazuki/Projects/Work: gh: kakkun61_work /home/kazuki/Projects: gh: kakkun61
# execs.yaml gh: gh auth token --user %s
direnv と何が違うの?
direnv はそのディレクトリーで設定したい環境変数をそのディレクトリーに置いた設定ファイルに書きます。主にプロジェクトを使う人みんなに必要になる環境変数を設定する用途です。プロジェクト都合の環境変数です。
それに対して envar は設定ファイルはユーザーの設定ディレクトリーに置きます(例えば ~/.config/envar)。上記例のアカウントの切り替えなど個人の都合の環境変数を設定する想定です。
対応しているシェルは?
いや別に飛行機の中でビルドするのが主題なわけではないのですが、オフラインモードのことを機内モードと言いますからね。最近の飛行機は Wi-Fi の提供があったりするらしいですが。
さて、あなたの Haskell プロジェクトをオフラインモードでビルドすることができますか? まあ、今時オフライン環境も珍しいですし「そんな必要あるのか?」という感覚もあるかもしれません。Nix ではビルド再現性のためにオフライン環境でビルドできることが求められます1。
Nix で Haskell プロジェクトをビルドするには Input Output(iohk.io)の作成した haskell.nix が使用されるのが普通です。
これは cabal ファイルや stack ファイル、もしくは plan ファイルを入力とし、Cabal のパッケージひとつにつきひとつの Nix デリベーションに翻訳するシステムです2。Cabal がやってることを Nix(と Haskell)で再実装したと言ってもいいんじゃないかと思います。
いやあ、これが「結構大掛かりなシステムだなあ」と思うわけですよね。「もうちょっと cabal-install に頼ってビルドできないかなあ」と前々から思っていて、とりあえず Proof of Concept が動いたので紹介しようと思います。
自分のアイデアの肝腎は Cabal の「ローカルリポジトリー」を使うことです。普通はローカルリポジトリーを使うことはありません。Hackage つまりリモートリポジトリーを使いますから。ですが、Cabal は Hackage 以外のリポジトリーも使えるように作られています。一般的には ~/.config/cabal/config にある設定ファイルには下記のように書かれています3。
repository hackage.haskell.org
url: http://hackage.haskell.org/
このファイルは、cabal update の実行時にこのファイルがなければデフォルトの内容で生成されます。そのデフォルトの内容に Hackage の URL が記載されているので、みんなは Hackage からパッケージを取ってこられます。なので、やろうと思えば社内リポジトリーを立てて社内ライブラリーを配布したりすることもできます(認証は秘密鍵でできるっぽい)4。そして、この URL の部分は file+nocache というスキーマの URL も書くことができます5。
repository my-local-repository
url: file+noindex:///absolute/path/to/directory
/absolute/path/to/directory のディレクトリーにはパッケージの sdist ファイルを配置します。
/absolute/path/to/directory/
foo-0.1.0.0.tar.gz
bar-0.2.0.0.tar.gz
ここまで準備できれば後は簡単で、下記ステップでオフラインビルドができるようになります。
cabal build するさて「ここまで準備できれば後は簡単」と書きましたが、依存ライブラリーの sdist を取得するはちょっと邪魔くさいです。間接依存や依存間のバージョン制約もあります。なので plan ファイルを元に sdist を取得するちょっとしたスクリプトを用意しました。
… dependencies=$(cabal-plan topo --hide-builtin | grep -v ' ') … for d in $dependencies do url=https://hackage.haskell.org/package/$d/$d.tar.gz if [ $verbose -eq 0 ] then wget --quiet "$url" else wget --no-verbose "$url" fi done
cabal-plan で依存のリストを取得して Hackage から wget でダウンロードするようにしています。
あとは flake.nix の buildPhase が肝腎なので気になる人は見ておくといいと思います6。
runHook preBuild # `cabal build` writes a file at a local repository, # and so it must be writable. cp -r --no-preserve=all $src/.local-repository . # This cabal.config file declares using the local repository. export CABAL_CONFIG=$src/cabal.config # Set a writable directory for cabal export CABAL_DIR=$TMPDIR/cabal cabal="cabal --project-dir=$src --builddir=$TMPDIR --verbose" $cabal v2-build --only-dependencies all $cabal v2-build all runHook postBuild
cabal.project ファイルに source-repository-package が記載されていたらどうなるのか確認できていません。もしかすると cabal.project ファイルも切り替えないといけないかもしれないです。cabal.project.local に何か記載すれば source-repository-package を無効化できたりしないかなあ。誰か教えてください。
#shared-cache fragment to the URI, then the cache will be stored inside the remote-repo-cache directory.」というのを見つけたので、ローカルリポジトリーをコピーするステップはなくすことができそう。↩