#! /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 '' -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 {}).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 <