From 3396a8eae8bd1c31173f2c9761d5cf8e2302af5d Mon Sep 17 00:00:00 2001 From: Ivan Oleynikov Date: Mon, 27 Nov 2023 19:09:49 +0100 Subject: [PATCH 1/2] Reliably determine latexmk's aux_dir and out_dir using -dir-report This commit makes texlab determine aux_dir and out_dir variables by calling latexmkrc -dir-report $TMPDIR/NONEXISTENT.tex Passing NONEXISTENT file is a hack to prevent latexmk from building anything. And the $TMPDIR part should ensure 100% that this file does not exist (to avoid event rarest cases when user may have a file called NONEXISTENT.tex in current working directory). This should be a more correct than `latexmk -r $TMPDIR/latexmkrc`, since -dir-report was intended exactly for this and it prints normalized values. --- crates/parser/src/latexmkrc.rs | 72 ++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/crates/parser/src/latexmkrc.rs b/crates/parser/src/latexmkrc.rs index e849c96c..52e6697f 100644 --- a/crates/parser/src/latexmkrc.rs +++ b/crates/parser/src/latexmkrc.rs @@ -3,43 +3,55 @@ use std::io::Write; use syntax::latexmkrc::LatexmkrcData; use tempfile::tempdir; -/// Extra section at the bottom of the latexmkrc file to print the values of $aux_dir and $log_dir. -const EXTRA: &str = r#" -print "texlab:aux_dir=" . $aux_dir . "\n"; -print "texlab:out_dir=" . $out_dir . "\n"; -exit 0; # Don't build the document"#; - -pub fn parse_latexmkrc(input: &str) -> std::io::Result { +pub fn parse_latexmkrc(_input: &str) -> std::io::Result { let temp_dir = tempdir()?; - let rc_path = temp_dir.path().join("latexmkrc"); - let mut rc_file = std::fs::File::create(&rc_path)?; - rc_file.write_all(input.as_bytes())?; - rc_file.write_all(EXTRA.as_bytes())?; - drop(rc_file); - + 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("-r") - .arg(rc_path) + .arg("-dir-report") + .arg(non_existent_tex) .output()?; - let mut result = LatexmkrcData::default(); let stdout = String::from_utf8_lossy(&output.stdout); - for line in stdout.lines() { - result.aux_dir = result - .aux_dir - .or_else(|| extract_dir(line, "texlab:aux_dir=")); - - result.out_dir = result - .out_dir - .or_else(|| extract_dir(line, "texlab:out_dir=")); - } + let (aux_dir, out_dir) = stdout + .lines() + .filter_map(extract_dirs) + .next() + .expect("Normalized aux and out dir were not found in latexmk output"); - Ok(result) + Ok(LatexmkrcData { + aux_dir: Some(aux_dir), + out_dir: Some(out_dir), + }) } -fn extract_dir(line: &str, key: &str) -> Option { - line.strip_prefix(key) - .filter(|path| !path.is_empty()) - .map(String::from) +/// 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: ") + .filter(|path| !path.is_empty())? + .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), + )) } From aebfe73d337d3bfba58b16d3edf00a417dc94e48 Mon Sep 17 00:00:00 2001 From: Ivan Oleynikov Date: Mon, 27 Nov 2023 20:49:51 +0100 Subject: [PATCH 2/2] remove a reduntant check --- crates/parser/src/latexmkrc.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/parser/src/latexmkrc.rs b/crates/parser/src/latexmkrc.rs index 52e6697f..96913106 100644 --- a/crates/parser/src/latexmkrc.rs +++ b/crates/parser/src/latexmkrc.rs @@ -38,8 +38,7 @@ pub fn parse_latexmkrc(_input: &str) -> std::io::Result { /// 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: ") - .filter(|path| !path.is_empty())? + .strip_prefix("Latexmk: Normalized aux dir and out dir: ")? .split(", "); let aux_dir = it.next()?.strip_prefix('\'')?.strip_suffix('\'')?;