1use crate::{At, Entry, Format, History};
2use core::fmt::{self, Write};
3#[cfg(feature = "std")]
4use std::time::SystemTime;
5
6pub struct Display<'a, E, S> {
8 history: &'a History<E, S>,
9 format: Format,
10 #[cfg(feature = "std")]
11 st_fmt: &'a dyn Fn(SystemTime, SystemTime) -> String,
12}
13
14impl<'a, E, S> Display<'a, E, S> {
15 #[cfg(feature = "colored")]
19 pub fn colored(&mut self, on: bool) -> &mut Self {
20 self.format.colored = on;
21 self
22 }
23
24 pub fn detailed(&mut self, on: bool) -> &mut Self {
26 self.format.detailed = on;
27 self
28 }
29
30 pub fn head(&mut self, on: bool) -> &mut Self {
32 self.format.head = on;
33 self
34 }
35
36 pub fn saved(&mut self, on: bool) -> &mut Self {
38 self.format.saved = on;
39 self
40 }
41
42 #[cfg(feature = "std")]
47 pub fn set_st_fmt(
48 &mut self,
49 st_fmt: &'a dyn Fn(SystemTime, SystemTime) -> String,
50 ) -> &mut Self {
51 self.st_fmt = st_fmt;
52 self
53 }
54}
55
56impl<E: fmt::Display, S> Display<'_, E, S> {
57 fn fmt_list(
58 &self,
59 f: &mut fmt::Formatter,
60 at: At,
61 entry: Option<&Entry<E>>,
62 level: usize,
63 #[cfg(feature = "std")] now: SystemTime,
64 ) -> fmt::Result {
65 self.format.mark(f, level)?;
66 self.format.at(f, at)?;
67
68 #[cfg(feature = "std")]
69 if let Some(entry) = entry {
70 if self.format.detailed {
71 let st_fmt = self.st_fmt;
72 let string = st_fmt(now, entry.st_of_latest());
73 self.format.elapsed(f, string)?;
74 }
75 }
76
77 self.format
78 .labels(f, at, self.history.head(), self.history.saved())?;
79
80 if let Some(entry) = entry {
81 if self.format.detailed {
82 writeln!(f)?;
83 self.format.message(f, entry, Some(level))?;
84 } else {
85 f.write_char(' ')?;
86 self.format.message(f, entry, Some(level))?;
87 writeln!(f)?;
88 }
89 }
90 Ok(())
91 }
92
93 fn fmt_graph(
94 &self,
95 f: &mut fmt::Formatter,
96 at: At,
97 entry: Option<&Entry<E>>,
98 level: usize,
99 #[cfg(feature = "std")] now: SystemTime,
100 ) -> fmt::Result {
101 for (i, branch) in self
102 .history
103 .branches()
104 .filter(|(_, branch)| branch.parent == at)
105 {
106 for (j, entry) in branch.entries.iter().enumerate().rev() {
107 let at = At::new(i, j + branch.parent.index + 1);
108 self.fmt_graph(
109 f,
110 at,
111 Some(entry),
112 level + 1,
113 #[cfg(feature = "std")]
114 now,
115 )?;
116 }
117
118 for j in 0..level {
119 self.format.edge(f, j)?;
120 f.write_char(' ')?;
121 }
122
123 self.format.split(f, level)?;
124 writeln!(f)?;
125 }
126
127 for i in 0..level {
128 self.format.edge(f, i)?;
129 f.write_char(' ')?;
130 }
131
132 self.fmt_list(
133 f,
134 at,
135 entry,
136 level,
137 #[cfg(feature = "std")]
138 now,
139 )
140 }
141}
142
143impl<'a, E, S> From<&'a History<E, S>> for Display<'a, E, S> {
144 fn from(history: &'a History<E, S>) -> Self {
145 Display {
146 history,
147 format: Format::default(),
148 #[cfg(feature = "std")]
149 st_fmt: &crate::format::default_st_fmt,
150 }
151 }
152}
153
154impl<E: fmt::Display, S> fmt::Display for Display<'_, E, S> {
155 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156 #[cfg(feature = "std")]
157 let now = SystemTime::now();
158 let root = self.history.root;
159 for (i, entry) in self.history.record.entries.iter().enumerate().rev() {
160 let at = At::new(root, i + 1);
161 self.fmt_graph(
162 f,
163 at,
164 Some(entry),
165 0,
166 #[cfg(feature = "std")]
167 now,
168 )?;
169 }
170 self.fmt_graph(
171 f,
172 At::new(root, 0),
173 None,
174 0,
175 #[cfg(feature = "std")]
176 now,
177 )
178 }
179}