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::{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
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>,
|
||||
_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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue