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

View file

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

View file

@ -6,6 +6,7 @@ mod filetree;
mod help;
mod msg;
mod reset;
mod stashmsg;
mod textinput;
mod utils;
pub use changes::ChangesComponent;
@ -16,6 +17,7 @@ pub use filetree::FileTreeComponent;
pub use help::HelpComponent;
pub use msg::MsgComponent;
pub use reset::ResetComponent;
pub use stashmsg::StashMsgComponent;
pub use utils::filetree::FileTreeItemKind;
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>,
_force_all: bool,
) -> CommandBlocking {
out.push(CommandInfo::new(
commands::CLOSE_POPUP,
true,
self.visible,
));
out.push(
CommandInfo::new(
commands::CLOSE_POPUP,
true,
self.visible,
)
.order(1),
);
visibility_blocking(self)
}

View file

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

View file

@ -161,7 +161,7 @@ pub mod commands {
///
pub static STASHING_SAVE: CommandText = CommandText::new(
"Save [s]",
"creates a new stash",
"opens stash name input popup",
CMD_GROUP_STASHING,
);
///
@ -178,4 +178,10 @@ pub mod commands {
"toggle including untracked files into stash",
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;
pub use revlog::Revlog;
pub use stashing::Stashing;
pub use stashing::{Stashing, StashingOptions};
pub use status::Status;

View file

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

View file

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