diff --git a/README.md b/README.md index c5b940d9..7a0be700 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ GITUI_LOGGING=true gitui # todo for 0.2 (first release) -* [ ] visualize commit-msg hook result * [ ] publish as homebrew-tap # inspiration diff --git a/src/app.rs b/src/app.rs index 9576ed21..0b7a876f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,7 +2,7 @@ use crate::{ components::{ ChangesComponent, CommandBlocking, CommandInfo, CommitComponent, Component, DiffComponent, DrawableComponent, - EventUpdate, HelpComponent, ResetComponent, + EventUpdate, HelpComponent, MsgComponent, ResetComponent, }, keys, queue::{InternalEvent, Queue}, @@ -52,6 +52,7 @@ pub struct App { index: ChangesComponent, index_wd: ChangesComponent, diff: DiffComponent, + msg: MsgComponent, git_diff: AsyncDiff, git_status: AsyncStatus, current_commands: Vec, @@ -68,7 +69,7 @@ impl App { diff_target: DiffTarget::WorkingDir, do_quit: false, reset: ResetComponent::new(queue.clone()), - commit: CommitComponent::default(), + commit: CommitComponent::new(queue.clone()), help: HelpComponent::default(), index_wd: ChangesComponent::new( strings::TITLE_STATUS, @@ -83,6 +84,7 @@ impl App { queue.clone(), ), diff: DiffComponent::new(queue.clone()), + msg: MsgComponent::default(), git_diff: AsyncDiff::new(sender.clone()), git_status: AsyncStatus::new(sender), current_commands: Vec::new(), @@ -152,8 +154,9 @@ impl App { ); self.commit.draw(f, f.size()); - self.help.draw(f, f.size()); self.reset.draw(f, f.size()); + self.help.draw(f, f.size()); + self.msg.draw(f, f.size()); } /// @@ -302,6 +305,10 @@ impl App { } } } + InternalEvent::ShowMsg(msg) => { + self.msg.show_msg(msg); + self.update(); + } }; } @@ -317,9 +324,11 @@ impl App { } } + //TODO: use a new popups_list call for this let main_cmds_available = !self.commit.is_visible() && !self.help.is_visible() - && !self.reset.is_visible(); + && !self.reset.is_visible() + && !self.msg.is_visible(); { { @@ -375,6 +384,7 @@ impl App { fn components(&self) -> Vec<&dyn Component> { vec![ + &self.msg, &self.reset, &self.commit, &self.help, @@ -386,6 +396,7 @@ impl App { fn components_mut(&mut self) -> Vec<&mut dyn Component> { vec![ + &mut self.msg, &mut self.reset, &mut self.commit, &mut self.help, diff --git a/src/components/command.rs b/src/components/command.rs index 5f855f20..22be5078 100644 --- a/src/components/command.rs +++ b/src/components/command.rs @@ -7,15 +7,29 @@ pub struct CommandText { pub desc: &'static str, /// pub group: &'static str, + /// + pub hide_help: bool, } impl CommandText { + /// pub const fn new( name: &'static str, desc: &'static str, group: &'static str, ) -> Self { - Self { name, desc, group } + Self { + name, + desc, + group, + hide_help: false, + } + } + /// + pub const fn hide_help(self) -> Self { + let mut tmp = self; + tmp.hide_help = true; + tmp } } diff --git a/src/components/commit.rs b/src/components/commit.rs index 9aa0c30d..d61a23c2 100644 --- a/src/components/commit.rs +++ b/src/components/commit.rs @@ -2,7 +2,11 @@ use super::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventUpdate, }; -use crate::{keys, strings, ui}; +use crate::{ + keys, + queue::{InternalEvent, Queue}, + strings, ui, +}; use asyncgit::{sync, CWD}; use crossterm::event::{Event, KeyCode}; use log::error; @@ -17,11 +21,11 @@ use tui::{ Frame, }; -#[derive(Default)] pub struct CommitComponent { msg: String, visible: bool, stage_empty: bool, + queue: Queue, } impl DrawableComponent for CommitComponent { @@ -122,17 +126,39 @@ impl Component for CommitComponent { } impl CommitComponent { + /// + pub fn new(queue: Queue) -> Self { + Self { + queue, + msg: String::default(), + stage_empty: true, + visible: false, + } + } + fn commit(&mut self) { if let HookResult::NotOk(e) = sync::hooks_commit_msg(CWD, &mut self.msg) { error!("commit-msg hook error: {}", e); + self.queue.borrow_mut().push_back( + InternalEvent::ShowMsg(format!( + "commit-msg hook error:\n{}", + e + )), + ); return; } sync::commit(CWD, &self.msg); if let HookResult::NotOk(e) = sync::hooks_post_commit(CWD) { error!("post-commit hook error: {}", e); + self.queue.borrow_mut().push_back( + InternalEvent::ShowMsg(format!( + "post-commit hook error:\n{}", + e + )), + ); } self.msg.clear(); diff --git a/src/components/help.rs b/src/components/help.rs index af22c4eb..cf81975f 100644 --- a/src/components/help.rs +++ b/src/components/help.rs @@ -126,7 +126,10 @@ impl Component for HelpComponent { impl HelpComponent { /// pub fn set_cmds(&mut self, cmds: Vec) { - self.cmds = cmds; + self.cmds = cmds + .into_iter() + .filter(|e| !e.text.hide_help) + .collect::>(); self.cmds.sort_by_key(|e| e.text); self.cmds.dedup_by_key(|e| e.text); self.cmds.sort_by_key(|e| hash(&e.text.group)); diff --git a/src/components/mod.rs b/src/components/mod.rs index ab1449ee..30a758fd 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -6,12 +6,14 @@ mod command; mod commit; mod diff; mod help; +mod msg; mod reset; pub use changes::ChangesComponent; pub use command::{CommandInfo, CommandText}; pub use commit::CommitComponent; pub use diff::DiffComponent; pub use help::HelpComponent; +pub use msg::MsgComponent; pub use reset::ResetComponent; /// diff --git a/src/components/msg.rs b/src/components/msg.rs new file mode 100644 index 00000000..eeb41b24 --- /dev/null +++ b/src/components/msg.rs @@ -0,0 +1,90 @@ +use super::{ + visibility_blocking, CommandBlocking, CommandInfo, Component, + DrawableComponent, EventUpdate, +}; +use crate::{keys, strings, ui}; +use crossterm::event::Event; +use std::borrow::Cow; +use strings::commands; +use tui::{ + backend::Backend, + layout::{Alignment, Rect}, + widgets::{Block, Borders, Paragraph, Text, Widget}, + Frame, +}; + +#[derive(Default)] +pub struct MsgComponent { + msg: String, + visible: bool, +} + +impl DrawableComponent for MsgComponent { + fn draw(&self, f: &mut Frame, _rect: Rect) { + if self.visible { + let txt = vec![Text::Raw(Cow::from(self.msg.as_str()))]; + + ui::Clear::new( + Paragraph::new(txt.iter()) + .block( + Block::default() + .title(strings::MSG_TITLE) + .borders(Borders::ALL), + ) + .wrap(true) + .alignment(Alignment::Left), + ) + .render(f, ui::centered_rect_absolute(65, 25, f.size())); + } + } +} + +impl Component for MsgComponent { + fn commands( + &self, + out: &mut Vec, + _force_all: bool, + ) -> CommandBlocking { + out.push(CommandInfo::new( + commands::CLOSE_MSG, + true, + self.visible, + )); + + visibility_blocking(self) + } + + fn event(&mut self, ev: Event) -> Option { + if self.visible { + if let Event::Key(e) = ev { + if let keys::CLOSE_MSG = e { + self.hide(); + } + } + + Some(EventUpdate::Commands) + } else { + None + } + } + + fn is_visible(&self) -> bool { + self.visible + } + + fn hide(&mut self) { + self.visible = false + } + + fn show(&mut self) { + self.visible = true + } +} + +impl MsgComponent { + /// + pub fn show_msg(&mut self, msg: &str) { + self.msg = msg.to_string(); + self.show(); + } +} diff --git a/src/keys.rs b/src/keys.rs index ee634fce..0cc009c0 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -16,6 +16,7 @@ pub const STATUS_STAGE_FILE: KeyEvent = no_mod(KeyCode::Enter); pub const EXIT_1: KeyEvent = no_mod(KeyCode::Esc); pub const EXIT_POPUP: KeyEvent = no_mod(KeyCode::Esc); pub const EXIT_2: KeyEvent = no_mod(KeyCode::Char('q')); +pub const CLOSE_MSG: KeyEvent = no_mod(KeyCode::Enter); pub const OPEN_COMMIT: KeyEvent = no_mod(KeyCode::Char('c')); pub const OPEN_HELP: KeyEvent = no_mod(KeyCode::Char('h')); pub const MOVE_UP: KeyEvent = no_mod(KeyCode::Up); diff --git a/src/queue.rs b/src/queue.rs index 62d9d5d3..a3208069 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -8,6 +8,8 @@ pub enum InternalEvent { ResetFile(String), /// AddHunk(u64), + /// + ShowMsg(String), } /// diff --git a/src/strings.rs b/src/strings.rs index 82518e59..a9a925b3 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -7,6 +7,7 @@ pub static TAB_DIVIDER: &str = " | "; pub static CMD_SPLITTER: &str = " "; +pub static MSG_TITLE: &str = "Info"; pub static COMMIT_TITLE: &str = "Commit"; pub static COMMIT_MSG: &str = "type commit message.."; pub static RESET_TITLE: &str = "Reset"; @@ -53,6 +54,13 @@ pub mod commands { CMD_GROUP_GENERAL, ); /// + pub static CLOSE_MSG: CommandText = CommandText::new( + "Close [enter]", + "close msg popup (e.g msg)", + CMD_GROUP_GENERAL, + ) + .hide_help(); + /// pub static COMMIT_OPEN: CommandText = CommandText::new( "Commit [c]", "open commit view (available in non-empty stage)",