summaryrefslogtreecommitdiff
path: root/support/texlab/src/distro.rs
blob: f8693923662f15e633e971bda1507fb309ba31b3 (plain)
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
mod kpsewhich;
mod miktex;
mod texlive;

use std::process::{Command, Stdio};

use anyhow::Result;
use derive_more::Display;
use log::warn;

pub use kpsewhich::Resolver;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)]
pub enum DistributionKind {
    #[display(fmt = "TeXLive")]
    Texlive,
    #[display(fmt = "MikTeX")]
    Miktex,
    #[display(fmt = "Tectonic")]
    Tectonic,
    #[display(fmt = "Unknown")]
    Unknown,
}

#[derive(Debug, Clone)]
pub struct Distribution {
    pub kind: DistributionKind,
    pub resolver: Resolver,
}

impl Distribution {
    #[must_use]
    pub fn detect() -> Self {
        let kind = match Command::new("latex").arg("--version").output() {
            Ok(output) => {
                let stdout = String::from_utf8_lossy(&output.stdout);
                if stdout.contains("TeX Live") {
                    DistributionKind::Texlive
                } else if stdout.contains("MiKTeX") {
                    DistributionKind::Miktex
                } else {
                    DistributionKind::Unknown
                }
            }
            Err(_) => {
                if Command::new("tectonic")
                    .arg("--version")
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .status()
                    .is_ok()
                {
                    DistributionKind::Tectonic
                } else {
                    DistributionKind::Unknown
                }
            }
        };

        let resolver = match kind {
            DistributionKind::Texlive => Self::load_resolver(texlive::load_resolver),
            DistributionKind::Miktex => Self::load_resolver(miktex::load_resolver),
            DistributionKind::Tectonic | DistributionKind::Unknown => Resolver::default(),
        };
        Self { kind, resolver }
    }

    fn load_resolver(loader: impl FnOnce() -> Result<Resolver>) -> Resolver {
        match loader() {
            Ok(resolver) => return resolver,
            Err(why) => warn!("Failed to load resolver: {}", why),
        };
        Resolver::default()
    }
}