1#![feature(const_trait_impl)]
7#![feature(const_default)]
8
9mod continuations;
11mod problem;
12mod section;
13#[cfg(test)]
14mod tests;
15
16use std::{
18 env::args,
19 fs::File,
20 path::PathBuf,
21 sync::LazyLock,
22 time::Instant
23};
24
25use core::fmt::{
27 Debug,
28 Display
29};
30
31use libutils_cage::Cage;
33
34use continuations::{
36 ActionRequired,
37 FileDescriptor
38};
39
40use libutils_issue::{
42 Issue,
43 Severity
44};
45
46use libutils_console::{
48 Console,
49 Argument,
50 Synchronization,
51 Descriptor
52};
53
54use section::Section;
56
57use problem::Problem;
59
60
61pub static TERMINAL: Terminal = Terminal {
67 arguments: LazyLock::new(|| args().map(Argument::from).collect()),
68 layout: Cage::default(),
69 output: Cage::default()
70};
71
72pub struct Terminal {
74 arguments: LazyLock<Vec<Argument>>,
75 layout: Cage<Vec<Section>>,
76 output: Cage<String>
77}
78
79impl Console for Terminal {
81 fn arguments<'valid>(&'valid self) -> &'valid [Argument] {return self.arguments.as_slice()}
82 fn open(&self, filename: &str) -> Result<impl Descriptor, Issue> {match File::open(PathBuf::from(filename)) {
83 Ok(file) => Ok(FileDescriptor {
84 file: file
85 }),
86 Err(error) => Err(Issue {
87 name: "Failed to open file",
88 description: Some(error.to_string()),
89 severity: Severity::Error
90 })
91 }}
92 fn problem(&self, issue: Issue, chain: &[&'static str]) -> impl Synchronization {
93 self.layout.write(|layout| layout.push(Section::Problem(Problem {
94 chain: Vec::from(chain),
95 issue: issue,
96 _at: Instant::now()
97 })));
98 return ActionRequired;
99 }
100 fn print(&self, value: impl Display) -> impl Synchronization {
101 self.layout.write(|layout| layout.push(Section::Display(value.to_string())));
102 return ActionRequired;
103 }
104 fn debug(&self, value: impl Debug) -> impl Synchronization {
105 self.layout.write(|layout| layout.push(Section::Debug(format!("{value:#?}"))));
106 return ActionRequired;
107 }
108}