diff options
Diffstat (limited to 'texnix')
-rwxr-xr-x | texnix | 102 |
1 files changed, 102 insertions, 0 deletions
@@ -0,0 +1,102 @@ +#! /bin/sh +# usage: texnix TEXFILE... +# Print Nix expression for creating a TeX working environment for a set of +# TEXFILEs. + +set -efu + +texnix_version=1.0.0 + +TMPDIR=$(mktemp --tmpdir -d texnix.XXXXXXXX) +trap 'rm -R "$TMPDIR"' EXIT + +# Export TMPDIR for subsequent calls to mktemp. +export TMPDIR + +# usage: extract_dependencies TEXFILE... +# Print all (transitive) dependencies of TEXFILEs. +extract_dependencies() {( + all_packages=$TMPDIR/all_packages + dependencies=$TMPDIR/dependencies + working_set=$TMPDIR/working_set + + get_all_packages > "$all_packages" + truncate -s 0 "$dependencies" + get_packages "$@" | comm -12 - "$all_packages" > "$working_set" + + while test -s "$working_set"; do + package=$(pop "$working_set") + + echo "$package" | add "$dependencies" + + tmp_working_set=$(mktemp working_set.XXXXXXXX) + { cat "$working_set" + texlive_cat "$package" | get_packages - | comm -2 - "$dependencies" + } | sort -u | comm -12 - "$all_packages" > "$tmp_working_set" + mv "$tmp_working_set" "$working_set" + done + + cat "$dependencies" +)} + +# usage: texlive_cat PACKAGE +# Concatenate and print all files of a TeX live package. +texlive_cat() { + nix-build --no-out-link '<nixpkgs>' -A texlive."$1".pkgs | + while read -r path; do + find "$path" -mindepth 1 -maxdepth 1 -name tex -exec find {} -type f \; + done | + xargs cat +} + +# usage: get_all_packages +# Print all TeX live packages. +get_all_packages() { + nix-instantiate \ + --eval \ + --json \ + --strict \ + -E \ + 'builtins.attrNames (import <nixpkgs> {}).texlive' \ + | + jq -r .[] | + sort -u +} + +# usage: get_packages TEXFILE... +# Print all packages used in TEXFILEs. +get_packages() { + sed -rn ' + s:.*(usepackage|RequirePackage).*\{([^}]+)}:\2:;T + s:,:\n:g + p + ' "$@" | + sort -u +} + +# usage: add SETFILE +# Add lines read from stdin to SETFILE. +add() {( + t=$(mktemp add.XXXXXXXX) + sort -u - "$1" > "$t" + mv "$t" "$1" +)} + +# usage: pop FILE +# Remove first line of FILE and print it to stdout. +pop() { + head -1 "$1" + sed -i 1d "$1" +} + +cat <<EOF +# Generated with texnix $texnix_version +{ texlive, extraTexPackages ? {} }: +texlive.combine ({ + inherit (texlive) scheme-small; + $(extract_dependencies "$@" | sed ' + s/.*/"&" = texlive."&";/ + 2,$s/^/ / + ') +} // extraTexPackages) +EOF |