diff --git a/src/app.rs b/src/app.rs index e376d369..a505963a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,12 +2,10 @@ use crate::{ components::{ CommandInfo, CommitComponent, Component, IndexComponent, }, - git_status::StatusLists, git_utils::{self, Diff, DiffLine, DiffLineType}, - tui_utils, }; use crossterm::event::{Event, KeyCode, MouseEvent}; -use git2::IndexAddOption; +use git2::{IndexAddOption, StatusShow}; use itertools::Itertools; use std::{borrow::Cow, path::Path}; use tui::{ @@ -18,18 +16,35 @@ use tui::{ Frame, }; -#[derive(Default)] pub struct App { - status: StatusLists, diff: Diff, offset: u16, do_quit: bool, commit: CommitComponent, index: IndexComponent, - // index_wt: IndexComponent, + index_wd: IndexComponent, } impl App { + /// + pub fn new() -> Self { + Self { + diff: Diff::default(), + offset: 0, + do_quit: false, + commit: CommitComponent::default(), + index_wd: IndexComponent::new( + "Status [s]", + StatusShow::Workdir, + true, + ), + index: IndexComponent::new( + "Index [i]", + StatusShow::Index, + false, + ), + } + } /// pub fn is_quit(&self) -> bool { self.do_quit @@ -37,21 +52,19 @@ impl App { } impl App { - /// - fn fetch_status(&mut self) { - let new_status = StatusLists::new(); - - if self.status != new_status { - self.status = new_status; - } - } - /// fn update_diff(&mut self) { - let new_diff = match self.index.selection() { - Some(i) => { - git_utils::get_diff(Path::new(i.path.as_str())) - } + let (idx, is_stage) = if self.index.focused() { + (&self.index, true) + } else { + (&self.index_wd, false) + }; + + let new_diff = match idx.selection() { + Some(i) => git_utils::get_diff( + Path::new(i.path.as_str()), + is_stage, + ), None => Diff::default(), }; @@ -105,16 +118,8 @@ impl App { ) .split(chunks[0]); - self.index.draw(f, left_chunks[0]); - - tui_utils::draw_list( - f, - left_chunks[1], - "Index [i]".to_string(), - self.status.index_items_pathlist().as_slice(), - None, - false, - ); + self.index_wd.draw(f, left_chunks[0]); + self.index.draw(f, left_chunks[1]); let txt = self .diff @@ -159,6 +164,7 @@ impl App { let mut cmds = self.commit.commands(); cmds.extend(self.index.commands()); + cmds.extend(self.index_wd.commands()); cmds.extend(self.commands()); self.draw_commands(f, chunks_main[2], cmds); @@ -186,6 +192,9 @@ impl App { if self.index.event(ev) { return; } + if self.index_wd.event(ev) { + return; + } if !self.commit.is_visible() { if ev == Event::Key(KeyCode::Esc.into()) @@ -194,6 +203,14 @@ impl App { self.do_quit = true; } + if ev == Event::Key(KeyCode::Char('s').into()) { + self.index_wd.focus(true); + self.index.focus(false); + } else if ev == Event::Key(KeyCode::Char('i').into()) { + self.index.focus(true); + self.index_wd.focus(false); + } + if ev == Event::Key(KeyCode::PageDown.into()) { self.scroll(true); } @@ -251,35 +268,38 @@ impl App { /// pub fn update(&mut self) { - self.fetch_status(); self.index.update(); + self.index_wd.update(); self.update_diff(); } fn index_add(&mut self) { - if let Some(i) = self.index.selection() { - let repo = git_utils::repo(); + if self.index_wd.focused() { + if let Some(i) = self.index_wd.selection() { + let repo = git_utils::repo(); - let mut index = repo.index().unwrap(); + let mut index = repo.index().unwrap(); - let path = Path::new(i.path.as_str()); + let path = Path::new(i.path.as_str()); - let cb = &mut |p: &Path, _matched_spec: &[u8]| -> i32 { - if p == path { - 0 - } else { - 1 + let cb = + &mut |p: &Path, _matched_spec: &[u8]| -> i32 { + if p == path { + 0 + } else { + 1 + } + }; + + if let Ok(_) = index.add_all( + path, + IndexAddOption::DISABLE_PATHSPEC_MATCH + | IndexAddOption::CHECK_PATHSPEC, + Some(cb as &mut git2::IndexMatchedPath), + ) { + index.write().unwrap(); + self.update(); } - }; - - if let Ok(_) = index.add_all( - path, - IndexAddOption::DISABLE_PATHSPEC_MATCH - | IndexAddOption::CHECK_PATHSPEC, - Some(cb as &mut git2::IndexMatchedPath), - ) { - index.write().unwrap(); - self.update(); } } } diff --git a/src/components/index.rs b/src/components/index.rs index 931124be..12f95063 100644 --- a/src/components/index.rs +++ b/src/components/index.rs @@ -9,24 +9,30 @@ use git2::StatusShow; use std::cmp; use tui::{backend::Backend, layout::Rect, Frame}; +/// pub struct IndexComponent { + title: String, items: Vec, index_type: StatusShow, selection: Option, -} - -impl Default for IndexComponent { - /// - fn default() -> Self { - Self { - items: Vec::new(), - index_type: StatusShow::Workdir, - selection: None, - } - } + focused: bool, } impl IndexComponent { + /// + pub fn new( + title: &str, + index_type: StatusShow, + focus: bool, + ) -> Self { + Self { + title: title.to_string(), + items: Vec::new(), + index_type, + selection: None, + focused: focus, + } + } /// pub fn update(&mut self) { let new_status = git_status::get_index(self.index_type); @@ -67,45 +73,60 @@ impl Component for IndexComponent { tui_utils::draw_list( f, r, - "Status [s]".to_string(), + self.title.to_string(), self.items .iter() .map(|e| e.path.clone()) .collect::>() .as_slice(), - self.selection, - true, + if self.focused { self.selection } else { None }, + self.focused, ); } fn commands(&self) -> Vec { - vec![ - CommandInfo { - name: "Scroll [↑↓]".to_string(), - enabled: self.items.len() > 0, - }, - CommandInfo { - name: "Stage File [enter]".to_string(), - enabled: self.selection.is_some(), - }, - ] + if self.focused { + return vec![ + CommandInfo { + name: "Scroll [↑↓]".to_string(), + enabled: self.items.len() > 0, + }, + CommandInfo { + name: "Stage File [enter]".to_string(), + enabled: self.selection.is_some(), + }, + ]; + } + + Vec::new() } fn event(&mut self, ev: Event) -> bool { - if let Event::Key(e) = ev { - return match e.code { - KeyCode::Down => { - self.move_selection(1); - true - } - KeyCode::Up => { - self.move_selection(-1); - true - } - _ => false, - }; + if self.focused { + if let Event::Key(e) = ev { + return match e.code { + KeyCode::Down => { + self.move_selection(1); + true + } + KeyCode::Up => { + self.move_selection(-1); + true + } + _ => false, + }; + } } false } + + /// + fn focused(&self) -> bool { + self.focused + } + /// + fn focus(&mut self, focus: bool) { + self.focused = focus + } } diff --git a/src/components/mod.rs b/src/components/mod.rs index 9aa089e2..2619438f 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -21,6 +21,12 @@ pub trait Component { /// fn event(&mut self, ev: Event) -> bool; /// + fn focused(&self) -> bool { + false + } + /// + fn focus(&mut self, _focus: bool) {} + /// fn is_visible(&self) -> bool { true } diff --git a/src/git_status.rs b/src/git_status.rs index f005d4f9..eb848f0f 100644 --- a/src/git_status.rs +++ b/src/git_status.rs @@ -32,29 +32,6 @@ pub struct StatusItem { pub status: Option, } -#[derive(Default, PartialEq)] -pub struct StatusLists { - pub wt_items: Vec, - pub index_items: Vec, -} - -impl StatusLists { - /// - pub fn new() -> Self { - let mut res = Self::default(); - - res.wt_items = get_index(StatusShow::Workdir); - res.index_items = get_index(StatusShow::Index); - - res - } - - /// - pub fn index_items_pathlist(&self) -> Vec { - self.index_items.iter().map(|e| e.path.clone()).collect() - } -} - pub fn get_index(show: StatusShow) -> Vec { let repo = git_utils::repo(); diff --git a/src/git_utils.rs b/src/git_utils.rs index 6dd0ad77..7bf32633 100644 --- a/src/git_utils.rs +++ b/src/git_utils.rs @@ -30,14 +30,28 @@ pub struct DiffLine { pub struct Diff(pub Vec); /// -pub fn get_diff(p: &Path) -> Diff { +pub fn get_diff(p: &Path, stage: bool) -> Diff { let repo = repo(); let mut opt = DiffOptions::new(); opt.pathspec(p); - let diff = - repo.diff_index_to_workdir(None, Some(&mut opt)).unwrap(); + let diff = if !stage { + // diff against stage + repo.diff_index_to_workdir(None, Some(&mut opt)).unwrap() + } else { + // diff against head + let ref_head = repo.head().unwrap(); + let parent = + repo.find_commit(ref_head.target().unwrap()).unwrap(); + let tree = parent.tree().unwrap(); + repo.diff_tree_to_index( + Some(&tree), + Some(&repo.index().unwrap()), + Some(&mut opt), + ) + .unwrap() + }; let mut res = Vec::new(); @@ -93,7 +107,6 @@ pub fn commit(msg: &String) { let reference = repo.head().unwrap(); let mut index = repo.index().unwrap(); let tree_id = index.write_tree().unwrap(); - let tree = repo.find_tree(tree_id).unwrap(); let parent = repo.find_commit(reference.target().unwrap()).unwrap(); diff --git a/src/main.rs b/src/main.rs index f7833433..9e0390c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,7 +31,7 @@ fn main() -> Result<()> { terminal.clear()?; - let mut app = App::default(); + let mut app = App::new(); loop { app.update();