]>
git.proxmox.com Git - rustc.git/blob - vendor/nu-ansi-term/src/display.rs
1 use crate::ansi
::RESET
;
2 use crate::difference
::Difference
;
3 use crate::style
::{Color, Style}
;
4 use crate::write
::AnyWrite
;
9 /// An `AnsiGenericString` includes a generic string type and a `Style` to
10 /// display that string. `AnsiString` and `AnsiByteString` are aliases for
11 /// this type on `str` and `\[u8]`, respectively.
12 #[derive(PartialEq, Debug)]
13 pub struct AnsiGenericString
<'a
, S
: 'a
+ ToOwned
+ ?Sized
>
15 <S
as ToOwned
>::Owned
: fmt
::Debug
,
17 pub(crate) style
: Style
,
18 pub(crate) string
: Cow
<'a
, S
>,
21 /// Cloning an `AnsiGenericString` will clone its underlying string.
26 /// use nu_ansi_term::AnsiString;
28 /// let plain_string = AnsiString::from("a plain string");
29 /// let clone_string = plain_string.clone();
30 /// assert_eq!(clone_string, plain_string);
32 impl<'a
, S
: 'a
+ ToOwned
+ ?Sized
> Clone
for AnsiGenericString
<'a
, S
>
34 <S
as ToOwned
>::Owned
: fmt
::Debug
,
36 fn clone(&self) -> AnsiGenericString
<'a
, S
> {
39 string
: self.string
.clone(),
44 // You might think that the hand-written Clone impl above is the same as the
45 // one that gets generated with #[derive]. But it’s not *quite* the same!
47 // `str` is not Clone, and the derived Clone implementation puts a Clone
48 // constraint on the S type parameter (generated using --pretty=expanded):
50 // ↓_________________↓
51 // impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
52 // for ANSIGenericString<'a, S> where
53 // <S as ToOwned>::Owned: fmt::Debug { ... }
55 // This resulted in compile errors when you tried to derive Clone on a type
58 // #[derive(PartialEq, Debug, Clone, Default)]
59 // pub struct TextCellContents(Vec<AnsiString<'static>>);
60 // ^^^^^^^^^^^^^^^^^^^^^^^^^
61 // error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
63 // The hand-written impl above can ignore that constraint and still compile.
65 /// An ANSI String is a string coupled with the `Style` to display it
68 /// Although not technically a string itself, it can be turned into
69 /// one with the `to_string` method.
74 /// use nu_ansi_term::AnsiString;
75 /// use nu_ansi_term::Color::Red;
77 /// let red_string = Red.paint("a red string");
78 /// println!("{}", red_string);
82 /// use nu_ansi_term::AnsiString;
84 /// let plain_string = AnsiString::from("a plain string");
86 pub type AnsiString
<'a
> = AnsiGenericString
<'a
, str>;
88 /// An `AnsiByteString` represents a formatted series of bytes. Use
89 /// `AnsiByteString` when styling text with an unknown encoding.
90 pub type AnsiByteString
<'a
> = AnsiGenericString
<'a
, [u8]>;
92 impl<'a
, I
, S
: 'a
+ ToOwned
+ ?Sized
> From
<I
> for AnsiGenericString
<'a
, S
>
95 <S
as ToOwned
>::Owned
: fmt
::Debug
,
97 fn from(input
: I
) -> AnsiGenericString
<'a
, S
> {
100 style
: Style
::default(),
105 impl<'a
, S
: 'a
+ ToOwned
+ ?Sized
> AnsiGenericString
<'a
, S
>
107 <S
as ToOwned
>::Owned
: fmt
::Debug
,
109 /// Directly access the style
110 pub fn style_ref(&self) -> &Style
{
114 /// Directly access the style mutably
115 pub fn style_ref_mut(&mut self) -> &mut Style
{
120 /// A set of `AnsiGenericStrings`s collected together, in order to be
121 /// written with a minimum of control characters.
122 #[derive(Debug, PartialEq)]
123 pub struct AnsiGenericStrings
<'a
, S
: 'a
+ ToOwned
+ ?Sized
>(pub &'a
[AnsiGenericString
<'a
, S
>])
125 <S
as ToOwned
>::Owned
: fmt
::Debug
,
128 /// A set of `AnsiString`s collected together, in order to be written with a
129 /// minimum of control characters.
130 pub type AnsiStrings
<'a
> = AnsiGenericStrings
<'a
, str>;
132 /// A function to construct an `AnsiStrings` instance.
133 #[allow(non_snake_case)]
134 pub fn AnsiStrings
<'a
>(arg
: &'a
[AnsiString
<'a
>]) -> AnsiStrings
<'a
> {
135 AnsiGenericStrings(arg
)
138 /// A set of `AnsiByteString`s collected together, in order to be
139 /// written with a minimum of control characters.
140 pub type AnsiByteStrings
<'a
> = AnsiGenericStrings
<'a
, [u8]>;
142 /// A function to construct an `AnsiByteStrings` instance.
143 #[allow(non_snake_case)]
144 pub fn AnsiByteStrings
<'a
>(arg
: &'a
[AnsiByteString
<'a
>]) -> AnsiByteStrings
<'a
> {
145 AnsiGenericStrings(arg
)
148 // ---- paint functions ----
151 /// Paints the given text with this color, returning an ANSI string.
153 pub fn paint
<'a
, I
, S
: 'a
+ ToOwned
+ ?Sized
>(self, input
: I
) -> AnsiGenericString
<'a
, S
>
156 <S
as ToOwned
>::Owned
: fmt
::Debug
,
159 string
: input
.into(),
166 /// Paints the given text with this color, returning an ANSI string.
167 /// This is a short-cut so you don’t have to use `Blue.normal()` just
168 /// to get blue text.
171 /// use nu_ansi_term::Color::Blue;
172 /// println!("{}", Blue.paint("da ba dee"));
175 pub fn paint
<'a
, I
, S
: 'a
+ ToOwned
+ ?Sized
>(self, input
: I
) -> AnsiGenericString
<'a
, S
>
178 <S
as ToOwned
>::Owned
: fmt
::Debug
,
181 string
: input
.into(),
182 style
: self.normal(),
187 // ---- writers for individual ANSI strings ----
189 impl<'a
> fmt
::Display
for AnsiString
<'a
> {
190 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
191 let w
: &mut dyn fmt
::Write
= f
;
196 impl<'a
> AnsiByteString
<'a
> {
197 /// Write an `AnsiByteString` to an `io::Write`. This writes the escape
198 /// sequences for the associated `Style` around the bytes.
199 pub fn write_to
<W
: io
::Write
>(&self, w
: &mut W
) -> io
::Result
<()> {
200 let w
: &mut dyn io
::Write
= w
;
205 impl<'a
, S
: 'a
+ ToOwned
+ ?Sized
> AnsiGenericString
<'a
, S
>
207 <S
as ToOwned
>::Owned
: fmt
::Debug
,
210 fn write_to_any
<W
: AnyWrite
<Wstr
= S
> + ?Sized
>(&self, w
: &mut W
) -> Result
<(), W
::Error
> {
211 write
!(w
, "{}", self.style
.prefix())?
;
212 w
.write_str(self.string
.as_ref())?
;
213 write
!(w
, "{}", self.style
.suffix())
217 // ---- writers for combined ANSI strings ----
219 impl<'a
> fmt
::Display
for AnsiStrings
<'a
> {
220 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
221 let f
: &mut dyn fmt
::Write
= f
;
226 impl<'a
> AnsiByteStrings
<'a
> {
227 /// Write `AnsiByteStrings` to an `io::Write`. This writes the minimal
228 /// escape sequences for the associated `Style`s around each set of
230 pub fn write_to
<W
: io
::Write
>(&self, w
: &mut W
) -> io
::Result
<()> {
231 let w
: &mut dyn io
::Write
= w
;
236 impl<'a
, S
: 'a
+ ToOwned
+ ?Sized
+ PartialEq
> AnsiGenericStrings
<'a
, S
>
238 <S
as ToOwned
>::Owned
: fmt
::Debug
,
241 fn write_to_any
<W
: AnyWrite
<Wstr
= S
> + ?Sized
>(&self, w
: &mut W
) -> Result
<(), W
::Error
> {
242 use self::Difference
::*;
244 let first
= match self.0.first
() {
245 None
=> return Ok(()),
249 write
!(w
, "{}", first
.style
.prefix())?
;
250 w
.write_str(first
.string
.as_ref())?
;
252 for window
in self.0.windows(2) {
253 match Difference
::between(&window
[0].style
, &window
[1].style
) {
254 ExtraStyles(style
) => write
!(w
, "{}", style
.prefix())?
,
255 Reset
=> write
!(w
, "{}{}", RESET
, window
[1].style
.prefix())?
,
256 Empty
=> { /* Do nothing! */ }
259 w
.write_str(&window
[1].string
)?
;
262 // Write the final reset string after all of the AnsiStrings have been
263 // written, *except* if the last one has no styles, because it would
264 // have already been written by this point.
265 if let Some(last
) = self.0.last() {
266 if !last
.style
.is_plain() {
267 write
!(w
, "{}", RESET
)?
;
279 pub use super::super::AnsiStrings
;
280 pub use crate::style
::Color
::*;
281 pub use crate::style
::Style
;
284 fn no_control_codes_for_plain() {
285 let one
= Style
::default().paint("one");
286 let two
= Style
::default().paint("two");
287 let output
= AnsiStrings(&[one
, two
]).to_string();
288 assert_eq
!(output
, "onetwo");