sheets_diff/core/
unified_format.rs1use std::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 FormattedUnifiedDiff {
19 pub content: Vec<UnifiedDiffContent>,
20}
21
22#[derive(Clone, Debug)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct UnifiedDiffContent {
26 pub old_title: String,
27 pub new_title: String,
28 pub lines: Vec<UnifiedDiffLine>,
29}
30
31#[derive(Clone, Debug)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34pub struct UnifiedDiffLine {
35 pub pos: Option<String>,
36 pub old: Option<String>,
37 pub new: Option<String>,
38}
39
40#[derive(Clone, Debug)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43pub struct SplitUnifiedDiff {
44 pub old: Vec<SplitUnifiedDiffContent>,
45 pub new: Vec<SplitUnifiedDiffContent>,
46}
47
48#[derive(Clone, Debug)]
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51pub struct SplitUnifiedDiffContent {
52 pub title: String,
53 pub lines: Vec<SplitUnifiedDiffLine>,
54}
55
56#[derive(Clone, Debug)]
58#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
59pub struct SplitUnifiedDiffLine {
60 pub pos: Option<String>,
61 pub text: Option<String>,
62}
63
64impl UnifiedDiff {
65 pub fn format(&self) -> FormattedUnifiedDiff {
67 let content: Vec<UnifiedDiffContent> = self
68 .content
69 .iter()
70 .map(|x| {
71 let old_title = format!("--- {}", &x.old_title);
72 let new_title = format!("+++ {}", &x.new_title);
73
74 let lines: Vec<UnifiedDiffLine> = x
75 .lines
76 .iter()
77 .map(|x| {
78 let pos = if let Some(pos) = &x.pos {
79 Some(format!("@@ {} @@", pos))
80 } else {
81 None
82 };
83 let old = if let Some(old) = &x.old {
84 Some(format!("- {}", old))
85 } else {
86 None
87 };
88 let new = if let Some(new) = &x.new {
89 Some(format!("+ {}", new))
90 } else {
91 None
92 };
93 UnifiedDiffLine { pos, old, new }
94 })
95 .collect();
96
97 UnifiedDiffContent {
98 old_title,
99 new_title,
100 lines,
101 }
102 })
103 .collect();
104 FormattedUnifiedDiff { content }
105 }
106
107 pub fn split(&self) -> SplitUnifiedDiff {
109 let old: Vec<SplitUnifiedDiffContent> = self
110 .content
111 .iter()
112 .map(|x| {
113 let title = x.old_title.clone();
114 let lines: Vec<SplitUnifiedDiffLine> = x
115 .lines
116 .iter()
117 .map(|x| {
118 let pos = if let Some(pos) = &x.pos {
119 Some(pos.to_owned())
120 } else {
121 None
122 };
123 let text = if let Some(text) = &x.old {
124 Some(text.to_owned())
125 } else {
126 None
127 };
128 SplitUnifiedDiffLine { pos, text }
129 })
130 .collect();
131 SplitUnifiedDiffContent { title, lines }
132 })
133 .collect();
134 let new: Vec<SplitUnifiedDiffContent> = self
135 .content
136 .iter()
137 .map(|x| {
138 let title = x.new_title.clone();
139 let lines: Vec<SplitUnifiedDiffLine> = x
140 .lines
141 .iter()
142 .map(|x| {
143 let pos = if let Some(pos) = &x.pos {
144 Some(pos.to_owned())
145 } else {
146 None
147 };
148 let text = if let Some(text) = &x.new {
149 Some(text.to_owned())
150 } else {
151 None
152 };
153 SplitUnifiedDiffLine { pos, text }
154 })
155 .collect();
156 SplitUnifiedDiffContent { title, lines }
157 })
158 .collect();
159
160 SplitUnifiedDiff { old, new }
161 }
162}
163
164impl fmt::Display for FormattedUnifiedDiff {
165 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 self.content.iter().for_each(|x| {
168 let _ = writeln!(f, "{}", &x.old_title);
169 let _ = writeln!(f, "{}", &x.new_title);
170 x.lines.iter().for_each(|x| {
171 if let Some(pos) = &x.pos {
172 let _ = writeln!(f, "{}", pos);
173 }
174 if let Some(old) = &x.old {
175 let _ = writeln!(f, "{}", old);
176 }
177 if let Some(new) = &x.new {
178 let _ = writeln!(f, "{}", new);
179 }
180 });
181 });
182 Ok(())
183 }
184}
185
186pub fn unified_diff(diff: &Diff) -> UnifiedDiff {
188 let mut ret: Vec<UnifiedDiffContent> = vec![];
189
190 if !diff.sheet_diff.is_empty() {
191 let old_title = format!("{} (sheet names)", diff.old_filepath);
192 let new_title = format!("{} (sheet names)", diff.new_filepath);
193
194 let lines: Vec<UnifiedDiffLine> = diff
195 .sheet_diff
196 .iter()
197 .map(|x| {
198 let old_sheet = if let Some(sheet) = x.old.as_ref() {
199 Some(sheet.to_owned())
200 } else {
201 None
202 };
203 let new_sheet = if let Some(sheet) = x.new.as_ref() {
204 Some(sheet.to_owned())
205 } else {
206 None
207 };
208 UnifiedDiffLine {
209 pos: None,
210 old: old_sheet,
211 new: new_sheet,
212 }
213 })
214 .collect();
215
216 ret.push(UnifiedDiffContent {
217 old_title,
218 new_title,
219 lines,
220 });
221 }
222
223 let cell_diffs_content: Vec<UnifiedDiffContent> = diff
224 .cell_diffs
225 .iter()
226 .map(|x| {
227 let cell_diffs_lines: Vec<UnifiedDiffLine> = x
228 .cells
229 .iter()
230 .map(|x| {
231 let pos = Some(format!("{}({},{}) {}", x.addr, x.row, x.col, x.kind));
232
233 let old = if let Some(sheet) = x.old.as_ref() {
234 Some(sheet.to_owned())
235 } else {
236 None
237 };
238 let new = if let Some(sheet) = x.new.as_ref() {
239 Some(sheet.to_owned())
240 } else {
241 None
242 };
243
244 UnifiedDiffLine { pos, old, new }
245 })
246 .collect();
247
248 UnifiedDiffContent {
249 old_title: format!("{} [{}]", diff.old_filepath, x.sheet),
250 new_title: format!("{} [{}]", diff.new_filepath, x.sheet),
251 lines: cell_diffs_lines,
252 }
253 })
254 .collect();
255
256 ret.extend(cell_diffs_content);
257
258 UnifiedDiff { content: ret }
259}