A somewhat common theme I’ve noticed when working on various projects is the need for “one-off” re-usable scripts, these are typically more than a few lines of code.
For example, in my Advent of Code repository I have a small Python script that pulls the input down given a year and day. But rather than wanting to manage this script explicitly, I wanted to encapsulate it as part of my flake so I can call it directly via nix.
It turns out, Nix has the concept of writers. These are functions that allow you to write other languages inline, in nix code.1 One other nice thing about this: you can add language-specific libraries as dependencies.
pkgs.writers.writePython3Bin "get_input" {
libraries = [ pkgs.python3Packages.requests ];
} ''
import requests
import sys
year, day = sys.argv[1], sys.argv[2]
url = 'https://adventofcode.com/{}/day/{}/input'.format(year, day)
cookie = open('cookie.txt').read().strip()
r = requests.get(url, cookies={'session': cookie})
print(r.text)
'';
Notice I was able to add requests
as a library
. From here, I am able to
call this script directly via the command:
$ nix run . -- 2022 5
There are some other ways this can be extended of course:
- Adding more scripts, effectively making the flake a trivial command runner.
- If the script becomes too large, you can always split it back out into its own file, then directly reading that file into the flake.
- Placing the script as a package in a dev shell, so that it’s available via
nix develop
.
-
Thank you fellow Nix enthusiasts in the Matrix channel for pointing me to these. ↩︎