Skip to main content

oino_ui/extras/
diff.rs

1//! `Diff` node (§4.5.2).
2
3use serde::{Deserialize, Serialize};
4
5use crate::node::{Common, IntoNode, Node};
6
7/// Diff layout.
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum DiffMode {
10    /// Unified (default).
11    #[default]
12    Unified,
13    /// Side by side (desktop ≥ 900 px only).
14    Split,
15}
16
17/// A unified patch, or old/new text pairs (§4.5.2).
18#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
19#[serde(rename_all = "camelCase")]
20pub struct Diff {
21    /// Common node props (`key`, `style`, `block`, `fallback`).
22    #[serde(flatten)]
23    pub common: Common,
24    /// Unified diff patch (either this, or `old` + `new`).
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub patch: Option<String>,
27    /// Old text (with `new`).
28    #[serde(default, skip_serializing_if = "Option::is_none")]
29    pub old: Option<String>,
30    /// New text (with `old`).
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub new: Option<String>,
33    /// File path shown in the header.
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub path: Option<String>,
36    /// Context lines for `old`/`new` (default 3).
37    #[serde(default, skip_serializing_if = "Option::is_none")]
38    pub context: Option<u16>,
39    /// Layout mode.
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub mode: Option<DiffMode>,
42}
43
44impl Diff {
45    /// Diff from a unified patch.
46    #[must_use]
47    pub fn patch(patch: impl Into<String>) -> Self {
48        Self {
49            common: Common::new(),
50            patch: Some(patch.into()),
51            old: None,
52            new: None,
53            path: None,
54            context: None,
55            mode: None,
56        }
57    }
58
59    /// Diff from old / new text.
60    #[must_use]
61    pub fn old_new(old: impl Into<String>, new: impl Into<String>) -> Self {
62        Self {
63            common: Common::new(),
64            patch: None,
65            old: Some(old.into()),
66            new: Some(new.into()),
67            path: None,
68            context: None,
69            mode: None,
70        }
71    }
72
73    /// Sets the file path.
74    #[must_use]
75    pub fn path(mut self, path: impl Into<String>) -> Self {
76        self.path = Some(path.into());
77        self
78    }
79
80    /// Sets the context-line count.
81    #[must_use]
82    pub fn context(mut self, context: u16) -> Self {
83        self.context = Some(context);
84        self
85    }
86
87    /// Sets the layout mode.
88    #[must_use]
89    pub fn mode(mut self, mode: DiffMode) -> Self {
90        self.mode = Some(mode);
91        self
92    }
93}
94
95impl IntoNode for Diff {}
96impl From<Diff> for Node {
97    fn from(d: Diff) -> Self {
98        Node::Diff(d)
99    }
100}