diff options
Diffstat (limited to 'support/texlab/crates/tex/src/compile.rs')
-rw-r--r-- | support/texlab/crates/tex/src/compile.rs | 87 |
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 }) +} |