ratatui_toolkit/widgets/code_diff/widget/
mod.rs

1//! Code diff widget for displaying side-by-side diffs.
2//!
3//! The main widget that renders diff hunks in a side-by-side or unified view,
4//! similar to VS Code's diff viewer. Optionally includes an integrated file
5//! tree sidebar for multi-file diffs.
6//!
7//! # Structure
8//!
9//! - [`CodeDiff`] - The main diff widget struct
10//! - [`constructors`] - Constructor functions (`new`, `from_unified_diff`, `from_multi_file_diff`)
11//! - [`methods`] - Instance methods for configuration and data access
12//! - [`traits`] - Trait implementations (`Widget`, `Default`)
13//!
14//! # Example
15//!
16//! ```rust
17//! use ratatui_toolkit::code_diff::CodeDiff;
18//!
19//! let diff_text = r#"
20//! --- a/file.txt
21//! +++ b/file.txt
22//! @@ -1,4 +1,5 @@
23//!  context line
24//! -removed line
25//! +added line
26//!  more context
27//! "#;
28//!
29//! let widget = CodeDiff::from_unified_diff(diff_text);
30//! ```
31//!
32//! # Multi-file diff with sidebar
33//!
34//! ```rust
35//! use ratatui_toolkit::code_diff::{CodeDiff, DiffConfig};
36//! use ratatui_toolkit::widgets::code_diff::diff_file_tree::FileStatus;
37//!
38//! let diff = CodeDiff::new()
39//!     .with_config(DiffConfig::new().sidebar_enabled(true))
40//!     .with_file("src/lib.rs", FileStatus::Modified, "--- a/src/lib.rs\n+++ b/src/lib.rs\n...")
41//!     .with_file("src/new.rs", FileStatus::Added, "--- /dev/null\n+++ b/src/new.rs\n...");
42//! ```
43
44pub mod constructors;
45pub mod methods;
46pub mod traits;
47
48use std::collections::HashMap;
49
50use crate::primitives::resizable_split::ResizableSplit;
51use crate::services::theme::AppTheme;
52use crate::widgets::code_diff::diff_config::DiffConfig;
53use crate::widgets::code_diff::diff_file_tree::DiffFileTree;
54use crate::widgets::code_diff::diff_hunk::DiffHunk;
55
56/// A widget for displaying code diffs in a terminal UI.
57///
58/// `CodeDiff` renders diff hunks in a side-by-side format (like VS Code) or
59/// unified format, with support for syntax highlighting, line numbers, and
60/// visual markers for added/removed lines.
61///
62/// # Layout
63///
64/// In side-by-side mode:
65/// - Left panel shows the old/original version
66/// - Right panel shows the new/modified version
67/// - Lines are aligned horizontally for easy comparison
68/// - Empty spaces fill gaps where lines were added/removed
69///
70/// When sidebar is enabled:
71/// - Left panel shows file tree with status markers
72/// - Right panel shows the diff for the selected file
73/// - `[` key toggles sidebar visibility
74/// - `h/l` keys switch focus between sidebar and diff
75///
76/// # Visual Elements
77///
78/// - Green background for added lines (+)
79/// - Red background for removed lines (-)
80/// - Gray header bars for hunk information
81/// - Line numbers on each side
82///
83/// # Fields
84///
85/// * `file_path` - Optional path to the file being diffed (for single-file mode)
86/// * `hunks` - Collection of diff hunks to display (for single-file mode)
87/// * `config` - Display configuration (colors, style, sidebar options)
88/// * `scroll_offset` - Current vertical scroll position
89/// * `file_tree` - Internal file tree widget for sidebar
90/// * `file_diffs` - Map of file paths to their diff hunks (for multi-file mode)
91/// * `show_sidebar` - Whether sidebar is currently visible
92/// * `sidebar_split` - Resizable split for sidebar/diff area division with mouse drag support
93/// * `sidebar_focused` - Whether sidebar has focus (vs diff view)
94#[derive(Debug, Clone)]
95pub struct CodeDiff {
96    /// Optional path to the file being diffed (single-file mode).
97    pub file_path: Option<String>,
98
99    /// The diff hunks to display (single-file mode).
100    pub hunks: Vec<DiffHunk>,
101
102    /// Display configuration.
103    pub config: DiffConfig,
104
105    /// Current vertical scroll offset.
106    pub scroll_offset: usize,
107
108    /// Internal file tree widget for sidebar.
109    pub file_tree: DiffFileTree,
110
111    /// Map of file paths to their diff hunks (multi-file mode).
112    pub file_diffs: HashMap<String, Vec<DiffHunk>>,
113
114    /// Whether the sidebar is currently visible.
115    pub show_sidebar: bool,
116
117    /// Resizable split for sidebar/diff area division with mouse drag support.
118    pub sidebar_split: ResizableSplit,
119
120    /// Whether the sidebar has focus (vs diff view).
121    pub sidebar_focused: bool,
122
123    /// Application theme for styling.
124    pub theme: AppTheme,
125}