mirror of
https://github.com/extrawurst/gitui.git
synced 2024-12-28 19:44:14 +03:00
visualize commit-msg hook when failed
This commit is contained in:
parent
19b540c123
commit
520456d0cd
@ -56,7 +56,6 @@ GITUI_LOGGING=true gitui
|
||||
|
||||
# todo for 0.2 (first release)
|
||||
|
||||
* [ ] visualize commit-msg hook result
|
||||
* [ ] publish as homebrew-tap
|
||||
|
||||
# inspiration
|
||||
|
19
src/app.rs
19
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<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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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
90
src/components/msg.rs
Normal 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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -8,6 +8,8 @@ pub enum InternalEvent {
|
||||
ResetFile(String),
|
||||
///
|
||||
AddHunk(u64),
|
||||
///
|
||||
ShowMsg(String),
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -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)",
|
||||
|
Loading…
Reference in New Issue
Block a user