nixpkgs/pkgs/tools/typesetting/tex/nix/default.nix

250 lines
6.0 KiB
Nix

pkgs:
rec {
runLaTeX =
{ rootFile
, generatePDF ? true # generate PDF, not DVI
, generatePS ? false # generate PS in addition to DVI
, extraFiles ? []
, compressBlanksInIndex ? true
, packages ? []
, texPackages ? {}
, copySources ? false
}:
assert generatePDF -> !generatePS;
let
tex = pkgs.texlive.combine
# always include basic stuff you need for LaTeX
({inherit (pkgs.texlive) scheme-basic;} // texPackages);
in
pkgs.stdenv.mkDerivation {
name = "doc";
builder = ./run-latex.sh;
copyIncludes = ./copy-includes.pl;
inherit rootFile generatePDF generatePS extraFiles
compressBlanksInIndex copySources;
includes = map (x: [x.key (baseNameOf (toString x.key))])
(findLaTeXIncludes {inherit rootFile;});
buildInputs = [ tex pkgs.perl ] ++ packages;
};
# Returns the closure of the "dependencies" of a LaTeX source file.
# Dependencies are other LaTeX source files (e.g. included using
# \input{}), images (e.g. \includegraphics{}), bibliographies, and
# so on.
findLaTeXIncludes =
{ rootFile
}:
builtins.genericClosure {
startSet = [{key = rootFile;}];
operator =
{key, ...}:
let
# `find-includes.pl' returns the dependencies of the current
# source file (`key') as a list, e.g. [{type = "tex"; name =
# "introduction.tex";} {type = "img"; name = "example"}].
# The type denotes the kind of dependency, which determines
# what extensions we use to look for it.
deps = import (pkgs.runCommand "latex-includes"
{ rootFile = baseNameOf (toString rootFile); src = key; }
"${pkgs.perl}/bin/perl ${./find-includes.pl}");
# Look for the dependencies of `key', trying various
# extensions determined by the type of each dependency.
# TODO: support a search path.
foundDeps = dep: xs:
let
exts =
if dep.type == "img" then [".pdf" ".png" ".ps" ".jpg"]
else if dep.type == "tex" then [".tex" ""]
else [""];
fn = pkgs.lib.findFirst (fn: builtins.pathExists fn) null
(map (ext: dirOf key + ("/" + dep.name + ext)) exts);
in if fn != null then [{key = fn;}] ++ xs
else xs;
in pkgs.lib.foldr foundDeps [] deps;
};
findLhs2TeXIncludes =
{ rootFile
}:
builtins.genericClosure {
startSet = [{key = rootFile;}];
operator =
{key, ...}:
let
deps = import (pkgs.runCommand "lhs2tex-includes"
{ src = key; }
"${pkgs.stdenv.bash}/bin/bash ${./find-lhs2tex-includes.sh}");
in pkgs.lib.concatMap (x: if builtins.pathExists x then [{key = x;}] else [])
(map (x: dirOf key + ("/" + x)) deps);
};
dot2pdf =
{ dotGraph
}:
pkgs.stdenv.mkDerivation {
name = "pdf";
builder = ./dot2pdf.sh;
inherit dotGraph fontsConf;
buildInputs = [
pkgs.perl pkgs.graphviz
];
};
dot2ps =
{ dotGraph
}:
pkgs.stdenv.mkDerivation {
name = "ps";
builder = ./dot2ps.sh;
inherit dotGraph;
buildInputs = [
pkgs.perl pkgs.graphviz pkgs.ghostscript
];
};
lhs2tex =
{ source, flags ? null } :
pkgs.stdenv.mkDerivation {
name = "tex";
builder = ./lhs2tex.sh;
inherit source flags;
buildInputs = [ pkgs.lhs2tex pkgs.perl ];
copyIncludes = ./copy-includes.pl;
includes = map (x: [x.key (baseNameOf (toString x.key))])
(findLhs2TeXIncludes {rootFile = source;});
};
animateDot = dotGraph: nrFrames: pkgs.stdenv.mkDerivation {
name = "dot-frames";
builder = ./animatedot.sh;
inherit dotGraph nrFrames;
};
# Wrap a piece of TeX code in a document. Useful when generating
# inline images from TeX code.
wrapSimpleTeX =
{ preamble ? null
, body
, name ? baseNameOf (toString body)
}:
pkgs.stdenv.mkDerivation {
inherit name preamble body;
buildCommand = ''
touch $out
echo '\documentclass{article}' >> $out
echo '\pagestyle{empty}' >> $out
if test -n "$preamble"; then cat $preamble >> $out; fi
echo '\begin{document}' >> $out
cat $body >> $out
echo '\end{document}' >> $out
'';
};
# Convert a Postscript file to a PNG image, trimming it so that
# there is no unnecessary surrounding whitespace.
postscriptToPNG =
{ postscript
}:
pkgs.stdenv.mkDerivation {
name = "png";
inherit postscript;
buildInputs = [pkgs.imagemagick pkgs.ghostscript];
buildCommand = ''
if test -d $postscript; then
input=$(ls $postscript/*.ps)
else
input=$(stripHash $postscript)
ln -s $postscript $input
fi
mkdir -p $out
convert -units PixelsPerInch \
-density 600 \
-trim \
-matte \
-transparent '#ffffff' \
-type PaletteMatte \
+repage \
$input \
"$out/$(basename $input .ps).png"
''; # */
};
# Convert a piece of TeX code to a PNG image.
simpleTeXToPNG =
{ preamble ? null
, body
, packages ? []
}:
postscriptToPNG {
postscript = runLaTeX {
rootFile = wrapSimpleTeX {
inherit body preamble;
};
inherit packages;
generatePDF = false;
generatePS = true;
};
};
# Convert a piece of TeX code to a PDF.
simpleTeXToPDF =
{ preamble ? null
, body
, packages ? []
}:
runLaTeX {
rootFile = wrapSimpleTeX {
inherit body preamble;
};
inherit packages;
};
# Some tools (like dot) need a fontconfig configuration file.
# This should be extended to allow the called to add additional
# fonts.
fontsConf = pkgs.makeFontsConf {
fontDirectories = [
"${pkgs.ghostscript}/share/ghostscript/fonts"
];
};
}