mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
update in a loop
This commit is contained in:
parent
c5e7b1b8ae
commit
955ef55d8d
5 changed files with 127 additions and 49 deletions
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"editor.formatOnSave": true,
|
||||
"workbench.settings.enableNaturalLanguageSearch": false,
|
||||
"telemetry.enableTelemetry": false,
|
||||
}
|
||||
57
src/app.rs
57
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),
|
||||
};
|
||||
///
|
||||
fn fetch_status(&mut self) {
|
||||
let new_status = StatusLists::new();
|
||||
|
||||
if repo.is_bare() {
|
||||
panic!("bare repo")
|
||||
}
|
||||
if self.status != new_status {
|
||||
self.status = new_status;
|
||||
|
||||
let statuses = repo.statuses(None).unwrap();
|
||||
|
||||
self.status_items = Vec::new();
|
||||
self.index_items = Vec::new();
|
||||
|
||||
for e in statuses.iter() {
|
||||
let status: Status = e.status();
|
||||
if status.is_ignored() {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
85
src/git_status.rs
Normal file
85
src/git_status.rs
Normal file
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue