retex-kpath 1.3.0-alpha.2

kpathsea-compatible file lookup for retex
Documentation
//! File formats known to kpathsea and their search parameters.

/// A kind of file to look up, mirroring kpathsea's `kpse_file_format_type`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FileFormat {
    /// TeX input files (`.tex`, and anything `\input` can read).
    Tex,
    /// Lua modules (`require` from LuaTeX).
    Lua,
    /// Format files (`.fmt`).
    Fmt,
    /// TeX font metrics (`.tfm`).
    Tfm,
    /// OpenType fonts (`.otf`).
    OpenType,
    /// TrueType fonts and collections (`.ttf`, `.ttc`).
    TrueType,
    /// Type 1 fonts (`.pfb`, `.pfa`).
    Type1,
    /// Encoding vectors (`.enc`).
    Enc,
    /// Font map files (`.map`).
    Map,
    /// Virtual fonts (`.vf`).
    Vf,
    /// BibTeX databases (`.bib`).
    Bib,
    /// BibTeX styles (`.bst`).
    Bst,
    /// Graphics and other files read by the backend (`TEXPICTS`).
    Pict,
    /// PostScript headers (`.pro`), which luapstricks reads.
    PsHeader,
    /// Files opened with `kpse.find_file(name, "other text files")`.
    Text,
}

/// Search parameters for a [`FileFormat`].
#[derive(Debug, Clone, Copy)]
pub struct FormatInfo {
    /// Variables holding the search path, in order of precedence.
    pub env_vars: &'static [&'static str],
    /// The path to use when no variable is set.
    pub default_path: &'static str,
    /// Standard suffixes, tried before the bare name.
    pub suffixes: &'static [&'static str],
    /// Alternate suffixes: a name with one is not given a standard suffix
    /// (`article.cls` is not looked up as `article.cls.tex`).
    pub alt_suffixes: &'static [&'static str],
    /// Whether the bare name is tried after the suffixed ones (not for Lua
    /// modules: `kpsewhich -format=lua q` does not find a file `q`).
    pub bare: bool,
}

impl FileFormat {
    /// The search parameters for this format.
    pub fn info(self) -> FormatInfo {
        let (env_vars, suffixes): (&[&str], &[&str]) = match self {
            FileFormat::Tex => (&["TEXINPUTS"], &[".tex"]),
            FileFormat::Lua => (
                &["LUAINPUTS"],
                &[
                    ".lua", ".luatex", ".luc", ".luctex", ".texlua", ".texluc", ".tlu",
                ],
            ),
            FileFormat::Fmt => (&["TEXFORMATS", "TEXMFINI"], &[".fmt"]),
            FileFormat::Tfm => (&["TFMFONTS", "TEXFONTS"], &[".tfm"]),
            FileFormat::OpenType => (&["OPENTYPEFONTS", "TEXFONTS"], &[".otf", ".OTF"]),
            FileFormat::TrueType => (
                &["TTFONTS", "TEXFONTS"],
                &[".ttf", ".ttc", ".TTF", ".TTC", ".dfont"],
            ),
            FileFormat::Type1 => (
                &[
                    "T1FONTS",
                    "T1INPUTS",
                    "TEXFONTS",
                    "TEXPSHEADERS",
                    "PSHEADERS",
                ],
                &[".pfa", ".pfb"],
            ),
            FileFormat::Enc => (&["ENCFONTS", "TEXFONTS"], &[".enc"]),
            FileFormat::Map => (&["TEXFONTMAPS", "TEXFONTS"], &[".map"]),
            FileFormat::Vf => (&["VFFONTS", "TEXFONTS"], &[".vf"]),
            FileFormat::Bib => (&["BIBINPUTS", "TEXBIB"], &[".bib"]),
            FileFormat::Bst => (&["BSTINPUTS"], &[".bst"]),
            FileFormat::Pict => (&["TEXPICTS", "TEXINPUTS"], &[]),
            FileFormat::PsHeader => (&["TEXPSHEADERS", "PSHEADERS"], &[".pro"]),
            // See [`FileFormat::variables`].
            FileFormat::Text => (&[], &[]),
        };
        // The paths compiled into kpathsea for the variables texmf.cnf
        // does not set (`kpsewhich -show-path`).
        let default_path = match self {
            FileFormat::Text => ".:$TEXMF/$progname//",
            _ => ".",
        };
        // Observed with `kpsewhich --help-formats`.
        let alt_suffixes: &[&str] = match self {
            FileFormat::Tex => &[
                ".sty", ".cls", ".fd", ".aux", ".bbl", ".def", ".clo", ".ldf",
            ],
            FileFormat::Pict => &[".eps", ".epsi"],
            _ => &[],
        };
        FormatInfo {
            env_vars,
            default_path,
            suffixes,
            alt_suffixes,
            bare: self != FileFormat::Lua,
        }
    }

    /// The variables holding the search path for program `progname`, in
    /// order of precedence. For "other text files" it is the program name
    /// in capitals followed by `INPUTS` (`LUALATEXINPUTS`; `kpsewhich
    /// -progname=lualatex --help-formats`).
    pub fn variables(self, progname: &str) -> Vec<String> {
        match self {
            FileFormat::Text => vec![format!("{}INPUTS", progname.to_ascii_uppercase())],
            _ => self
                .info()
                .env_vars
                .iter()
                .map(|v| (*v).to_owned())
                .collect(),
        }
    }
}