diff options
author | Stephan Dilly <dilly.stephan@gmail.com> | 2020-03-16 23:03:13 +0100 |
---|---|---|
committer | Stephan Dilly <dilly.stephan@gmail.com> | 2020-03-16 23:03:13 +0100 |
commit | 955ef55d8dc16001799bc1b30b2459d28f215c13 (patch) | |
tree | 3e6dd6ce5dfe456cf8ceb32d5ab066fc6ad4e898 | |
parent | c5e7b1b8aefb1ca5f66f37b26ee6eb1c9f9c8b3b (diff) |
update in a loop
-rw-r--r-- | .vscode/settings.json | 5 | ||||
-rw-r--r-- | src/app.rs | 57 | ||||
-rw-r--r-- | src/git_status.rs | 85 | ||||
-rw-r--r-- | src/git_utils.rs | 21 | ||||
-rw-r--r-- | src/main.rs | 8 |
5 files changed, 127 insertions, 49 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..a9c40cf5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.formatOnSave": true, + "workbench.settings.enableNaturalLanguageSearch": false, + "telemetry.enableTelemetry": false, +}
\ No newline at end of file @@ -1,8 +1,8 @@ +use crate::git_status::StatusLists; use crate::git_utils; use crate::git_utils::Diff; use crate::git_utils::DiffLine; use crossterm::event::{Event, KeyCode}; -use git2::{Repository, Status}; use git_utils::DiffLineType; use std::cmp; use std::path::Path; @@ -16,8 +16,7 @@ use tui::{ #[derive(Default)] pub struct App { - status_items: Vec<String>, - index_items: Vec<String>, + status: StatusLists, status_select: Option<usize>, diff: Diff, offset: u16, @@ -32,49 +31,27 @@ impl App { } impl App { - // - pub fn fetch_status(&mut self) { - let repo = match Repository::init("./") { - Ok(repo) => repo, - Err(e) => panic!("failed to init: {}", e), - }; - - if repo.is_bare() { - panic!("bare repo") - } - - let statuses = repo.statuses(None).unwrap(); - - self.status_items = Vec::new(); - self.index_items = Vec::new(); + /// + fn fetch_status(&mut self) { + let new_status = StatusLists::new(); - for e in statuses.iter() { - let status: Status = e.status(); - if status.is_ignored() { - continue; - } + if self.status != new_status { + self.status = new_status; - if git_utils::on_index(&status) { - self.index_items - .push(format!("{} ({:?})", e.path().unwrap().to_string(), status)) + self.status_select = if self.status.wt_items.len() > 0 { + Some(0) } else { - self.status_items.push(e.path().unwrap().to_string()) - } + None + }; } - self.status_select = if self.status_items.len() > 0 { - Some(0) - } else { - None - }; - self.update_diff(); } /// fn update_diff(&mut self) { let new_diff = match self.status_select { - Some(i) => git_utils::get_diff(Path::new(self.status_items[i].as_str())), + Some(i) => git_utils::get_diff(Path::new(self.status.wt_items[i].path.as_str())), None => Diff::default(), }; @@ -100,7 +77,7 @@ impl App { f, left_chunks[0], "Status".to_string(), - self.status_items.as_slice(), + self.status.wt_items_pathlist().as_slice(), self.status_select, ); @@ -108,7 +85,7 @@ impl App { f, left_chunks[1], "Index".to_string(), - self.index_items.as_slice(), + self.status.index_items_pathlist().as_slice(), None, ); @@ -173,8 +150,12 @@ impl App { } } + pub fn update(&mut self) { + self.fetch_status(); + } + fn input(&mut self, delta: i32) { - let items_len = self.status_items.len(); + let items_len = self.status.wt_items.len(); if items_len > 0 { if let Some(i) = self.status_select { let mut i = i as i32; diff --git a/src/git_status.rs b/src/git_status.rs new file mode 100644 index 00000000..4b6fac9e --- /dev/null +++ b/src/git_status.rs @@ -0,0 +1,85 @@ +use crate::git_utils; +use git2::Repository; +use git2::{Status, StatusOptions, StatusShow}; + +#[derive(PartialEq)] +pub enum StatusItemType { + New, + Modified, + Deleted, + Renamed, + Typechange, +} + +impl From<Status> for StatusItemType { + fn from(s: Status) -> Self { + if s.is_index_new() || s.is_wt_new() { + Self::New + } else if s.is_index_deleted() || s.is_wt_deleted() { + Self::Deleted + } else if s.is_index_renamed() || s.is_wt_renamed() { + Self::Renamed + } else if s.is_index_typechange() || s.is_wt_typechange() { + Self::Typechange + } else { + Self::Modified + } + } +} + +#[derive(Default, PartialEq)] +pub struct StatusItem { + pub path: String, + pub status: Option<StatusItemType>, +} + +#[derive(Default, PartialEq)] +pub struct StatusLists { + pub wt_items: Vec<StatusItem>, + pub index_items: Vec<StatusItem>, +} + +impl StatusLists { + /// + pub fn new() -> Self { + let mut res = Self::default(); + + let repo = git_utils::repo(); + + res.wt_items = Self::get(&repo, StatusShow::Workdir); + res.index_items = Self::get(&repo, StatusShow::Index); + + res + } + + fn get(repo: &Repository, show: StatusShow) -> Vec<StatusItem> { + let mut res = Vec::new(); + + let statuses = repo + .statuses(Some(StatusOptions::default().show(show))) + .unwrap(); + + for e in statuses.iter() { + let status: Status = e.status(); + if status.is_ignored() { + continue; + } + + res.push(StatusItem { + path: e.path().unwrap().to_string(), + status: Some(StatusItemType::from(status)), + }); + } + + res + } + + /// + pub fn wt_items_pathlist(&self) -> Vec<String> { + self.wt_items.iter().map(|e| e.path.clone()).collect() + } + /// + pub fn index_items_pathlist(&self) -> Vec<String> { + self.index_items.iter().map(|e| e.path.clone()).collect() + } +} diff --git a/src/git_utils.rs b/src/git_utils.rs index 79b91475..912721de 100644 --- a/src/git_utils.rs +++ b/src/git_utils.rs @@ -1,6 +1,7 @@ -use git2::{DiffFormat, DiffOptions, Repository, Status}; +use git2::{DiffFormat, DiffOptions, Repository}; use std::path::Path; +/// #[derive(Copy, Clone, PartialEq)] pub enum DiffLineType { None, @@ -15,22 +16,20 @@ impl Default for DiffLineType { } } +/// #[derive(Default, PartialEq)] pub struct DiffLine { pub content: String, pub line_type: DiffLineType, } +/// #[derive(Default, PartialEq)] pub struct Diff(pub Vec<DiffLine>); /// pub fn get_diff(p: &Path) -> Diff { - let repo = Repository::init("./").unwrap(); - - if repo.is_bare() { - panic!("bare repo") - } + let repo = repo(); let mut opt = DiffOptions::new(); opt.pathspec(p); @@ -72,6 +71,12 @@ pub fn get_diff(p: &Path) -> Diff { } /// -pub fn on_index(s: &Status) -> bool { - s.is_index_new() || s.is_index_modified() +pub fn repo() -> Repository { + let repo = Repository::init("./").unwrap(); + + if repo.is_bare() { + panic!("bare repo") + } + + repo } diff --git a/src/main.rs b/src/main.rs index 3189b2c8..18f31f3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,16 @@ mod app; -mod poll; +mod git_status; mod git_utils; +mod poll; use app::App; use crossterm::{ terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, Result, }; +use poll::PollResult; use std::{io, time::Duration}; use tui::{backend::CrosstermBackend, Terminal}; -use poll::PollResult; fn main() -> Result<()> { enable_raw_mode()?; @@ -22,9 +23,10 @@ fn main() -> Result<()> { terminal.clear()?; let mut app = App::default(); - app.fetch_status(); loop { + app.update(); + terminal.draw(|mut f| app.draw(&mut f))?; if let PollResult::Event(e) = poll::poll(Duration::from_millis(200)) { |