summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Dilly <dilly.stephan@gmail.com>2020-03-16 23:03:13 +0100
committerStephan Dilly <dilly.stephan@gmail.com>2020-03-16 23:03:13 +0100
commit955ef55d8dc16001799bc1b30b2459d28f215c13 (patch)
tree3e6dd6ce5dfe456cf8ceb32d5ab066fc6ad4e898
parentc5e7b1b8aefb1ca5f66f37b26ee6eb1c9f9c8b3b (diff)
update in a loop
-rw-r--r--.vscode/settings.json5
-rw-r--r--src/app.rs57
-rw-r--r--src/git_status.rs85
-rw-r--r--src/git_utils.rs21
-rw-r--r--src/main.rs8
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
diff --git a/src/app.rs b/src/app.rs
index b8998046..02412463 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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)) {