diff options
author | Norbert Preining <norbert@preining.info> | 2020-05-28 03:03:21 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-05-28 03:03:21 +0000 |
commit | 745892fbddea56040139108277e728b53fd8fc11 (patch) | |
tree | 15e55e299b38fccdabce8364f1fbf4f02ef37994 /support/texlab/src/tex/texlive.rs | |
parent | 195ca7e0c377d83455867bdd8e409d4e1cf024ea (diff) |
CTAN sync 202005280303
Diffstat (limited to 'support/texlab/src/tex/texlive.rs')
-rw-r--r-- | support/texlab/src/tex/texlive.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/support/texlab/src/tex/texlive.rs b/support/texlab/src/tex/texlive.rs new file mode 100644 index 0000000000..64bcfebdb7 --- /dev/null +++ b/support/texlab/src/tex/texlive.rs @@ -0,0 +1,71 @@ +use super::{ + compile, + kpsewhich::{self, KpsewhichError, Resolver}, + Artifacts, CompileError, CompileParams, Distribution, DistributionKind, +}; +use async_trait::async_trait; +use futures::lock::Mutex; +use std::{ + io, mem, + path::{Path, PathBuf}, + str::Lines, + sync::Arc, +}; +use tokio::fs; + +#[derive(Debug, Default)] +pub struct Texlive { + resolver: Mutex<Arc<Resolver>>, +} + +#[async_trait] +impl Distribution for Texlive { + fn kind(&self) -> DistributionKind { + DistributionKind::Texlive + } + + async fn compile<'a>(&'a self, params: CompileParams<'a>) -> Result<Artifacts, CompileError> { + compile(params).await + } + + async fn load(&self) -> Result<(), KpsewhichError> { + let root_directories = kpsewhich::root_directories().await?; + let resolver = kpsewhich::parse_database(&root_directories, read_database).await?; + mem::replace(&mut *self.resolver.lock().await, Arc::new(resolver)); + Ok(()) + } + + async fn resolver(&self) -> Arc<Resolver> { + let resolver = self.resolver.lock().await; + Arc::clone(&resolver) + } +} + +const DATABASE_PATH: &str = "ls-R"; + +async fn read_database(directory: &Path) -> Result<Vec<PathBuf>, KpsewhichError> { + let file = directory.join(DATABASE_PATH); + if !file.is_file() { + return Ok(Vec::new()); + } + + let text = fs::read_to_string(file) + .await + .map_err(|_| KpsewhichError::NoDatabase)?; + parse_database(text.lines()).map_err(|_| KpsewhichError::CorruptDatabase) +} + +fn parse_database(lines: Lines) -> io::Result<Vec<PathBuf>> { + let mut paths = Vec::new(); + let mut directory = ""; + + for line in lines.filter(|x| !x.trim().is_empty() && !x.starts_with('%')) { + if line.ends_with(':') { + directory = &line[..line.len() - 1]; + } else { + let path = PathBuf::from(directory).join(line); + paths.push(path); + } + } + Ok(paths) +} |