support stash msg

This commit is contained in:
Stephan Dilly 2020-05-22 17:37:48 +02:00
parent 21cbc3b136
commit 1f5706fa0c
10 changed files with 171 additions and 57 deletions

View file

@ -3,7 +3,7 @@ use crate::{
components::{ components::{
event_pump, CommandBlocking, CommandInfo, CommitComponent, event_pump, CommandBlocking, CommandInfo, CommitComponent,
Component, DrawableComponent, HelpComponent, MsgComponent, Component, DrawableComponent, HelpComponent, MsgComponent,
ResetComponent, ResetComponent, StashMsgComponent,
}, },
keys, keys,
queue::{InternalEvent, NeedsUpdate, Queue}, queue::{InternalEvent, NeedsUpdate, Queue},
@ -34,6 +34,7 @@ pub struct App {
msg: MsgComponent, msg: MsgComponent,
reset: ResetComponent, reset: ResetComponent,
commit: CommitComponent, commit: CommitComponent,
stashmsg_popup: StashMsgComponent,
current_commands: Vec<CommandInfo>, current_commands: Vec<CommandInfo>,
tab: usize, tab: usize,
revlog: Revlog, revlog: Revlog,
@ -54,6 +55,10 @@ impl App {
Self { Self {
reset: ResetComponent::new(queue.clone(), &theme), reset: ResetComponent::new(queue.clone(), &theme),
commit: CommitComponent::new(queue.clone(), &theme), commit: CommitComponent::new(queue.clone(), &theme),
stashmsg_popup: StashMsgComponent::new(
queue.clone(),
&theme,
),
do_quit: false, do_quit: false,
current_commands: Vec::new(), current_commands: Vec::new(),
help: HelpComponent::new(&theme), help: HelpComponent::new(&theme),
@ -181,7 +186,16 @@ impl App {
impl App { impl App {
accessors!( accessors!(
self, self,
[msg, reset, commit, help, revlog, status_tab, stashing_tab] [
msg,
reset,
commit,
stashmsg_popup,
help,
revlog,
status_tab,
stashing_tab
]
); );
fn check_quit(&mut self, ev: Event) -> bool { fn check_quit(&mut self, ev: Event) -> bool {
@ -292,6 +306,9 @@ impl App {
} }
InternalEvent::Update(u) => flags.insert(u), InternalEvent::Update(u) => flags.insert(u),
InternalEvent::OpenCommit => self.commit.show(), InternalEvent::OpenCommit => self.commit.show(),
InternalEvent::PopupStashing(_opts) => {
self.stashmsg_popup.show()
}
}; };
flags flags
@ -341,6 +358,7 @@ impl App {
let size = f.size(); let size = f.size();
self.commit.draw(f, size); self.commit.draw(f, size);
self.stashmsg_popup.draw(f, size);
self.reset.draw(f, size); self.reset.draw(f, size);
self.help.draw(f, size); self.help.draw(f, size);
self.msg.draw(f, size); self.msg.draw(f, size);

View file

@ -29,18 +29,15 @@ impl Component for CommitComponent {
fn commands( fn commands(
&self, &self,
out: &mut Vec<CommandInfo>, out: &mut Vec<CommandInfo>,
_force_all: bool, force_all: bool,
) -> CommandBlocking { ) -> CommandBlocking {
self.input.commands(out, force_all);
out.push(CommandInfo::new( out.push(CommandInfo::new(
commands::COMMIT_ENTER, commands::COMMIT_ENTER,
self.can_commit(), self.can_commit(),
self.is_visible(), self.is_visible(),
)); ));
out.push(CommandInfo::new(
commands::CLOSE_POPUP,
true,
self.is_visible(),
));
visibility_blocking(self) visibility_blocking(self)
} }

View file

@ -6,6 +6,7 @@ mod filetree;
mod help; mod help;
mod msg; mod msg;
mod reset; mod reset;
mod stashmsg;
mod textinput; mod textinput;
mod utils; mod utils;
pub use changes::ChangesComponent; pub use changes::ChangesComponent;
@ -16,6 +17,7 @@ pub use filetree::FileTreeComponent;
pub use help::HelpComponent; pub use help::HelpComponent;
pub use msg::MsgComponent; pub use msg::MsgComponent;
pub use reset::ResetComponent; pub use reset::ResetComponent;
pub use stashmsg::StashMsgComponent;
pub use utils::filetree::FileTreeItemKind; pub use utils::filetree::FileTreeItemKind;
use crossterm::event::Event; use crossterm::event::Event;

View file

@ -0,0 +1,99 @@
use super::{
textinput::TextInputComponent, visibility_blocking,
CommandBlocking, CommandInfo, Component, DrawableComponent,
};
use crate::{
queue::{InternalEvent, NeedsUpdate, Queue},
strings,
tabs::StashingOptions,
ui::style::Theme,
};
use asyncgit::{sync, CWD};
use crossterm::event::{Event, KeyCode};
use strings::commands;
use tui::{backend::Backend, layout::Rect, Frame};
pub struct StashMsgComponent {
options: StashingOptions,
input: TextInputComponent,
queue: Queue,
}
impl DrawableComponent for StashMsgComponent {
fn draw<B: Backend>(&mut self, f: &mut Frame<B>, rect: Rect) {
self.input.draw(f, rect)
}
}
impl Component for StashMsgComponent {
fn commands(
&self,
out: &mut Vec<CommandInfo>,
force_all: bool,
) -> CommandBlocking {
self.input.commands(out, force_all);
out.push(CommandInfo::new(
commands::STASHING_CONFIRM_MSG,
true,
self.is_visible() || force_all,
));
visibility_blocking(self)
}
fn event(&mut self, ev: Event) -> bool {
if self.is_visible() {
if self.input.event(ev) {
return true;
}
if let Event::Key(e) = ev {
if let KeyCode::Enter = e.code {
if sync::stash_save(
CWD,
if self.input.get_text().is_empty() {
None
} else {
Some(self.input.get_text().as_str())
},
self.options.stash_untracked,
!self.options.stash_indexed,
)
.is_ok()
{
self.queue.borrow_mut().push_back(
InternalEvent::Update(NeedsUpdate::ALL),
);
}
}
// stop key event propagation
return true;
}
}
false
}
fn is_visible(&self) -> bool {
self.input.is_visible()
}
fn hide(&mut self) {
self.input.hide()
}
fn show(&mut self) {
self.input.show()
}
}
impl StashMsgComponent {
///
pub fn new(queue: Queue, theme: &Theme) -> Self {
Self {
options: StashingOptions::default(),
queue,
input: TextInputComponent::new(theme),
}
}
}

View file

@ -75,11 +75,14 @@ impl Component for TextInputComponent {
out: &mut Vec<CommandInfo>, out: &mut Vec<CommandInfo>,
_force_all: bool, _force_all: bool,
) -> CommandBlocking { ) -> CommandBlocking {
out.push(CommandInfo::new( out.push(
commands::CLOSE_POPUP, CommandInfo::new(
true, commands::CLOSE_POPUP,
self.visible, true,
)); self.visible,
)
.order(1),
);
visibility_blocking(self) visibility_blocking(self)
} }

View file

@ -1,5 +1,6 @@
use bitflags::bitflags; use bitflags::bitflags;
use std::{cell::RefCell, collections::VecDeque, rc::Rc}; use std::{cell::RefCell, collections::VecDeque, rc::Rc};
use crate::tabs::StashingOptions;
bitflags! { bitflags! {
/// flags defining what part of the app need to update /// flags defining what part of the app need to update
@ -35,6 +36,8 @@ pub enum InternalEvent {
Update(NeedsUpdate), Update(NeedsUpdate),
/// ///
OpenCommit, OpenCommit,
///
PopupStashing(StashingOptions),
} }
/// ///

View file

@ -161,7 +161,7 @@ pub mod commands {
/// ///
pub static STASHING_SAVE: CommandText = CommandText::new( pub static STASHING_SAVE: CommandText = CommandText::new(
"Save [s]", "Save [s]",
"creates a new stash", "opens stash name input popup",
CMD_GROUP_STASHING, CMD_GROUP_STASHING,
); );
/// ///
@ -178,4 +178,10 @@ pub mod commands {
"toggle including untracked files into stash", "toggle including untracked files into stash",
CMD_GROUP_STASHING, CMD_GROUP_STASHING,
); );
///
pub static STASHING_CONFIRM_MSG: CommandText = CommandText::new(
"Stash [enter]",
"save files to stash",
CMD_GROUP_STASHING,
);
} }

View file

@ -3,5 +3,5 @@ mod stashing;
mod status; mod status;
pub use revlog::Revlog; pub use revlog::Revlog;
pub use stashing::Stashing; pub use stashing::{Stashing, StashingOptions};
pub use status::Status; pub use status::Status;

View file

@ -1,17 +1,18 @@
use crate::{ use crate::{
accessors, accessors,
components::{ components::{
command_pump, event_pump, CommandBlocking, CommandInfo, command_pump, event_pump, visibility_blocking,
Component, DrawableComponent, FileTreeComponent, CommandBlocking, CommandInfo, Component, DrawableComponent,
FileTreeComponent,
}, },
keys, keys,
queue::{InternalEvent, NeedsUpdate, Queue}, queue::{InternalEvent, Queue},
strings, strings,
ui::style::Theme, ui::style::Theme,
}; };
use asyncgit::{ use asyncgit::{
sync::{self, status::StatusType}, sync::status::StatusType, AsyncNotification, AsyncStatus,
AsyncNotification, AsyncStatus, StatusParams, CWD, StatusParams,
}; };
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use crossterm::event::Event; use crossterm::event::Event;
@ -22,15 +23,16 @@ use tui::{
widgets::{Block, Borders, Paragraph, Text}, widgets::{Block, Borders, Paragraph, Text},
}; };
struct Options { #[derive(Default, Clone, Copy)]
stash_untracked: bool, pub struct StashingOptions {
stash_indexed: bool, pub stash_untracked: bool,
pub stash_indexed: bool,
} }
pub struct Stashing { pub struct Stashing {
visible: bool,
options: Options,
index: FileTreeComponent, index: FileTreeComponent,
visible: bool,
options: StashingOptions,
theme: Theme, theme: Theme,
git_status: AsyncStatus, git_status: AsyncStatus,
queue: Queue, queue: Queue,
@ -46,17 +48,17 @@ impl Stashing {
theme: &Theme, theme: &Theme,
) -> Self { ) -> Self {
Self { Self {
visible: false,
options: Options {
stash_indexed: true,
stash_untracked: true,
},
index: FileTreeComponent::new( index: FileTreeComponent::new(
strings::STASHING_FILES_TITLE, strings::STASHING_FILES_TITLE,
true, true,
queue.clone(), queue.clone(),
theme, theme,
), ),
visible: false,
options: StashingOptions {
stash_indexed: true,
stash_untracked: true,
},
theme: *theme, theme: *theme,
git_status: AsyncStatus::new(sender.clone()), git_status: AsyncStatus::new(sender.clone()),
queue: queue.clone(), queue: queue.clone(),
@ -144,8 +146,6 @@ impl DrawableComponent for Stashing {
) )
.split(chunks[1]); .split(chunks[1]);
self.index.draw(f, chunks[0]);
f.render_widget( f.render_widget(
Paragraph::new(self.get_option_text().iter()) Paragraph::new(self.get_option_text().iter())
.block( .block(
@ -156,6 +156,8 @@ impl DrawableComponent for Stashing {
.alignment(Alignment::Left), .alignment(Alignment::Left),
right_chunks[0], right_chunks[0],
); );
self.index.draw(f, chunks[0]);
} }
} }
@ -183,11 +185,7 @@ impl Component for Stashing {
self.visible || force_all, self.visible || force_all,
)); ));
if self.visible { visibility_blocking(self)
CommandBlocking::Blocking
} else {
CommandBlocking::PassingOn
}
} }
fn event(&mut self, ev: crossterm::event::Event) -> bool { fn event(&mut self, ev: crossterm::event::Event) -> bool {
@ -199,20 +197,12 @@ impl Component for Stashing {
if let Event::Key(k) = ev { if let Event::Key(k) = ev {
return match k { return match k {
keys::STASHING_SAVE if !self.index.is_empty() => { keys::STASHING_SAVE if !self.index.is_empty() => {
if sync::stash_save( self.queue.borrow_mut().push_back(
CWD, InternalEvent::PopupStashing(
None, self.options,
self.options.stash_untracked, ),
!self.options.stash_indexed, );
)
.is_ok()
{
self.queue.borrow_mut().push_back(
InternalEvent::Update(
NeedsUpdate::ALL,
),
);
}
true true
} }
keys::STASHING_TOGGLE_INDEX => { keys::STASHING_TOGGLE_INDEX => {

View file

@ -14,7 +14,7 @@ use asyncgit::{
sync::status::StatusType, AsyncDiff, AsyncNotification, sync::status::StatusType, AsyncDiff, AsyncNotification,
AsyncStatus, DiffParams, StatusParams, AsyncStatus, DiffParams, StatusParams,
}; };
use components::command_pump; use components::{command_pump, visibility_blocking};
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use crossterm::event::Event; use crossterm::event::Event;
use strings::commands; use strings::commands;
@ -314,11 +314,7 @@ impl Component for Status {
); );
} }
if self.visible { visibility_blocking(self)
CommandBlocking::Blocking
} else {
CommandBlocking::PassingOn
}
} }
fn event(&mut self, ev: crossterm::event::Event) -> bool { fn event(&mut self, ev: crossterm::event::Event) -> bool {