sheets_diff/core/
unified_format.rs1use core::fmt;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use super::diff::Diff;
7
8#[derive(Clone, Debug)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub struct UnifiedDiff {
12 pub content: Vec<UnifiedDiffContent>,
13}
14
15#[derive(Clone, Debug)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct UnifiedDiffContent {
19 pub old_title: String,
20 pub new_title: String,
21 pub lines: Vec<UnifiedDiffLine>,
22}
23
24#[derive(Clone, Debug)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27pub struct UnifiedDiffLine {
28 pub pos: Option<String>,
29 pub old: Option<String>,
30 pub new: Option<String>,
31}
32
33#[derive(Clone, Debug)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct SplitUnifiedDiff {
37 pub old: Vec<SplitUnifiedDiffContent>,
38 pub new: Vec<SplitUnifiedDiffContent>,
39}
40
41#[derive(Clone, Debug)]
43#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44pub struct SplitUnifiedDiffContent {
45 pub title: String,
46 pub lines: Vec<SplitUnifiedDiffLine>,
47}
48
49#[derive(Clone, Debug)]
51#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
52pub struct SplitUnifiedDiffLine {
53 pub pos: Option<String>,
54 pub text: Option<String>,
55}
56
57impl fmt::Display for UnifiedDiff {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 self.content.iter().for_each(|x| {
61 let _ = writeln!(f, "--- {}", &x.old_title);
62 let _ = writeln!(f, "+++ {}", &x.new_title);
63 x.lines.iter().for_each(|x| {
64 if let Some(pos) = &x.pos {
65 let _ = writeln!(f, "@@ {} @@", pos);
66 }
67 if let Some(old) = &x.old {
68 let _ = writeln!(f, "- {}", old);
69 }
70 if let Some(new) = &x.new {
71 let _ = writeln!(f, "+ {}", new);
72 }
73 });
74 });
75 Ok(())
76 }
77}
78
79impl UnifiedDiff {
80 pub fn split(&self) -> SplitUnifiedDiff {
82 let old: Vec<SplitUnifiedDiffContent> = self
83 .content
84 .iter()
85 .map(|x| {
86 let title = x.old_title.clone();
87 let lines: Vec<SplitUnifiedDiffLine> = x
88 .lines
89 .iter()
90 .map(|x| {
91 let pos = if let Some(pos) = &x.pos {
92 Some(pos.to_owned())
93 } else {
94 None
95 };
96 let text = if let Some(text) = &x.old {
97 Some(text.to_owned())
98 } else {
99 None
100 };
101 SplitUnifiedDiffLine { pos, text }
102 })
103 .collect();
104 SplitUnifiedDiffContent { title, lines }
105 })
106 .collect();
107 let new: Vec<SplitUnifiedDiffContent> = self
108 .content
109 .iter()
110 .map(|x| {
111 let title = x.new_title.clone();
112 let lines: Vec<SplitUnifiedDiffLine> = x
113 .lines
114 .iter()
115 .map(|x| {
116 let pos = if let Some(pos) = &x.pos {
117 Some(pos.to_owned())
118 } else {
119 None
120 };
121 let text = if let Some(text) = &x.new {
122 Some(text.to_owned())
123 } else {
124 None
125 };
126 SplitUnifiedDiffLine { pos, text }
127 })
128 .collect();
129 SplitUnifiedDiffContent { title, lines }
130 })
131 .collect();
132
133 SplitUnifiedDiff { old, new }
134 }
135}
136
137pub fn unified_diff(diff: &Diff) -> UnifiedDiff {
139 let mut ret: Vec<UnifiedDiffContent> = vec![];
140
141 if !diff.sheet_diff.is_empty() {
142 let old_title = format!("{} (sheet names)", diff.old_filepath);
143 let new_title = format!("{} (sheet names)", diff.new_filepath);
144
145 let lines: Vec<UnifiedDiffLine> = diff
146 .sheet_diff
147 .iter()
148 .map(|x| {
149 let old_sheet = if let Some(sheet) = x.old.as_ref() {
150 Some(sheet.to_owned())
151 } else {
152 None
153 };
154 let new_sheet = if let Some(sheet) = x.new.as_ref() {
155 Some(sheet.to_owned())
156 } else {
157 None
158 };
159 UnifiedDiffLine {
160 pos: None,
161 old: old_sheet,
162 new: new_sheet,
163 }
164 })
165 .collect();
166
167 ret.push(UnifiedDiffContent {
168 old_title,
169 new_title,
170 lines,
171 });
172 }
173
174 let cell_diffs_content: Vec<UnifiedDiffContent> = diff
175 .cell_diffs
176 .iter()
177 .map(|x| {
178 let cell_diffs_lines: Vec<UnifiedDiffLine> = x
179 .cells
180 .iter()
181 .map(|x| {
182 let pos = Some(format!("{}({},{}) {}", x.addr, x.row, x.col, x.kind));
183
184 let old = if let Some(sheet) = x.old.as_ref() {
185 Some(sheet.to_owned())
186 } else {
187 None
188 };
189 let new = if let Some(sheet) = x.new.as_ref() {
190 Some(sheet.to_owned())
191 } else {
192 None
193 };
194
195 UnifiedDiffLine { pos, old, new }
196 })
197 .collect();
198
199 UnifiedDiffContent {
200 old_title: format!("{} [{}]", diff.old_filepath, x.sheet),
201 new_title: format!("{} [{}]", diff.new_filepath, x.sheet),
202 lines: cell_diffs_lines,
203 }
204 })
205 .collect();
206
207 ret.extend(cell_diffs_content);
208
209 UnifiedDiff { content: ret }
210}