Skip to content

Commit d418bcc

Browse files
committed
Update version to 0.4.1
修改: Cargo.toml 修改: UpdateLog.md 修改: src/lib.rs
1 parent da3c584 commit d418bcc

File tree

3 files changed

+213
-48
lines changed

3 files changed

+213
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "term_lattice"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
edition = "2021"
55

66
license = "MIT"

UpdateLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ Revised the visibility of some fields again and added some methods
1515
Added some useful methods, such as `get_colors_arrow` and `Into<Vec<Color>>`, to compensate for visibility changes in `self.colors`.
1616
Can be easily created from `Iterator` (such as the colors field of a buffer of the same size))
1717
Manually expand `EnumVariantEq` to reduce dependencies
18+
19+
# v0.4.1
20+
Fixed a bug where the output color was changed during optimization of the serialization optimizer, and the serialization optimizer has been refactored

src/lib.rs

Lines changed: 209 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ impl ANSICursorControl {
206206
pub fn sub(&mut self) {
207207
self.subn(1)
208208
}
209-
#[allow(unused)]
210209
pub fn subn(&mut self, num: u16) {
211210
debug_assert!(self.len >= num);
212211
self.len -= num
@@ -282,29 +281,121 @@ impl<T> From<T> for ANSIColors
282281
}
283282
impl Display for ANSIColors {
284283
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285-
fn func(a: u8, b: u8) -> bool {
286-
const EMPTY: (u8, u8) = (39, 49);
287-
(a, b) == EMPTY || (b, a) == EMPTY
288-
}
289284
let len = self.colors.len();
290-
let res = if len != 0 {
291-
let x = if self.colors[len - 1] == 0
292-
|| (len >= 2 && func(
293-
self.colors[len - 1], self.colors[len - 2])) {
294-
"0".to_string()
285+
write!(f, "{}", if len == 0 { String::new() } else {
286+
let mut iter = self.colors.iter();
287+
let [mut bnone, mut fnone] = [false; 2];
288+
let [mut bgs, mut fgs] = [[0u8; 5]; 2];
289+
let [mut bgc, mut fgc] = [0usize; 2];
290+
macro_rules! err {
291+
() => {
292+
panic!(
293+
"color format error: {:?}", self.colors)
294+
};
295+
( $( $x:expr ),* ) => {
296+
panic!(
297+
"color format error: {:?} ({})",
298+
self.colors, format!( $( $x ),* ))
299+
};
300+
}
301+
macro_rules! next {
302+
() => {
303+
iter.next()
304+
.unwrap_or_else(
305+
|| err!("next to end"))
306+
};
307+
}
308+
// 将每种颜色情况分析 如果全部重置则重置为0
309+
loop {
310+
if let Some(x) = iter.next() {
311+
match *x {
312+
0 => [bnone, fnone] = [true; 2],
313+
39 => {
314+
fgc = 0;
315+
fnone = true;
316+
},
317+
49 => {
318+
bgc = 0;
319+
bnone = true;
320+
},
321+
38 => {
322+
fnone = false;
323+
match *next!()
324+
{
325+
y @ 2 => {
326+
fgs[0] = *x;
327+
fgs[1] = y;
328+
for i in 2..5 {
329+
fgs[i] = *next!();
330+
}
331+
fgc = 5;
332+
},
333+
y @ 5 => {
334+
fgs[0] = *x;
335+
fgs[1] = y;
336+
fgs[2] = *next!();
337+
fgc = 3;
338+
},
339+
_ => err!(),
340+
}
341+
},
342+
48 => {
343+
bnone = false;
344+
match *next!()
345+
{
346+
y @ 2 => {
347+
bgs[0] = *x;
348+
bgs[1] = y;
349+
for i in 2..5 {
350+
bgs[i] = *next!();
351+
}
352+
bgc = 5;
353+
},
354+
y @ 5 => {
355+
bgs[0] = *x;
356+
bgs[1] = y;
357+
bgs[2] = *next!();
358+
bgc = 3;
359+
},
360+
_ => err!(),
361+
}
362+
},
363+
n @ (30..=37 | 90..=97) => {
364+
fnone = false;
365+
fgs[0] = n;
366+
fgc = 1;
367+
},
368+
n @ (40..=47 | 100..=107) => {
369+
bnone = false;
370+
bgs[0] = n;
371+
bgc = 1;
372+
},
373+
e => err!("e:{}", e),
374+
}
375+
} else {
376+
break;
377+
}
378+
}
379+
macro_rules! join {
380+
( $x:expr ) => {
381+
($x).into_iter().map(|x| format!("{}", x)).collect::<Vec<_>>().join(";")
382+
};
383+
}
384+
if bnone && fnone {
385+
format!("{}[0m", ESC)
386+
} else if bgc == 0 && fgc == 0 {
387+
format!("")
295388
} else {
296-
self.colors.iter()
297-
.map(|x| x.to_string())
298-
.collect::<Vec<String>>().join(";")
299-
};
300-
format!("{ESC}[{}m", x)
301-
} else { /* empty */ "".to_string() };
302-
write!(f, "{res}")
389+
format!("{}[{}m", ESC,
390+
join!(bgs[0..bgc].into_iter()
391+
.chain(fgs[0..fgc].into_iter())))
392+
}
393+
})
303394
}
304395
}
305396
#[cfg(test)]
306397
mod ansi_colors_tests {
307-
use super::{ANSIColors,ESC};
398+
use super::{ANSIColors,ESC,Color};
308399
#[test]
309400
fn new() {
310401
assert_eq!(ANSIColors::new(), ANSIColors { colors: Vec::new() });
@@ -323,8 +414,8 @@ mod ansi_colors_tests {
323414
#[test]
324415
fn fmt() {
325416
let mut a = ANSIColors::new();
326-
a.add([1, 2, 4]);
327-
assert_eq!(format!("{a}"), format!("{ESC}[1;2;4m"));
417+
a.add([31, 42, 36]);
418+
assert_eq!(format!("{a}"), format!("{ESC}[42;36m"));
328419
assert_eq!(format!("{}", ANSIColors::new()), String::new());
329420

330421
let mut a = ANSIColors::new();
@@ -334,8 +425,25 @@ mod ansi_colors_tests {
334425
a.add([39, 49]);
335426
assert_eq!(format!("{a}"), format!("{ESC}[0m"));
336427
let mut a = ANSIColors::new();
337-
a.add([8, 39, 49]);
428+
a.add([32, 39, 49]);
338429
assert_eq!(format!("{a}"), format!("{ESC}[0m"));
430+
let mut a = ANSIColors::new();
431+
a.add(Color::Rgb([0, 1, 2]).to_ansi(false));
432+
assert_eq!(format!("{a}"), format!("{ESC}[38;2;0;1;2m"));
433+
434+
let mut a = ANSIColors::new();
435+
a.add(Color::Rgb([255, 39, 0]).to_ansi(false));
436+
assert_eq!(format!("{a}"), format!("{ESC}[38;2;255;39;0m"));
437+
a.add(Color::Rgb([255, 39, 0]).to_ansi(true));
438+
assert_eq!(format!("{a}"), format!("{ESC}[48;2;255;39;0;38;2;255;39;0m"));
439+
a.add(Color::None.to_ansi(false));
440+
assert_eq!(format!("{a}"), format!("{ESC}[48;2;255;39;0m"));
441+
a.add(Color::None.to_ansi(true));
442+
assert_eq!(format!("{a}"), format!("{ESC}[0m"));
443+
a.add(Color::C256(72).to_ansi(true));
444+
assert_eq!(format!("{a}"), format!("{ESC}[48;5;72m"));
445+
a.add(Color::C256(12).to_ansi(true));
446+
assert_eq!(format!("{a}"), format!("{ESC}[104m"));
339447
}
340448
}
341449

@@ -366,6 +474,10 @@ impl Color {
366474
/// let a = Color::Rgb([8, 18, 28]);
367475
/// assert_eq!(a.to_ansi(false), vec![38, 2, 8, 18, 28]);
368476
/// assert_eq!(a.to_ansi(true), vec![48, 2, 8, 18, 28]);
477+
///
478+
/// let a = Color::Rgb([0; 3]);
479+
/// assert_eq!(a.to_ansi(false), vec![38, 2, 0, 0, 0]);
480+
/// assert_eq!(a.to_ansi(true), vec![48, 2, 0, 0, 0]);
369481
/// ```
370482
pub fn to_ansi(&self, is_background: bool) -> Vec<u8> {
371483
let head = if is_background { 48 } else { 38 };
@@ -414,7 +526,7 @@ impl Color {
414526
Self::Rgb(color) => {
415527
type Num = i32;
416528
macro_rules! sum {
417-
( $a:expr $(, $x:expr)* ) => ( $a $(+ $x)* );
529+
( $a:expr $(, $x:expr )* ) => ( $a $(+ $x )* );
418530
}
419531
macro_rules! fun {
420532
( $self:ident, $other:ident
@@ -708,17 +820,20 @@ impl ScreenBuffer {
708820
/// You can use discontinuous output to avoid changing the color
709821
/// between multiple outputs that can affect the output effect.
710822
pub fn flush(&self, is_continue: bool) -> String {
711-
let width: SizeType = self.size[0];
712-
let line_size: usize = width as usize * (
713-
UNIT_COLOR_CHARS * 2 + self.cfg.half.len_utf8()) + 9;
714-
let line_count = self.size[1];
715-
let text_line_count = line_count >> 1;
716-
let res_cap = line_size * (text_line_count + 1) as usize;
717-
let mut downs = ANSICursorControl::from('B');
718-
let mut skips = ANSICursorControl::from('C');
823+
let res_cap = self.get_output_string_size();
719824
let mut res: String
720825
= String::with_capacity(res_cap);
721-
let mut backs = ANSICursorControl::from('D');
826+
self.flush_to_string(is_continue, &mut res);
827+
debug_assert_eq!(res.capacity(), res_cap);
828+
res
829+
}
830+
/// Same as `flush` , but output to the incoming string after clearing the incoming string
831+
pub fn flush_to_string(&self, is_continue: bool, res: &mut String) {
832+
let [width, height]: Position = self.size;
833+
let line_size: usize = self.get_output_string_line_size();
834+
let mut downs: ANSICursorControl = ANSICursorControl::from('B');
835+
let mut skips: ANSICursorControl = ANSICursorControl::from('C');
836+
let mut backs: ANSICursorControl = ANSICursorControl::from('D');
722837
let mut line_buf: String = String::with_capacity(line_size);
723838

724839
macro_rules! add_empty_color {
@@ -734,7 +849,9 @@ impl ScreenBuffer {
734849
self.init_prev_color()
735850
}
736851

737-
for line_num in (0..line_count).step_by(2) {
852+
res.clear(); // 清空传入字符串
853+
854+
for line_num in (0..height).step_by(2) {
738855
for column_num in 0..width {
739856
if let Some(x) = self.get_pos_text([column_num, line_num]) {
740857
if ! skips.is_empty() {
@@ -757,13 +874,22 @@ impl ScreenBuffer {
757874
downs.add();
758875
res.push_str(&line_buf);
759876
line_buf.clear();
877+
debug_assert_eq!(line_buf.capacity(), line_size);
760878
}
761879
res.push_str(&downs.to_string());
762880
if ! is_continue {
763881
add_empty_color!();
764882
}
765-
debug_assert_eq!(res.capacity(), res_cap);
766-
res
883+
}
884+
/// Obtain the expected size of the string used for output. (Byte)
885+
pub fn get_output_string_size(&self) -> usize {
886+
let text_lines = (self.size[1] >> 1) as usize;
887+
self.get_output_string_line_size() * text_lines
888+
}
889+
/// Obtain the expected size of a single line output string. (Byte)
890+
pub fn get_output_string_line_size(&self) -> usize {
891+
self.size[0] as usize * (
892+
UNIT_COLOR_CHARS * 2 + self.cfg.half.len_utf8()) + 12
767893
}
768894
/// Get a borrow of the color buffer
769895
/// # Examples
@@ -855,6 +981,16 @@ impl<T> From<(Position, Config, T)> for ScreenBuffer
855981
/// assert_eq!(
856982
/// b, vec![Color::None, Color::C256(39), Color::None, Color::None]);
857983
/// ```
984+
/// ---
985+
/// From Buffer
986+
/// # Examples
987+
/// ```
988+
/// # use term_lattice::{ScreenBuffer,Color,Config};
989+
/// let a = ScreenBuffer::default();
990+
/// let b = ScreenBuffer::from((
991+
/// a.size(), a.cfg, a.get_colors_borrow().clone().into_iter()));
992+
/// assert_eq!(a, b);
993+
/// ```
858994
fn from(value: (Position, Config, T)) -> Self {
859995
let res = Self::new_from_cfg(value.0, value.1);
860996
let mut i = 0;
@@ -918,32 +1054,36 @@ mod screen_buffer_test {
9181054
let mut cfg = Config::new();
9191055
cfg.default_color = Color::C256(15);
9201056
cfg.chromatic_aberration = 1;
921-
let a = ScreenBuffer::new_from_cfg([n; 2], cfg);
1057+
let buf = ScreenBuffer::new_from_cfg([n; 2], cfg);
1058+
//let mut outstr: String = String::with_capacity(buf.get_output_string_size());
9221059
macro_rules! out {
9231060
($mode:expr) => {
924-
print!("\x1b[H\x1b[B {}", a.flush($mode));
1061+
print!("\x1b[H\x1b[B {}", buf.flush($mode));
1062+
//buf.flush_to_string($mode, &mut outstr);
1063+
//print!("\x1b[H\x1b[B {outstr}");
9251064
};
9261065
}
9271066
for i in 0..n >> 1 {
9281067
for j in 0..n {
929-
a.set([j, i], Color::None);
1068+
buf.set([i, j], Color::None);
1069+
buf.set([j, i], Color::None);
9301070
out!(true);
9311071
}
9321072
}
9331073
for i in 0..n {
934-
a.set([i; 2], Color::C256((i & 0xff) as u8));
1074+
buf.set([i; 2], Color::C256((i & 0xff) as u8));
9351075
out!(true);
9361076
}
9371077
for i in 0..n {
938-
a.set([(12 + i) / 8, i], Color::C256((i & 0xff) as u8));
939-
a.set([i, (12 + i) / 8], Color::C256((i & 0xff) as u8));
1078+
buf.set([(12 + i) / 8, i], Color::C256((i & 0xff) as u8));
1079+
buf.set([i, (12 + i) / 8], Color::C256((i & 0xff) as u8));
9401080
out!(true);
9411081
}
9421082
let mut i: f64 = 0.0;
9431083
let mut j = 0;
9441084
let n1 = (n >> 1) as f64;
9451085
while i < 6.28 {
946-
a.set(
1086+
buf.set(
9471087
[((i.cos() * 0.5) * n1 + n1) as SizeType,
9481088
((i.sin() * 0.5) * n1 + n1) as SizeType],
9491089
Color::C256(j));
@@ -953,18 +1093,40 @@ mod screen_buffer_test {
9531093
}
9541094
out!(false);
9551095
println!("\x1b[5A&&&");
956-
a.init_rect_bg([0, n - 10], [3, 2]);
1096+
buf.init_rect_bg([0, n - 10], [3, 2]);
9571097
out!(false);
958-
a.fill_rect([8, 7], [22; 2], Color::C256(84));
1098+
buf.fill_rect([8, 7], [22; 2], Color::C256(84));
9591099
out!(false);
960-
//for i in (0..=255).step_by(4) {
961-
// a.fill(Color::C256(i));
962-
// out!(false);
963-
//}
1100+
for i in 0..16 {
1101+
buf.fill(Color::C256(i));
1102+
out!(false);
1103+
}
1104+
for i in (16..=255).step_by(4) {
1105+
buf.fill(Color::C256(i));
1106+
out!(false);
1107+
}
9641108
let s = ScreenBuffer::new([0, 0]).flush(true);
9651109
assert_eq!(s, String::from(""));
9661110
}
9671111

1112+
#[test]
1113+
fn example() {
1114+
let n = 100;
1115+
let mut cfg = Config::new();
1116+
let text_lines = n as usize >> 1;
1117+
cfg.default_color = Color::C256(15);
1118+
cfg.default_color = Color::Rgb([0; 3]);
1119+
cfg.chromatic_aberration = 1;
1120+
let a = ScreenBuffer::new_from_cfg([n; 2], cfg);
1121+
1122+
print!("\x1b[s{}", "\n".repeat(text_lines + 1));
1123+
1124+
for i in 0..n {
1125+
a.set([i; 2], Color::C256((i & 0xff) as u8));
1126+
println!("\x1b[u{}", a.flush(false));
1127+
}
1128+
}
1129+
9681130
#[test]
9691131
fn incremental_flush() {
9701132
let mut a = ScreenBuffer::new([80; 2]);

0 commit comments

Comments
 (0)