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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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)
}
}
|