1use std::fmt;
2
3use cba::{bird::one_or_many, define_transparent_wrapper};
4use ratatui::widgets::Borders;
5
6use regex::Regex;
7
8use serde::{
9 Deserialize, Deserializer, Serialize, Serializer,
10 de::{self, Visitor},
11 ser::SerializeSeq,
12};
13
14#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
15pub enum HorizontalSeparator {
16 #[default]
17 None,
18 Empty,
19 Light,
20 Normal,
21 Heavy,
22 Dashed,
23}
24
25impl HorizontalSeparator {
26 pub fn as_str(self) -> &'static str {
27 match self {
28 Self::None => unreachable!(),
29 Self::Empty => " ",
30 Self::Light => "─", Self::Normal => "─",
32 Self::Heavy => "━", Self::Dashed => "╌", }
35 }
36}
37
38#[derive(Debug, Default, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
39pub enum RowConnectionStyle {
40 #[default]
41 Disjoint,
42 Capped,
43 Full,
44}
45
46define_transparent_wrapper!(
47 #[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
48 #[serde(transparent)]
49 Count: u16 = 1
50);
51use ratatui::widgets::Padding as rPadding;
52
53define_transparent_wrapper!(
54 #[derive(Copy, Clone, Default)]
55 Padding: rPadding
56);
57
58#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
59#[serde(untagged)]
60pub enum ShowCondition {
61 Bool(bool),
62 Free(u16),
63}
64impl Default for ShowCondition {
65 fn default() -> Self {
66 Self::Bool(false)
67 }
68}
69impl From<bool> for ShowCondition {
70 fn from(value: bool) -> Self {
71 ShowCondition::Bool(value)
72 }
73}
74
75impl From<u16> for ShowCondition {
76 fn from(value: u16) -> Self {
77 ShowCondition::Free(value)
78 }
79}
80
81impl Serialize for Padding {
84 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85 where
86 S: Serializer,
87 {
88 use serde::ser::SerializeSeq;
89 let padding = self;
90 if padding.top == padding.bottom
91 && padding.left == padding.right
92 && padding.top == padding.left
93 {
94 serializer.serialize_u16(padding.top)
95 } else if padding.top == padding.bottom && padding.left == padding.right {
96 let mut seq = serializer.serialize_seq(Some(2))?;
97 seq.serialize_element(&padding.left)?;
98 seq.serialize_element(&padding.top)?;
99 seq.end()
100 } else {
101 let mut seq = serializer.serialize_seq(Some(4))?;
102 seq.serialize_element(&padding.top)?;
103 seq.serialize_element(&padding.right)?;
104 seq.serialize_element(&padding.bottom)?;
105 seq.serialize_element(&padding.left)?;
106 seq.end()
107 }
108 }
109}
110
111impl<'de> Deserialize<'de> for Padding {
112 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113 where
114 D: Deserializer<'de>,
115 {
116 use serde::de::Error;
117
118 let repr: Vec<u16> = one_or_many::deserialize(deserializer)?;
119
120 let inner = match repr.len() {
121 1 => {
122 let v = repr[0];
123 rPadding {
124 top: v,
125 right: v,
126 bottom: v,
127 left: v,
128 }
129 }
130 2 => {
131 let lr = repr[0];
132 let tb = repr[1];
133 rPadding {
134 top: tb,
135 right: lr,
136 bottom: tb,
137 left: lr,
138 }
139 }
140 4 => rPadding {
141 top: repr[0],
142 right: repr[1],
143 bottom: repr[2],
144 left: repr[3],
145 },
146 _ => {
147 return Err(D::Error::custom(
148 "a number or an array of 1, 2, or 4 numbers",
149 ));
150 }
151 };
152
153 Ok(inner.into())
154 }
155}
156
157#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
166#[serde(rename_all = "lowercase")]
167pub enum Side {
168 Top,
169 Bottom,
170 Left,
171 #[default]
172 Right,
173}
174
175impl Side {
176 pub fn opposite(&self) -> Borders {
177 match self {
178 Side::Top => Borders::BOTTOM,
179 Side::Bottom => Borders::TOP,
180 Side::Left => Borders::RIGHT,
181 Side::Right => Borders::LEFT,
182 }
183 }
184}
185
186#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
187#[serde(rename_all = "lowercase")]
188pub enum CursorSetting {
189 None,
190 #[default]
191 Default,
192}
193
194#[derive(Default, Debug, Clone, PartialEq, serde::Serialize)]
195pub struct ColumnSetting {
196 pub filter: bool,
197 pub hidden: bool,
198 pub name: String,
199}
200
201#[derive(Default, Debug, Clone)]
202pub enum Split {
203 Delimiter(Regex),
205 Regexes(Vec<Regex>),
207 #[default]
209 None,
210}
211
212impl PartialEq for Split {
213 fn eq(&self, other: &Self) -> bool {
214 match (self, other) {
215 (Split::Delimiter(r1), Split::Delimiter(r2)) => r1.as_str() == r2.as_str(),
216 (Split::Regexes(v1), Split::Regexes(v2)) => {
217 if v1.len() != v2.len() {
218 return false;
219 }
220 v1.iter()
221 .zip(v2.iter())
222 .all(|(r1, r2)| r1.as_str() == r2.as_str())
223 }
224 (Split::None, Split::None) => true,
225 _ => false,
226 }
227 }
228}
229
230impl serde::Serialize for Split {
233 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
234 where
235 S: serde::Serializer,
236 {
237 match self {
238 Split::Delimiter(r) => serializer.serialize_str(r.as_str()),
239 Split::Regexes(rs) => {
240 let mut seq = serializer.serialize_seq(Some(rs.len()))?;
241 for r in rs {
242 seq.serialize_element(r.as_str())?;
243 }
244 seq.end()
245 }
246 Split::None => serializer.serialize_none(),
247 }
248 }
249}
250
251impl<'de> Deserialize<'de> for Split {
252 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
253 where
254 D: Deserializer<'de>,
255 {
256 struct SplitVisitor;
257
258 impl<'de> Visitor<'de> for SplitVisitor {
259 type Value = Split;
260
261 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
262 formatter.write_str("string for delimiter or array of strings for regexes")
263 }
264
265 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
266 where
267 E: de::Error,
268 {
269 Regex::new(value)
271 .map(Split::Delimiter)
272 .map_err(|e| E::custom(format!("Invalid regex: {}", e)))
273 }
274
275 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
276 where
277 A: serde::de::SeqAccess<'de>,
278 {
279 let mut regexes = Vec::new();
280 while let Some(s) = seq.next_element::<String>()? {
281 let r = Regex::new(&s)
282 .map_err(|e| de::Error::custom(format!("Invalid regex: {}", e)))?;
283 regexes.push(r);
284 }
285 Ok(Split::Regexes(regexes))
286 }
287 }
288
289 deserializer.deserialize_any(SplitVisitor)
290 }
291}
292
293impl<'de> Deserialize<'de> for ColumnSetting {
294 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
295 where
296 D: Deserializer<'de>,
297 {
298 #[derive(Deserialize)]
299 #[serde(deny_unknown_fields)]
300 struct ColumnStruct {
301 #[serde(default = "default_true")]
302 filter: bool,
303 #[serde(default)]
304 hidden: bool,
305 name: String,
306 }
307
308 fn default_true() -> bool {
309 true
310 }
311
312 #[derive(Deserialize)]
313 #[serde(untagged)]
314 enum Input {
315 Str(String),
316 Obj(ColumnStruct),
317 }
318
319 match Input::deserialize(deserializer)? {
320 Input::Str(name) => Ok(ColumnSetting {
321 filter: true,
322 hidden: false,
323 name,
324 }),
325 Input::Obj(obj) => Ok(ColumnSetting {
326 filter: obj.filter,
327 hidden: obj.hidden,
328 name: obj.name,
329 }),
330 }
331 }
332}
333
334pub fn deserialize_string_or_char_as_double_width<'de, D, T>(deserializer: D) -> Result<T, D::Error>
336where
337 D: Deserializer<'de>,
338 T: From<String>,
339{
340 struct GenericVisitor<T> {
341 _marker: std::marker::PhantomData<T>,
342 }
343
344 impl<'de, T> Visitor<'de> for GenericVisitor<T>
345 where
346 T: From<String>,
347 {
348 type Value = T;
349
350 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
351 formatter.write_str("a string or single character")
352 }
353
354 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
355 where
356 E: de::Error,
357 {
358 let s = if v.chars().count() == 1 {
359 let mut s = String::with_capacity(2);
360 s.push(v.chars().next().unwrap());
361 s.push(' ');
362 s
363 } else {
364 v.to_string()
365 };
366 Ok(T::from(s))
367 }
368
369 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
370 where
371 E: de::Error,
372 {
373 self.visit_str(&v)
374 }
375 }
376
377 deserializer.deserialize_string(GenericVisitor {
378 _marker: std::marker::PhantomData,
379 })
380}
381
382define_transparent_wrapper!(
384 #[derive(Clone, Eq, Serialize)]
385 StringValue: String
386
387);
388
389impl<'de> Deserialize<'de> for StringValue {
390 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
391 where
392 D: Deserializer<'de>,
393 {
394 struct Visitor;
395
396 impl<'de> de::Visitor<'de> for Visitor {
397 type Value = StringValue;
398
399 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
400 formatter.write_str("a string, number, or bool")
401 }
402
403 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
404 Ok(StringValue(v.to_owned()))
405 }
406
407 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
408 Ok(StringValue(v))
409 }
410
411 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> {
412 Ok(StringValue(v.to_string()))
413 }
414
415 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
416 Ok(StringValue(v.to_string()))
417 }
418
419 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> {
420 Ok(StringValue(v.to_string()))
421 }
422
423 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> {
424 Ok(StringValue(v.to_string()))
425 }
426 }
427
428 deserializer.deserialize_any(Visitor)
429 }
430}