summaryrefslogtreecommitdiff
path: root/support/texlab/crates/tex/src/compile.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/tex/src/compile.rs')
-rw-r--r--support/texlab/crates/tex/src/compile.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/support/texlab/crates/tex/src/compile.rs b/support/texlab/crates/tex/src/compile.rs
new file mode 100644
index 0000000000..eeb7db9e4e
--- /dev/null
+++ b/support/texlab/crates/tex/src/compile.rs
@@ -0,0 +1,87 @@
+use futures::future::TryFutureExt;
+use std::io;
+use std::process::Stdio;
+use std::time::Duration;
+use tempfile::{tempdir, TempDir};
+use tokio::fs;
+use tokio::future::FutureExt;
+use tokio_net::process::Command;
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum Format {
+ Latex,
+ Pdflatex,
+ Xelatex,
+ Lualatex,
+}
+
+impl Format {
+ pub fn executable(self) -> &'static str {
+ match self {
+ Self::Latex => "latex",
+ Self::Pdflatex => "pdflatex",
+ Self::Xelatex => "xelatex",
+ Self::Lualatex => "lualatex",
+ }
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum OutputKind {
+ Dvi,
+ Pdf,
+}
+
+#[derive(Debug)]
+pub struct CompileResult {
+ pub log: String,
+ pub directory: TempDir,
+}
+
+#[derive(Debug)]
+pub enum CompileError {
+ IO(io::Error),
+ NotInstalled,
+ Timeout,
+}
+
+impl From<io::Error> for CompileError {
+ fn from(error: io::Error) -> Self {
+ Self::IO(error)
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct CompileParams<'a> {
+ pub file_name: &'a str,
+ pub code: &'a str,
+ pub format: Format,
+ pub timeout: Duration,
+}
+
+pub async fn compile<'a>(
+ executable: &'a str,
+ args: &'a [&'a str],
+ params: CompileParams<'a>,
+) -> Result<CompileResult, CompileError> {
+ let directory = tempdir()?;
+ let code_file = directory.path().join(params.file_name);
+ fs::write(code_file.clone(), params.code).await?;
+
+ Command::new(executable)
+ .args(args)
+ .current_dir(&directory)
+ .stdout(Stdio::null())
+ .stderr(Stdio::null())
+ .status()
+ .map_err(|_| CompileError::NotInstalled)
+ .timeout(params.timeout)
+ .map_err(|_| CompileError::Timeout)
+ .await?
+ .map_err(|_| CompileError::NotInstalled)?;
+
+ let log_file = code_file.with_extension("log");
+ let log_bytes = fs::read(log_file).await?;
+ let log = String::from_utf8_lossy(&log_bytes).into_owned();
+ Ok(CompileResult { log, directory })
+}