]>
git.proxmox.com Git - rustc.git/blob - vendor/anstream/src/adapter/wincon.rs
1 /// Incrementally convert to wincon calls for non-contiguous data
2 #[derive(Default, Clone, Debug, PartialEq, Eq)]
3 pub struct WinconBytes
{
4 parser
: anstyle_parse
::Parser
,
5 capture
: WinconCapture
,
10 pub fn new() -> Self {
14 /// Strip the next segment of data
15 pub fn extract_next
<'s
>(&'s
mut self, bytes
: &'s
[u8]) -> WinconBytesIter
<'s
> {
17 self.capture
.printable
.reserve(bytes
.len());
20 parser
: &mut self.parser
,
21 capture
: &mut self.capture
,
26 /// See [`WinconBytes`]
27 #[derive(Debug, PartialEq, Eq)]
28 pub struct WinconBytesIter
<'s
> {
30 parser
: &'s
mut anstyle_parse
::Parser
,
31 capture
: &'s
mut WinconCapture
,
34 impl<'s
> Iterator
for WinconBytesIter
<'s
> {
35 type Item
= (anstyle
::Style
, String
);
38 fn next(&mut self) -> Option
<Self::Item
> {
39 next_bytes(&mut self.bytes
, self.parser
, self.capture
)
46 parser
: &mut anstyle_parse
::Parser
,
47 capture
: &mut WinconCapture
,
48 ) -> Option
<(anstyle
::Style
, String
)> {
50 while capture
.ready
.is_none() {
51 let byte
= if let Some((byte
, remainder
)) = (*bytes
).split_first() {
57 parser
.advance(capture
, byte
);
59 if capture
.printable
.is_empty() {
63 let style
= capture
.ready
.unwrap_or(capture
.style
);
64 Some((style
, std
::mem
::take(&mut capture
.printable
)))
67 #[derive(Default, Clone, Debug, PartialEq, Eq)]
68 struct WinconCapture
{
69 style
: anstyle
::Style
,
71 ready
: Option
<anstyle
::Style
>,
80 impl anstyle_parse
::Perform
for WinconCapture
{
81 /// Draw a character to the screen and update states.
82 fn print(&mut self, c
: char) {
83 self.printable
.push(c
);
86 /// Execute a C0 or C1 control function.
87 fn execute(&mut self, byte
: u8) {
88 if byte
.is_ascii_whitespace() {
89 self.printable
.push(byte
as char);
95 params
: &anstyle_parse
::Params
,
96 _intermediates
: &[u8],
107 let mut style
= self.style
;
108 for param
in params
{
109 let mut state
= State
::Normal
;
112 let mut is_bg
= false;
114 match (state
, *value
) {
115 (State
::Normal
, 0) => {
116 style
= anstyle
::Style
::default();
119 (State
::Normal
, 1) => {
120 style
= style
.bold();
123 (State
::Normal
, 4) => {
124 style
= style
.underline();
127 (State
::Normal
, 30..=37) => {
128 let color
= to_ansi_color(value
- 30).unwrap();
129 style
= style
.fg_color(Some(color
.into()));
132 (State
::Normal
, 38) => {
134 state
= State
::PrepareCustomColor
;
136 (State
::Normal
, 39) => {
137 style
= style
.fg_color(None
);
140 (State
::Normal
, 40..=47) => {
141 let color
= to_ansi_color(value
- 40).unwrap();
142 style
= style
.bg_color(Some(color
.into()));
145 (State
::Normal
, 48) => {
147 state
= State
::PrepareCustomColor
;
149 (State
::Normal
, 49) => {
150 style
= style
.bg_color(None
);
153 (State
::Normal
, 90..=97) => {
154 let color
= to_ansi_color(value
- 90).unwrap().bright(true);
155 style
= style
.fg_color(Some(color
.into()));
158 (State
::Normal
, 100..=107) => {
159 let color
= to_ansi_color(value
- 100).unwrap().bright(true);
160 style
= style
.bg_color(Some(color
.into()));
163 (State
::PrepareCustomColor
, 5) => {
164 state
= State
::Ansi256
;
166 (State
::PrepareCustomColor
, 2) => {
171 (State
::Ansi256
, n
) => {
172 let color
= anstyle
::Ansi256Color(n
as u8);
174 style
= style
.bg_color(Some(color
.into()));
176 style
= style
.fg_color(Some(color
.into()));
180 (State
::Rgb
, b
) => match (r
, g
) {
187 (Some(r
), Some(g
)) => {
188 let color
= anstyle
::RgbColor(r
as u8, g
as u8, b
as u8);
190 style
= style
.bg_color(Some(color
.into()));
192 style
= style
.fg_color(Some(color
.into()));
204 if style
!= self.style
&& !self.printable
.is_empty() {
205 self.ready
= Some(self.style
);
211 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
219 fn to_ansi_color(digit
: u16) -> Option
<anstyle
::AnsiColor
> {
221 0 => Some(anstyle
::AnsiColor
::Black
),
222 1 => Some(anstyle
::AnsiColor
::Red
),
223 2 => Some(anstyle
::AnsiColor
::Green
),
224 3 => Some(anstyle
::AnsiColor
::Yellow
),
225 4 => Some(anstyle
::AnsiColor
::Blue
),
226 5 => Some(anstyle
::AnsiColor
::Magenta
),
227 6 => Some(anstyle
::AnsiColor
::Cyan
),
228 7 => Some(anstyle
::AnsiColor
::White
),
236 use owo_colors
::OwoColorize
as _
;
237 use proptest
::prelude
::*;
240 fn verify(input
: &str, expected
: Vec
<(anstyle
::Style
, &str)>) {
241 let expected
= expected
243 .map(|(style
, value
)| (style
, value
.to_owned()))
244 .collect
::<Vec
<_
>>();
245 let mut state
= WinconBytes
::new();
246 let actual
= state
.extract_next(input
.as_bytes()).collect
::<Vec
<_
>>();
247 assert_eq
!(expected
, actual
);
252 let input
= format
!("{} world!", "Hello".green().on_red());
255 anstyle
::AnsiColor
::Green
.on(anstyle
::AnsiColor
::Red
),
258 (anstyle
::Style
::default(), " world!"),
260 verify(&input
, expected
);
265 let input
= format
!("Hello {}!", "world".green().on_red());
267 (anstyle
::Style
::default(), "Hello "),
269 anstyle
::AnsiColor
::Green
.on(anstyle
::AnsiColor
::Red
),
272 (anstyle
::Style
::default(), "!"),
274 verify(&input
, expected
);
279 let input
= format
!("Hello {}", "world!".green().on_red());
281 (anstyle
::Style
::default(), "Hello "),
283 anstyle
::AnsiColor
::Green
.on(anstyle
::AnsiColor
::Red
),
287 verify(&input
, expected
);
292 #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
293 fn wincon_no_escapes(s
in "\\PC*") {
294 let expected
= if s
.is_empty() {
297 vec
![(anstyle
::Style
::default(), s
.clone())]
299 let mut state
= WinconBytes
::new();
300 let actual
= state
.extract_next(s
.as_bytes()).collect
::<Vec
<_
>>();
301 assert_eq
!(expected
, actual
);