Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ See https://github.com/Piturnah/gex/issues/13.", MessageType::Error);
state.status.fetch(&state.repo, &config.options)?;
}
KeyCode::Char('u') => {
if state.status.cursor
if state.status.cursor >= state.status.file_diffs.len() {
state.status.stash_pop()?;
} else if state.status.cursor
>= state.status.count_untracked + state.status.count_unstaged
{
state.status.unstage()?;
Expand Down
156 changes: 115 additions & 41 deletions src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ use nom::{bytes::complete::take_until, IResult};

use crate::{
config::{Config, Options, CONFIG},
git_process,
debug, git_process,
minibuffer::{MessageType, MiniBuffer},
parse::{self, parse_hunk_new, parse_hunk_old},
render::{self, Renderer, ResetAttributes, ResetColor},
status,
};

pub trait Expand {
Expand Down Expand Up @@ -284,6 +285,7 @@ pub struct Status {
pub count_unstaged: usize,
pub count_staged: usize,
pub cursor: usize,
pub stash_list: Vec<String>, // pub stash_list: Vec<Stash>,
}

impl render::Render for Status {
Expand Down Expand Up @@ -367,6 +369,32 @@ impl render::Render for Status {
writeln!(f, "{ResetAttributes}")?;
}

if !self.stash_list.is_empty() {
writeln!(
f,
"\r\n{}Stash {}{}({}){}",
style::SetForegroundColor(config.colors.heading),
ResetColor,
style::Attribute::Dim,
self.stash_list.len(),
ResetAttributes
)?;

for (i, stash) in self.stash_list.iter().enumerate() {
if let Some(stash_cursor) = self.cursor.checked_sub(self.file_diffs.len()) {
if i == stash_cursor {
let mut stash = stash.to_string();
stash.insert_str(0, &format!("{}", Attribute::Reverse));
write!(&mut stash, "{ResetAttributes}")?;
f.insert_cursor();
writeln!(f, "\r{stash}")?;
continue;
}
}
writeln!(f, "\r{stash}")?;
}
}

Ok(())
}
}
Expand Down Expand Up @@ -556,6 +584,14 @@ impl Status {
file_diff.selected = true;
}

let stash_list_output = git_process(&["stash", "list"])?;

self.stash_list = std::str::from_utf8(&stash_list_output.stdout)
.context("broken stdout from `git stash list`")?
.lines()
.map(|l| l.to_string())
.collect::<Vec<_>>();

Ok(())
}

Expand Down Expand Up @@ -781,63 +817,86 @@ impl Status {

/// Move the cursor up one
pub fn up(&mut self) -> Result<()> {
if self.file_diffs.is_empty() {
return Ok(());
}

let file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor is at invalid position")?;
let count_file_diffs = self.file_diffs.len();

if file.up().is_err() {
match self.cursor.checked_sub(1) {
Some(v) => {
self.cursor = v;
file.selected = false;
let new_file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor at invalid position")?;
new_file.selected = true;
if new_file.expanded() {
new_file.cursor_last();
if let Some(file) = self.file_diffs.get_mut(self.cursor) {
if file.up().is_err() {
match self.cursor.checked_sub(1) {
Some(v) => {
self.cursor = v;
file.selected = false;
let new_file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor at invalid position")?;
new_file.selected = true;
if new_file.expanded() {
new_file.cursor_last();
}
}
None => self.cursor = 0,
}
None => self.cursor = 0,
}
} else if let Some(_) = self.stash_list.get(self.cursor - self.file_diffs.len()) {
if self.cursor - self.file_diffs.len() == 0 {
if count_file_diffs == 0 {
return Ok(());
}

self.cursor -= 1;
let new_file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor at invalid position")?;
new_file.selected = true;
if new_file.expanded() {
new_file.cursor_last();
}
return Ok(());
}

self.cursor -= 1;
}

Ok(())
}

/// Move the cursor down one
pub fn down(&mut self) -> Result<()> {
if self.file_diffs.is_empty() {
return Ok(());
}

let count_file_diffs = self.file_diffs.len();
let file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor is at invalid position")?;
let count_stash_list = self.stash_list.len();

if let Some(file) = self.file_diffs.get_mut(self.cursor) {
if file.down().is_err() {
if self.cursor + 1 >= count_file_diffs {
if count_stash_list != 0 {
// advance to stash list
self.cursor += 1;
file.selected = false;
debug!("IN FILE SECTION: CURSOR COUNT: {:?}", self.cursor)
}
return Ok(());
}

if file.down().is_err() {
if self.cursor + 1 >= count_file_diffs {
self.cursor += 1;
file.selected = false;
let new_file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor at invalid position")?;
new_file.selected = true;
if new_file.expanded() {
new_file.cursor_first();
}
}
} else if let Some(_) = self.stash_list.get(self.cursor - self.file_diffs.len()) {
if self.cursor + 1 >= count_file_diffs + count_stash_list {
debug!("returning ok");
return Ok(());
}

self.cursor += 1;
file.selected = false;
let new_file = self
.file_diffs
.get_mut(self.cursor)
.context("cursor at invalid position")?;
new_file.selected = true;
if new_file.expanded() {
new_file.cursor_first();
}
debug!("CURSOR COUNT: {:?}", self.cursor);
}

Ok(())
Expand Down Expand Up @@ -882,4 +941,19 @@ impl Status {
new_file.selected = true;
Ok(())
}

pub(crate) fn stash_pop(&self) -> Result<()> {
let stash_entry = self
.stash_list
.get(self.cursor - self.file_diffs.len())
.context("cursor at an invalid position")?;

if let Some(start) = stash_entry.find("{") {
if let Some(end) = stash_entry.find("}") {
git_process(&["stash", "pop", &stash_entry[start + 1..end]])?;
}
}

Ok(())
}
}