mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
support stash msg
This commit is contained in:
parent
21cbc3b136
commit
1f5706fa0c
10 changed files with 171 additions and 57 deletions
22
src/app.rs
22
src/app.rs
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
99
src/components/stashmsg.rs
Normal file
99
src/components/stashmsg.rs
Normal 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 => {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue