1#![feature(default_field_values)]
7#![feature(const_trait_impl)]
8
9mod argument;
11mod console;
12mod layout;
13mod problem;
14#[cfg(test)]
15mod tests;
16
17use std::{
19 collections::HashMap as Map,
20 env::{
21 args,
22 vars
23 },
24 io::{
25 Write,
26 stderr
27 },
28 sync::LazyLock
29};
30
31use libutils_cage::Cage;
33
34use libutils_threat::Threat;
36
37use libutils_diff::Diff;
39
40use layout::Layout;
42
43pub use console::Console;
45
46pub use argument::Argument;
48
49
50pub static TERMINAL: Cage<Terminal> = Cage::new(Terminal {..});
56
57pub struct Terminal {
59 layout: Layout = Layout {..},
60 arguments: LazyLock<Vec<Argument>> = LazyLock::new(|| args().map(Argument::from).collect()),
61 pub environment: LazyLock<Map<String, String>> = LazyLock::new(|| vars().collect()),
62 stderr: String = String::new()
63}
64
65impl Console for Terminal {
67 #[inline]
68 fn arguments(&self) -> &[Argument] {return self.arguments.as_slice()}
69 #[inline]
70 fn sync(&mut self) -> () {
71 let content = self.layout.view();
72 stderr().lock().write(<Diff as Into<Vec<u8>>>::into(Diff::new(self.stderr.as_bytes(), content.as_bytes())).as_ref()).unwrap();
73 self.stderr = content;
74 }
75 #[inline]
76 fn problem(&mut self, threat: Threat) -> () {self.layout.problems.push(threat.into())}
77}