summaryrefslogtreecommitdiff
path: root/support/texlab/crates/tex/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/tex/src/lib.rs')
-rw-r--r--support/texlab/crates/tex/src/lib.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/support/texlab/crates/tex/src/lib.rs b/support/texlab/crates/tex/src/lib.rs
new file mode 100644
index 0000000000..5075ec0efb
--- /dev/null
+++ b/support/texlab/crates/tex/src/lib.rs
@@ -0,0 +1,106 @@
+mod compile;
+mod language;
+mod miktex;
+mod tectonic;
+mod texlive;
+
+pub use self::compile::*;
+pub use self::language::Language;
+
+use self::miktex::Miktex;
+use self::tectonic::Tectonic;
+use self::texlive::Texlive;
+use futures_boxed::boxed;
+use tokio_net::process::Command;
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum DistributionKind {
+ Texlive,
+ Miktex,
+ Tectonic,
+ Unknown,
+}
+
+impl DistributionKind {
+ pub async fn detect() -> Self {
+ if Command::new("tectonic")
+ .arg("--version")
+ .status()
+ .await
+ .is_ok()
+ {
+ return Self::Tectonic;
+ }
+
+ match Command::new("latex").arg("--version").output().await {
+ Ok(output) => {
+ let stdout = String::from_utf8_lossy(&output.stdout);
+ if stdout.contains("TeX Live") {
+ Self::Texlive
+ } else if stdout.contains("MiKTeX") {
+ Self::Miktex
+ } else {
+ Self::Unknown
+ }
+ }
+ Err(_) => Self::Unknown,
+ }
+ }
+}
+
+pub trait Distribution: Send + Sync {
+ fn kind(&self) -> DistributionKind;
+
+ fn supports_format(&self, format: Format) -> bool;
+
+ fn output_kind(&self, format: Format) -> OutputKind {
+ match format {
+ Format::Latex => OutputKind::Dvi,
+ Format::Pdflatex | Format::Xelatex | Format::Lualatex => OutputKind::Pdf,
+ }
+ }
+
+ #[boxed]
+ async fn compile<'a>(
+ &'a self,
+ params: CompileParams<'a>,
+ ) -> Result<CompileResult, CompileError> {
+ let executable = params.format.executable();
+ let args = &["--interaction=batchmode", "-shell-escape", params.file_name];
+ compile(executable, args, params).await
+ }
+}
+
+impl dyn Distribution {
+ pub async fn detect() -> Box<Self> {
+ let kind = DistributionKind::detect().await;
+ let distro: Box<Self> = match kind {
+ DistributionKind::Texlive => Box::new(Texlive),
+ DistributionKind::Miktex => Box::new(Miktex),
+ DistributionKind::Tectonic => Box::new(Tectonic),
+ DistributionKind::Unknown => Box::new(Unknown),
+ };
+ distro
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Unknown;
+
+impl Distribution for Unknown {
+ fn kind(&self) -> DistributionKind {
+ DistributionKind::Unknown
+ }
+
+ fn supports_format(&self, _format: Format) -> bool {
+ false
+ }
+
+ #[boxed]
+ async fn compile<'a>(
+ &'a self,
+ _params: CompileParams<'a>,
+ ) -> Result<CompileResult, CompileError> {
+ Err(CompileError::NotInstalled)
+ }
+}