easy_sgr/writing.rs
1use std::{fmt, io};
2
3use crate::{DiscreteSGR, SGRString};
4
5/// An interface for an [`SGRWriter`] to work with
6///
7/// Does not provide SGR writing capability itself
8pub trait CapableWriter: Sized {
9 /// The writer that will be internally used
10 ///
11 /// i.e. what [`CapableWriter::write`] will call upon
12 type Writer;
13 /// The type of error returned by trait methods
14 ///
15 /// Will typically be [`std::io::Error`] or [`std::fmt::Error`]
16 type Error: std::error::Error;
17 /// Writes a [`str`] to the inner writer
18 ///
19 /// # Errors
20 ///
21 /// Returns an error if writing fails.
22 /// Error type specified by [`CapableWriter::Error`]
23 fn write(&mut self, s: &str) -> Result<(), Self::Error>;
24 /// Returns the type specified by [`CapableWriter::Writer`]
25 fn get_writer(self) -> Self::Writer;
26}
27/// A Standard SGR writer
28#[derive(Debug, Clone)]
29pub struct SGRWriter<W: CapableWriter> {
30 /// A writer capable of writing a [`str`]
31 pub writer: W,
32}
33impl<W: CapableWriter> SGRWriter<W> {
34 /// Writes a [`str`] to the inner writer
35 ///
36 /// A shortcut to [`CapableWriter::write`] without having to import it
37 ///
38 /// # Errors
39 ///
40 /// Returns an error if writing fails.
41 /// Error type specified by [`CapableWriter::Error`]
42 #[inline]
43 pub fn write_inner(&mut self, s: &str) -> Result<(), W::Error> {
44 self.write(s)
45 }
46 /// Returns the internal writer
47 ///
48 /// Returns the type specified by [`CapableWriter::get_writer`]
49 #[inline]
50 #[must_use]
51 pub fn internal(self) -> W::Writer {
52 self.get_writer().get_writer()
53 }
54 /// Returns a new, empty [`SGRBuilder`]
55 ///
56 /// Used for convenience
57 #[inline]
58 pub fn builder(&self) -> SGRBuilder {
59 SGRBuilder::default()
60 }
61 /// Writes the contained SGR codes to the writer through calling [`SGRString::place_all`]
62 ///
63 /// # Errors
64 ///
65 /// Returns an error if writing fails.
66 /// Error type specified by [`CapableWriter::Error`]
67 #[inline]
68 pub fn place_sgr(&mut self, sgr: &SGRString) -> Result<(), W::Error> {
69 let mut builder = SGRBuilder::default();
70 sgr.place_all(&mut builder);
71 builder.write_to(self)
72 }
73 /// Writes the contained SGR codes to the writer through calling [`SGRString::clean_all`]
74 ///
75 /// Supposed to reverse the effects made by [`SGRString::place_all`]
76 ///
77 /// # Errors
78 ///
79 /// Returns an error if writing fails.
80 /// Error type specified by [`CapableWriter::Error`]
81 #[inline]
82 pub fn clean_sgr(&mut self, sgr: &SGRString) -> Result<(), W::Error> {
83 let mut builder = SGRBuilder::default();
84 sgr.clean_all(&mut builder);
85 builder.write_to(self)
86 }
87 /// Writes the contained SGR codes to the writer through calling [`DiscreteSGR::write`]
88 ///
89 /// # Errors
90 ///
91 /// Returns an error if writing fails.
92 /// Error type specified by [`CapableWriter::Error`]
93 #[inline]
94 pub fn inline_sgr(&mut self, sgr: &impl DiscreteSGR) -> Result<(), W::Error> {
95 let mut builder = SGRBuilder::default();
96 sgr.write(&mut builder);
97 builder.write_to(self)
98 }
99 /// Writes the contained SGR codes to the writer
100 ///
101 /// Uses [`EasyWrite`] so the it can be used for both
102 /// [`SGRString`] and [`DiscreteSGR`]
103 ///
104 /// # Errors
105 ///
106 /// Returns an error if writing fails.
107 /// Error type specified by [`CapableWriter::Error`]
108 pub fn sgr(&mut self, sgr: &impl EasyWrite) -> Result<(), W::Error> {
109 let mut builder = SGRBuilder::default();
110 sgr.sgr(&mut builder);
111 builder.write_to(self)
112 }
113 /// Writes the contained SGR codes to the writer
114 ///
115 /// Does not write the escape or end sequences
116 ///
117 /// Uses [`EasyWrite`] so the it can be used for both
118 /// [`SGRString`] and [`DiscreteSGR`]
119 ///
120 /// # Errors
121 ///
122 /// Returns an error if writing fails.
123 /// Error type specified by [`CapableWriter::Error`]
124 #[inline]
125 pub fn partial_sgr(&mut self, sgr: &impl EasyWrite) -> Result<(), W::Error> {
126 let mut builder = SGRBuilder::default();
127 sgr.sgr(&mut builder);
128 builder.write_partial(self)
129 }
130}
131impl<W: CapableWriter> From<W> for SGRWriter<W> {
132 fn from(value: W) -> Self {
133 Self { writer: value }
134 }
135}
136impl<W: std::fmt::Write> From<W> for SGRWriter<FmtWriter<W>> {
137 fn from(value: W) -> Self {
138 Self {
139 writer: FmtWriter(value),
140 }
141 }
142}
143impl<W: std::io::Write> From<W> for SGRWriter<IoWriter<W>> {
144 fn from(value: W) -> Self {
145 Self {
146 writer: IoWriter(value),
147 }
148 }
149}
150impl<W: CapableWriter> CapableWriter for SGRWriter<W> {
151 type Writer = W;
152 type Error = W::Error;
153 #[inline]
154 fn write(&mut self, s: &str) -> Result<(), Self::Error> {
155 self.writer.write(s)
156 }
157 #[must_use]
158 fn get_writer(self) -> Self::Writer {
159 self.writer
160 }
161}
162/// Used to implement [`CapableWriter`] for [`std::io::Write`]
163#[derive(Debug, Clone)]
164pub struct IoWriter<W: std::io::Write>(pub W);
165impl<W: std::io::Write> CapableWriter for IoWriter<W> {
166 type Writer = W;
167 type Error = io::Error;
168 #[inline]
169 fn write(&mut self, s: &str) -> Result<(), Self::Error> {
170 self.0.write_all(s.as_bytes())
171 }
172
173 #[must_use]
174 fn get_writer(self) -> Self::Writer {
175 self.0
176 }
177}
178/// Used to implement [`CapableWriter`] for [`std::fmt::Write`]
179#[derive(Debug, Clone)]
180pub struct FmtWriter<W: std::fmt::Write>(pub W);
181impl<W: std::fmt::Write> CapableWriter for FmtWriter<W> {
182 type Writer = W;
183 type Error = fmt::Error;
184 #[inline]
185 fn write(&mut self, s: &str) -> Result<(), Self::Error> {
186 self.0.write_str(s)
187 }
188 #[must_use]
189 fn get_writer(self) -> Self::Writer {
190 self.0
191 }
192}
193/// Builds a SGR sequence
194#[derive(Debug, Default)]
195pub struct SGRBuilder(pub Vec<u8>);
196
197impl SGRBuilder {
198 /// Writes a code to the internal buffer
199 #[inline]
200 pub fn write_code(&mut self, code: u8) {
201 self.0.push(code);
202 }
203 /// Writes codes to the internal buffer
204 #[inline]
205 pub fn write_codes(&mut self, codes: &[u8]) {
206 self.0.extend_from_slice(codes);
207 }
208 /// Writes a code to the internal buffer
209 ///
210 /// Returns self to allow for chaining
211 #[inline]
212 pub fn chain_code(&mut self, code: u8) -> &mut Self {
213 self.0.push(code);
214 self
215 }
216 /// Writes codes to the internal buffer
217 ///
218 /// Returns self to allow for chaining
219 #[inline]
220 pub fn chain_codes(&mut self, codes: &[u8]) -> &mut Self {
221 self.0.extend_from_slice(codes);
222 self
223 }
224 /// Writes buffered codes to the provided writer
225 ///
226 /// # Errors
227 ///
228 /// Writing failed
229 pub fn write_to<W: CapableWriter>(&mut self, writer: &mut W) -> Result<(), W::Error> {
230 if self.0.is_empty() {
231 Ok(())
232 } else {
233 writer.write("\x1b[")?;
234 self.codes_inner(writer)?;
235 writer.write("m")
236 }
237 }
238 /// Writes buffered codes to the writer
239 ///
240 /// Does not write the escape or end sequences
241 ///
242 /// Performs IO operations with the inputted [`SGRWriter`]
243 ///
244 /// # Errors
245 ///
246 /// Writing failed
247 pub fn write_partial<W: CapableWriter>(&mut self, writer: &mut W) -> Result<(), W::Error> {
248 if !self.0.is_empty() {
249 self.codes_inner(writer)?;
250 }
251 Ok(())
252 }
253 /// Writes the buffered codes into the inputted writer
254 fn codes_inner<W: CapableWriter>(&mut self, writer: &mut W) -> Result<(), W::Error> {
255 writer.write(&self.0[0].to_string())?;
256
257 for code in &self.0[1..] {
258 writer.write(";")?;
259 writer.write(&code.to_string())?;
260 }
261 Ok(())
262 }
263}
264
265/// Helps to make writing easier
266///
267/// Allows to use the same method for both
268/// [`SGRString`] and [`DiscreteSGR`] types
269pub trait EasyWrite {
270 /// Writes a set of codes to the builder
271 fn sgr(&self, builder: &mut SGRBuilder);
272}
273
274impl EasyWrite for SGRString {
275 /// Writes a set of codes to the builder
276 ///
277 /// Uses [`SGRString::place_all`]
278 fn sgr(&self, builder: &mut SGRBuilder) {
279 self.place_all(builder);
280 }
281}
282
283impl<D: DiscreteSGR> EasyWrite for D {
284 /// Writes a set of codes to the builder
285 ///
286 /// Uses [`DiscreteSGR::write`]
287 fn sgr(&self, builder: &mut SGRBuilder) {
288 self.write(builder);
289 }
290}