Skip to main content

rustex_lib/engine/
files.rs

1use std::path::PathBuf;
2use tex_engine::engine::filesystem::{File, FileSystem, NoOutputFileSystem, VirtualFile};
3use tex_engine::engine::{EngineAux, EngineTypes};
4use tex_engine::prelude::CSName;
5use tex_engine::tex::characters::{StringLineSource, TextLine};
6use tex_engine::utils::errors::TeXResult;
7use tex_engine::utils::Ptr;
8
9static PGFSYS: &str = include_str!("../resources/pgfsys.def");
10static RUSTEX_DEFS: &str = include_str!("../resources/patches.tex");
11
12#[derive(Clone)]
13pub struct RusTeXFileSystem {
14    pub(crate) inner: NoOutputFileSystem<u8>,
15    pub(crate) svg: (<VirtualFile<u8> as File>::SourceRefID, Ptr<[TextLine<u8>]>),
16    pub(crate) defs: (<VirtualFile<u8> as File>::SourceRefID, Ptr<[TextLine<u8>]>),
17}
18impl RusTeXFileSystem {
19    pub fn new_with_envs<I: IntoIterator<Item = (String, String)>>(pwd: PathBuf, envs: I) -> Self {
20        let mut ret = Self::new(pwd);
21        ret.inner.envs.extend(envs);
22        ret
23    }
24
25    pub fn add_file(&mut self, path: PathBuf, file_content: &str) {
26        self.inner.add_file(path, file_content);
27    }
28
29    pub fn add_envs<I: IntoIterator<Item = (String, String)>>(&mut self, envs: I) {
30        self.inner.envs.extend(envs);
31    }
32}
33
34impl FileSystem for RusTeXFileSystem {
35    type File = VirtualFile<u8>;
36
37    fn new(pwd: PathBuf) -> Self {
38        let mut inner = NoOutputFileSystem::new(pwd);
39        let svg_id = inner
40            .interner
41            .get_or_intern("<TEXINPUTS>/pgfsys-rustex.def");
42        let ext_id = inner.interner.get_or_intern("<TEXINPUTS>/rustex_defs.def");
43        Self {
44            inner,
45            svg: (
46                Some(svg_id),
47                StringLineSource::make_lines(PGFSYS.as_bytes().iter().copied()).into(),
48            ),
49            defs: (
50                Some(ext_id),
51                StringLineSource::make_lines(RUSTEX_DEFS.as_bytes().iter().copied()).into(),
52            ),
53        }
54    }
55    fn ref_str(&self, id: <Self::File as File>::SourceRefID) -> &str {
56        self.inner.ref_str(id)
57    }
58
59    fn get<S: AsRef<str>>(&mut self, path: S) -> Self::File {
60        let sr = path.as_ref();
61        if sr.ends_with("pgfsys-rustex.def") {
62            VirtualFile {
63                path: self.inner.kpse.pwd.join("pgfsys-rustex.def"),
64                id: self.svg.0,
65                pipe: false,
66                exists: true,
67                source: Some(self.svg.1.clone()),
68            }
69        } else if sr.ends_with("rustex_defs.def") {
70            VirtualFile {
71                path: self.inner.kpse.pwd.join("rustex_defs.def"),
72                id: self.defs.0,
73                pipe: false,
74                exists: true,
75                source: Some(self.defs.1.clone()),
76            }
77        } else {
78            self.inner.get(sr)
79        }
80    }
81
82    fn set_pwd(&mut self, pwd: PathBuf) -> PathBuf {
83        self.inner.set_pwd(pwd)
84    }
85
86    fn open_out(&mut self, idx: u8, file: Self::File) {
87        self.inner.open_out(idx, file)
88    }
89
90    fn open_in(&mut self, idx: u8, file: Self::File) {
91        self.inner.open_in(idx, file)
92    }
93
94    fn close_in(&mut self, idx: u8) {
95        self.inner.close_in(idx)
96    }
97
98    fn close_out(&mut self, idx: u8) {
99        self.inner.close_out(idx)
100    }
101
102    fn eof(&self, idx: u8) -> bool {
103        self.inner.eof(idx)
104    }
105
106    fn write<ET: EngineTypes, D: std::fmt::Display>(
107        &mut self,
108        idx: i64,
109        string: D,
110        newlinechar: Option<ET::Char>,
111        aux: &mut EngineAux<ET>,
112    ) {
113        self.inner.write(idx, string, newlinechar, aux)
114    }
115
116    fn read<ET: EngineTypes<Char = <Self::File as File>::Char>, F: FnMut(ET::Token)>(
117        &mut self,
118        idx: u8,
119        handler: &mut <ET::CSName as CSName<ET::Char>>::Handler,
120        state: &ET::State,
121        cont: F,
122    ) -> TeXResult<(), ET> {
123        self.inner.read::<ET, F>(idx, handler, state, cont)
124    }
125
126    fn readline<ET: EngineTypes<Char = <Self::File as File>::Char>, F: FnMut(ET::Token)>(
127        &mut self,
128        idx: u8,
129        state: &ET::State,
130        cont: F,
131    ) -> TeXResult<(), ET> {
132        self.inner.readline(idx, state, cont)
133    }
134}