summaryrefslogtreecommitdiff
path: root/support/texlab/crates/parser/src/latexmkrc.rs
blob: 63c92bd353aa1158e7c8a053b565b4d5dc7bc04e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use syntax::latexmkrc::LatexmkrcData;
use tempfile::tempdir;

pub fn parse_latexmkrc(_input: &str) -> std::io::Result<LatexmkrcData> {
    let temp_dir = tempdir()?;
    let non_existent_tex = temp_dir.path().join("NONEXISTENT.tex");

    // Run `latexmk -dir-report $TMPDIR/NONEXISTENT.tex` to obtain out_dir
    // and aux_dir values. We pass nonexistent file to prevent latexmk from
    // building anything, since we need this invocation only to extract the
    // -dir-report variables.
    //
    // In the future, latexmk plans to implement -dir-report-only option and we
    // won't have to resort to this hack with NONEXISTENT.tex.
    let output = std::process::Command::new("latexmk")
        .arg("-dir-report")
        .arg(non_existent_tex)
        .output()?;

    let stderr = String::from_utf8_lossy(&output.stderr);

    let (aux_dir, out_dir) = stderr.lines().find_map(extract_dirs).ok_or_else(|| {
        std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            "Normalized aux and out dir were not found in latexmk output",
        )
    })?;

    Ok(LatexmkrcData {
        aux_dir: Some(aux_dir),
        out_dir: Some(out_dir),
    })
}

/// Extracts $aux_dir and $out_dir from lines of the form
///
///   Latexmk: Normalized aux dir and out dir: '$aux_dir', '$out_dir'
fn extract_dirs(line: &str) -> Option<(String, String)> {
    let mut it = line
        .strip_prefix("Latexmk: Normalized aux dir and out dir: ")?
        .split(", ");

    let aux_dir = it.next()?.strip_prefix('\'')?.strip_suffix('\'')?;
    let out_dir = it.next()?.strip_prefix('\'')?.strip_suffix('\'')?;

    // Ensure there's no more data
    if it.next().is_some() {
        return None;
    }

    Some((String::from(aux_dir), String::from(out_dir)))
}