visualize commit-msg hook when failed

This commit is contained in:
Stephan Dilly 2020-04-10 14:02:24 +02:00
parent 19b540c123
commit 520456d0cd
10 changed files with 165 additions and 9 deletions

View File

@ -56,7 +56,6 @@ GITUI_LOGGING=true gitui
# todo for 0.2 (first release)
* [ ] visualize commit-msg hook result
* [ ] publish as homebrew-tap
# inspiration

View File

@ -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<CommandInfo>,
@ -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,

View File

@ -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
}
}

View File

@ -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();

View File

@ -126,7 +126,10 @@ impl Component for HelpComponent {
impl HelpComponent {
///
pub fn set_cmds(&mut self, cmds: Vec<CommandInfo>) {
self.cmds = cmds;
self.cmds = cmds
.into_iter()
.filter(|e| !e.text.hide_help)
.collect::<Vec<_>>();
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));

View File

@ -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;
///

90
src/components/msg.rs Normal file
View File

@ -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<B: Backend>(&self, f: &mut Frame<B>, _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<CommandInfo>,
_force_all: bool,
) -> CommandBlocking {
out.push(CommandInfo::new(
commands::CLOSE_MSG,
true,
self.visible,
));
visibility_blocking(self)
}
fn event(&mut self, ev: Event) -> Option<EventUpdate> {
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();
}
}

View File

@ -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);

View File

@ -8,6 +8,8 @@ pub enum InternalEvent {
ResetFile(String),
///
AddHunk(u64),
///
ShowMsg(String),
}
///

View File

@ -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)",