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}