1use std::{
2 borrow::Cow,
3 convert::TryFrom,
4 mem,
5 ops::{
6 Deref,
7 DerefMut,
8 },
9};
10
11use thiserror::Error;
12use tui::{
13 style::Style,
14 text::{
15 Span,
16 Spans,
17 },
18};
19
20#[derive(Clone, Debug, Default)]
21pub struct Text(Spans<'static>);
22
23#[derive(Clone, Debug)]
24pub struct Line(Text);
25
26#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
27#[error("string contains a newline")]
28pub struct NewlineError;
29
30impl Text {
31 pub fn with_style(style: Style) -> Text {
32 let mut text = Text::new();
33 text.new_span(style);
34 text
35 }
36
37 pub fn new() -> Text {
38 Text::default()
39 }
40
41 pub fn push_str(&mut self, s: impl AsRef<str>) -> Result<(), NewlineError> {
42 no_newlines(&s)?;
43 self.current_span_mut()
44 .content
45 .to_mut()
46 .push_str(s.as_ref());
47 Ok(())
48 }
49
50 pub fn push_string(&mut self, s: String) -> Result<(), NewlineError> {
51 let current = self.current_span_mut();
52 if current.content.len() == 0 {
53 no_newlines(&s)?;
54 current.content = Cow::Owned(s);
55 return Ok(());
56 }
57 self.push_str(s)
58 }
59
60 pub fn current_span_mut(&mut self) -> &mut Span<'static> {
61 if self.spans().len() == 0 {
62 self.new_span(Default::default());
63 }
64 self.spans_mut().last_mut().unwrap()
65 }
66
67 pub fn set_style(&mut self, style: Style) {
68 let current = self.current_span_mut();
69 if current.content.is_empty() {
70 current.style = style;
71 } else {
72 self.new_span(style);
73 }
74 }
75
76 fn spans_mut(&mut self) -> &mut Vec<Span<'static>> {
77 &mut self.0 .0
78 }
79
80 pub fn new_span(&mut self, style: Style) {
81 self.spans_mut().push(Span {
82 content: Cow::Owned(String::new()),
83 style,
84 })
85 }
86
87 pub fn extend(&mut self, other: &mut Text) {
90 let mut style = self.style();
91 self.spans_mut()
92 .extend(other.spans_mut().drain(..).map(|mut span| {
93 span.style = style.patch(span.style);
94 style = span.style;
95 span
96 }));
97 }
98
99 pub fn spans(&self) -> &Vec<Span<'static>> {
100 &self.0 .0
101 }
102
103 pub fn complete(mut self, mut line: Line) -> Line {
104 self.extend(&mut *line);
105 self.into()
106 }
107
108 pub fn swap_complete(&mut self, line: Line) -> Line {
111 let text = mem::replace(self, Text::new());
112 let line = text.complete(line);
113 self.set_style(line.style());
114 line
115 }
116
117 pub fn empty(&self) -> bool {
118 self.spans().len() == 0
119 }
120
121 pub fn style(&self) -> Style {
122 let spans = self.spans();
123 if spans.len() == 0 {
124 Style::default()
125 } else {
126 spans.last().unwrap().style
127 }
128 }
129}
130
131fn no_newlines(s: impl AsRef<str>) -> Result<(), NewlineError> {
132 if s.as_ref()
133 .as_bytes()
134 .iter()
135 .any(|c| matches!(c, b'\r' | b'\n'))
136 {
137 return Err(NewlineError);
138 }
139 Ok(())
140}
141
142impl<'a> TryFrom<&'a str> for Text {
143 type Error = NewlineError;
144
145 fn try_from(other: &'a str) -> Result<Self, Self::Error> {
146 let mut text = Text::new();
147 text.push_str(other)?;
148 Ok(text)
149 }
150}
151impl TryFrom<String> for Text {
152 type Error = NewlineError;
153 fn try_from(other: String) -> Result<Self, Self::Error> {
154 let mut text = Text::new();
155 text.push_string(other)?;
156 Ok(text)
157 }
158}
159
160impl From<Text> for Line {
161 fn from(other: Text) -> Self {
162 Line(other)
163 }
164}
165
166impl Deref for Line {
167 type Target = Text;
168 fn deref(&self) -> &Self::Target {
169 &self.0
170 }
171}
172
173impl DerefMut for Line {
174 fn deref_mut(&mut self) -> &mut Self::Target {
175 &mut self.0
176 }
177}
178
179impl Line {
180 pub fn new() -> Self {
181 Line(Text::new())
182 }
183}