mod event_loop;
mod rebase;
pub(crate) mod render;
mod syntax;
pub(crate) mod theme;
mod types;
#[cfg(test)]
mod tests;
use crate::diff::FileChanges;
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{prelude::*, Terminal};
use std::collections::HashMap;
use std::{error::Error, io};
use event_loop::run_ui;
use types::*;
pub fn is_valid_syntax_theme(name: &str) -> bool {
syntax::THEME_SET.themes.contains_key(name)
}
fn restore_terminal() {
let _ = disable_raw_mode();
let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
}
pub fn run_app(
file_changes: FileChanges,
left_label: &str,
right_label: &str,
theme: theme::Theme,
rebase_notification: Option<String>,
) -> Result<(), Box<dyn Error>> {
let original_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
restore_terminal();
original_hook(info);
}));
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let mut file_names: Vec<String> = file_changes.keys().cloned().collect();
file_names.sort();
let mut scroll_positions = HashMap::new();
for name in &file_names {
scroll_positions.insert(name.clone(), 0usize);
}
let dark = theme::Theme::dark();
let light = theme::Theme::light();
let mut theme_cycle = vec![theme.clone()];
if theme != dark {
theme_cycle.push(dark);
}
if theme != light {
theme_cycle.push(light);
}
let app = App {
file_changes: &file_changes,
left_label,
right_label,
current_file_idx: 0,
file_names,
scroll_positions,
focused_pane: Pane::FileList,
view_mode: ViewMode::SideBySide,
app_mode: AppMode::Diff,
rebase_changes: HashMap::new(),
current_change_idx: 0,
show_rebase_modal: rebase_notification.is_some(),
rebase_notification,
status_message: None,
show_help_modal: false,
theme,
theme_cycle,
theme_cycle_idx: 0,
};
let res = run_ui(&mut terminal, app);
restore_terminal();
terminal.show_cursor()?;
match res {
Ok(true) => {
println!("Rebase completed successfully. Please re-run giff to see updated changes.");
}
Err(err) => {
println!("{:?}", err);
}
_ => {}
}
Ok(())
}