diff --git a/src/app.rs b/src/app.rs index cebacfe5..e64cc2dd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,9 +3,9 @@ use crate::{ cmdbar::CommandBar, components::{ event_pump, CommandBlocking, CommandInfo, CommitComponent, - Component, DrawableComponent, HelpComponent, - InspectCommitComponent, MsgComponent, ResetComponent, - StashMsgComponent, + Component, DrawableComponent, ExternalEditorComponent, + HelpComponent, InspectCommitComponent, MsgComponent, + ResetComponent, StashMsgComponent, }, input::{Input, InputEvent, InputState}, keys, @@ -35,6 +35,7 @@ pub struct App { commit: CommitComponent, stashmsg_popup: StashMsgComponent, inspect_commit_popup: InspectCommitComponent, + external_editor_popup: ExternalEditorComponent, cmdbar: RefCell, tab: usize, revlog: Revlog, @@ -76,6 +77,9 @@ impl App { sender, theme.clone(), ), + external_editor_popup: ExternalEditorComponent::new( + theme.clone(), + ), do_quit: false, cmdbar: RefCell::new(CommandBar::new(theme.clone())), help: HelpComponent::new(theme.clone()), @@ -190,6 +194,7 @@ impl App { self.update_commands(); } } else if let InputEvent::State(polling_state) = ev { + self.external_editor_popup.hide(); if let InputState::Paused = polling_state { if let Err(e) = self.commit.show_editor() { let msg = @@ -274,6 +279,7 @@ impl App { commit, stashmsg_popup, inspect_commit_popup, + external_editor_popup, help, revlog, status_tab, @@ -404,6 +410,8 @@ impl App { } InternalEvent::SuspendPolling => { self.input.set_polling(false); + self.external_editor_popup.show()?; + flags.insert(NeedsUpdate::COMMANDS) } }; @@ -458,6 +466,7 @@ impl App { || self.msg.is_visible() || self.stashmsg_popup.is_visible() || self.inspect_commit_popup.is_visible() + || self.external_editor_popup.is_visible() } fn draw_popups( @@ -481,6 +490,7 @@ impl App { self.help.draw(f, size)?; self.msg.draw(f, size)?; self.inspect_commit_popup.draw(f, size)?; + self.external_editor_popup.draw(f, size)?; Ok(()) } diff --git a/src/components/commit.rs b/src/components/commit.rs index 6bb2f93d..7430a2ec 100644 --- a/src/components/commit.rs +++ b/src/components/commit.rs @@ -97,6 +97,7 @@ impl Component for CommitComponent { self.queue .borrow_mut() .push_back(InternalEvent::SuspendPolling); + self.hide(); } _ => (), @@ -204,6 +205,7 @@ impl CommitComponent { let message = message.trim().to_string(); self.input.set_text(message); + self.input.show()?; Ok(()) } diff --git a/src/components/externaleditor.rs b/src/components/externaleditor.rs new file mode 100644 index 00000000..dd33057f --- /dev/null +++ b/src/components/externaleditor.rs @@ -0,0 +1,98 @@ +use crate::{ + components::{ + visibility_blocking, CommandBlocking, CommandInfo, Component, + DrawableComponent, + }, + strings, + ui::{self, style::SharedTheme}, +}; +use anyhow::Result; +use crossterm::event::Event; +use tui::{ + backend::Backend, + layout::Rect, + widgets::{Block, BorderType, Borders, Clear, Paragraph, Text}, + Frame, +}; + +/// +pub struct ExternalEditorComponent { + visible: bool, + theme: SharedTheme, +} + +impl ExternalEditorComponent { + /// + pub fn new(theme: SharedTheme) -> Self { + Self { + visible: false, + theme, + } + } +} + +impl DrawableComponent for ExternalEditorComponent { + fn draw( + &self, + f: &mut Frame, + _rect: Rect, + ) -> Result<()> { + if self.visible { + let txt = + vec![Text::Raw(strings::MSG_OPENING_EDITOR.into())]; + + let area = ui::centered_rect_absolute(25, 3, f.size()); + f.render_widget(Clear, area); + f.render_widget( + Paragraph::new(txt.iter()) + .block( + Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Thick) + .title_style(self.theme.title(true)) + .border_style(self.theme.block(true)), + ) + .style(self.theme.text_danger()), + area, + ); + } + + Ok(()) + } +} + +impl Component for ExternalEditorComponent { + fn commands( + &self, + out: &mut Vec, + _force_all: bool, + ) -> CommandBlocking { + if self.visible { + out.clear(); + } + + visibility_blocking(self) + } + + fn event(&mut self, _ev: Event) -> Result { + if self.visible { + return Ok(true); + } + + Ok(false) + } + + fn is_visible(&self) -> bool { + self.visible + } + + fn hide(&mut self) { + self.visible = false + } + + fn show(&mut self) -> Result<()> { + self.visible = true; + + Ok(()) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 3d8a6691..386e5922 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,6 +4,7 @@ mod commit; mod commit_details; mod commitlist; mod diff; +mod externaleditor; mod filetree; mod help; mod inspect_commit; @@ -22,6 +23,7 @@ pub use commit::CommitComponent; pub use commit_details::CommitDetailsComponent; pub use commitlist::CommitList; pub use diff::DiffComponent; +pub use externaleditor::ExternalEditorComponent; pub use filetree::FileTreeComponent; pub use help::HelpComponent; pub use inspect_commit::InspectCommitComponent; diff --git a/src/queue.rs b/src/queue.rs index eea4aa39..c2a79a1e 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -49,6 +49,8 @@ pub enum InternalEvent { /// InspectCommit(CommitId), /// + //TODO: make this a generic OpenExternalEditor to also use it for other places + //(see https://github.com/extrawurst/gitui/issues/166) SuspendPolling, } diff --git a/src/strings.rs b/src/strings.rs index e58b09ae..03f7e7dd 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -10,6 +10,7 @@ pub static TAB_DIVIDER: &str = " | "; pub static CMD_SPLITTER: &str = " "; +pub static MSG_OPENING_EDITOR: &str = "opening editor..."; pub static MSG_TITLE_ERROR: &str = "Error"; pub static COMMIT_TITLE: &str = "Commit"; pub static COMMIT_TITLE_AMEND: &str = "Commit (Amend)";