tabled/settings/format/
format_content.rs1use crate::{
2 grid::{
3 config::{Entity, Position},
4 records::{ExactRecords, PeekableRecords, Records, RecordsMut},
5 },
6 settings::{CellOption, TableOption},
7};
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
11pub struct FormatContent<F> {
12 f: F,
13 multiline: bool,
14}
15
16impl<F> FormatContent<F> {
17 pub(crate) fn new(f: F) -> Self {
18 Self {
19 f,
20 multiline: false,
21 }
22 }
23}
24
25impl<F> FormatContent<F> {
26 pub fn multiline(mut self) -> Self {
38 self.multiline = true;
39 self
40 }
41}
42
43impl<F, R, D, C> TableOption<R, C, D> for FormatContent<F>
44where
45 F: FnMut(&str) -> String + Clone,
46 R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
47{
48 fn change(self, records: &mut R, cfg: &mut C, _: &mut D) {
49 CellOption::change(self, records, cfg, Entity::Global);
50 }
51}
52
53impl<F, R, C> CellOption<R, C> for FormatContent<F>
54where
55 F: FnMut(&str) -> String + Clone,
56 R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
57{
58 fn change(mut self, records: &mut R, _: &mut C, entity: Entity) {
59 let count_rows = records.count_rows();
60 let count_cols = records.count_columns();
61 let max_pos = Position::new(count_rows, count_cols);
62
63 for pos in entity.iter(count_rows, count_cols) {
64 if !max_pos.has_coverage(pos) {
65 continue;
66 }
67
68 let text = records.get_text(pos);
69
70 let new_text = if self.multiline {
71 multiline(self.f.clone())(text)
72 } else {
73 (self.f)(text)
74 };
75
76 records.set(pos, new_text);
77 }
78 }
79}
80
81fn multiline<F: FnMut(&str) -> String>(mut f: F) -> impl FnMut(&str) -> String {
82 move |s: &str| {
83 let mut v = Vec::new();
84 for line in s.lines() {
85 v.push(f(line));
86 }
87
88 v.join("\n")
89 }
90}