diff options
author | Tim Oram <dev@mitmaro.ca> | 2019-06-23 13:50:04 -0230 |
---|---|---|
committer | Tim Oram <dev@mitmaro.ca> | 2019-06-23 13:50:04 -0230 |
commit | bd98d8c365cfc714d57762cb8bdf0cbbd45f8e26 (patch) | |
tree | 7052ed1b5c4dd026ccaed984683dc3fe1c82aa3f | |
parent | 669f865a1d28be02f0cef10410492721888208af (diff) |
Move external editor to module
-rw-r--r-- | src/application.rs | 120 | ||||
-rw-r--r-- | src/external_editor/external_editor.rs | 141 | ||||
-rw-r--r-- | src/external_editor/mod.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/process/state.rs | 4 |
5 files changed, 160 insertions, 110 deletions
diff --git a/src/application.rs b/src/application.rs index f012ea3..fa97798 100644 --- a/src/application.rs +++ b/src/application.rs @@ -6,28 +6,19 @@ use crate::confirm_abort::ConfirmAbort; use crate::confirm_rebase::ConfirmRebase; use crate::constants::{LIST_HELP_LINES, VISUAL_MODE_HELP_LINES}; use crate::edit::Edit; +use crate::external_editor::ExternalEditor; use crate::input::{Input, InputHandler}; -use crate::process::{ - ExitStatus, - HandleInputResult, - HandleInputResultBuilder, - ProcessModule, - ProcessResult, - ProcessResultBuilder, - State, -}; +use crate::process::{ExitStatus, HandleInputResult, HandleInputResultBuilder, ProcessModule, ProcessResult, State}; use crate::show_commit::ShowCommit; use crate::view::View; -use crate::window::Window; use core::borrow::Borrow; -use std::process::Command; -use std::process::ExitStatus as ProcessExitStatus; pub struct Application<'a> { config: &'a Config, confirm_abort: ConfirmAbort, confirm_rebase: ConfirmRebase, edit: Edit, + external_editor: ExternalEditor<'a>, git_interactive: GitInteractive, input_handler: &'a InputHandler<'a>, show_commit: ShowCommit, @@ -47,6 +38,7 @@ impl<'a> Application<'a> { confirm_abort: ConfirmAbort::new(), confirm_rebase: ConfirmRebase::new(), edit: Edit::new(), + external_editor: ExternalEditor::new(config), git_interactive, input_handler, show_commit: ShowCommit::new(), @@ -65,9 +57,7 @@ impl<'a> Application<'a> { State::Edit => self.edit.activate(state, &self.git_interactive), State::Error { .. } => {}, State::Exiting => {}, - State::ExternalEditor(_) => {}, - State::ExternalEditorError => {}, - State::ExternalEditorFinish(_) => {}, + State::ExternalEditor => self.external_editor.activate(state, &self.git_interactive), State::Help(_) => {}, State::List => {}, State::ShowCommit => self.show_commit.activate(state, &self.git_interactive), @@ -83,9 +73,7 @@ impl<'a> Application<'a> { State::Edit => self.edit.deactivate(), State::Error { .. } => {}, State::Exiting => {}, - State::ExternalEditor(_) => {}, - State::ExternalEditorError => {}, - State::ExternalEditorFinish(_) => {}, + State::ExternalEditor => self.external_editor.deactivate(), State::Help(_) => {}, State::List => {}, State::ShowCommit => self.show_commit.deactivate(), @@ -101,9 +89,7 @@ impl<'a> Application<'a> { State::Edit => self.edit.process(&mut self.git_interactive), State::Error { .. } => ProcessResult::new(), State::Exiting => ProcessResult::new(), - State::ExternalEditor(return_state) => self.process_external_editor(return_state.borrow()), - State::ExternalEditorError => self.process_external_editor_error(), - State::ExternalEditorFinish(_) => self.process_external_editor_finish(), + State::ExternalEditor => self.external_editor.process(&mut self.git_interactive), State::Help(_) => ProcessResult::new(), State::List => self.process_list(), State::ShowCommit => self.show_commit.process(&mut self.git_interactive), @@ -112,48 +98,6 @@ impl<'a> Application<'a> { } } - pub fn process_external_editor(&mut self, return_state: &State) -> ProcessResult { - let mut result = ProcessResultBuilder::new(); - - result = if let Err(e) = self.run_editor() { - result.error(e.as_str(), State::ExternalEditorError) - } - else { - result.state(State::ExternalEditorFinish(Box::new(return_state.clone()))) - }; - - result.build() - } - - pub fn process_external_editor_finish(&mut self) -> ProcessResult { - let mut result = ProcessResultBuilder::new(); - result = if let Err(e) = self.git_interactive.reload_file(self.config.comment_char.as_str()) { - result.error(e.as_str(), State::List) - } - else if self.git_interactive.get_lines().is_empty() { - result.error("Rebase empty", State::List) - } - else { - result.state(State::List) - }; - - result.build() - } - - pub fn process_external_editor_error(&mut self) -> ProcessResult { - ProcessResultBuilder::new() - .state(State::Exiting) - .exit_status( - if self.git_interactive.get_lines().is_empty() { - ExitStatus::Good - } - else { - ExitStatus::StateError - }, - ) - .build() - } - pub fn process_list(&mut self) -> ProcessResult { let lines = self.git_interactive.get_lines(); let selected_index = self.get_cursor_index(); @@ -173,9 +117,7 @@ impl<'a> Application<'a> { State::Edit => self.edit.render(&self.view, &self.git_interactive), State::Error { message, .. } => self.draw_error(message.as_str()), State::Exiting => self.draw_exiting(), - State::ExternalEditor(_) => {}, - State::ExternalEditorError => {}, - State::ExternalEditorFinish(_) => {}, + State::ExternalEditor => self.external_editor.render(&self.view, &self.git_interactive), State::Help(help_state) => self.draw_help(help_state.borrow()), State::List => self.draw_main(false), State::VisualMode => self.draw_main(true), @@ -238,9 +180,10 @@ impl<'a> Application<'a> { State::Edit => self.edit.handle_input(&self.input_handler, &mut self.git_interactive), State::Error { return_state, .. } => self.handle_error_input(return_state.borrow()), State::Exiting => HandleInputResult::new(Input::Other), - State::ExternalEditor(return_state) => self.handle_external_editor_input(return_state.borrow()), - State::ExternalEditorError => HandleInputResult::new(Input::Other), - State::ExternalEditorFinish(_) => HandleInputResult::new(Input::Other), + State::ExternalEditor => { + self.external_editor + .handle_input(&self.input_handler, &mut self.git_interactive) + }, State::Help(help_state) => self.handle_help_input(help_state.borrow()), State::List => self.handle_list_input(), State::VisualMode => self.handle_visual_mode_input(), @@ -326,18 +269,6 @@ impl<'a> Application<'a> { result.build() } - pub fn handle_external_editor_input(&mut self, return_state: &State) -> HandleInputResult { - let input = self.get_input(); - let mut result = HandleInputResultBuilder::new(input); - match input { - Input::Resize => {}, - _ => { - result = result.state(return_state.clone()); - }, - } - result.build() - } - pub fn handle_list_input(&mut self) -> HandleInputResult { let input = self.get_input(); let mut result = HandleInputResultBuilder::new(input); @@ -386,7 +317,7 @@ impl<'a> Application<'a> { self.git_interactive.start_visual_mode(); result = result.state(State::VisualMode); }, - Input::OpenInEditor => result = result.state(State::ExternalEditor(Box::new(State::List))), + Input::OpenInEditor => result = result.state(State::ExternalEditor), _ => {}, } result.build() @@ -396,31 +327,6 @@ impl<'a> Application<'a> { HandleInputResult::new(self.get_input()) } - pub fn run_editor(&mut self) -> Result<(), String> { - self.git_interactive.write_file()?; - let filepath = self.git_interactive.get_filepath(); - let callback = || -> Result<ProcessExitStatus, String> { - // TODO: This doesn't handle editor with arguments (e.g. EDITOR="edit --arg") - Command::new(&self.config.editor) - .arg(filepath.as_os_str()) - .status() - .map_err(|e| { - format!( - "Unable to run editor ({}):\n{}", - self.config.editor.to_string_lossy(), - e.to_string() - ) - }) - }; - let exit_status: ProcessExitStatus = Window::leave_temporarily(callback)?; - - if !exit_status.success() { - return Err(String::from("Editor returned non-zero exit status.")); - } - - Ok(()) - } - pub fn write_file(&self) -> Result<(), String> { self.git_interactive.write_file() } diff --git a/src/external_editor/external_editor.rs b/src/external_editor/external_editor.rs new file mode 100644 index 0000000..b7fd186 --- /dev/null +++ b/src/external_editor/external_editor.rs @@ -0,0 +1,141 @@ +use crate::config::Config; +use crate::git_interactive::GitInteractive; +use crate::input::{Input, InputHandler}; +use crate::process::{ + ExitStatus, + HandleInputResult, + HandleInputResultBuilder, + ProcessModule, + ProcessResult, + ProcessResultBuilder, + State, +}; +use crate::view::View; +use crate::window::Window; +use std::process::Command; +use std::process::ExitStatus as ProcessExitStatus; + +enum ExternalEditorState { + Active, + Error, + Finish, +} + +pub struct ExternalEditor<'e> { + state: ExternalEditorState, + config: &'e Config, +} + +impl<'e> ProcessModule for ExternalEditor<'e> { + fn activate(&mut self, _state: State, _git_interactive: &GitInteractive) { + self.state = ExternalEditorState::Active; + } + + fn process(&mut self, git_interactive: &mut GitInteractive) -> ProcessResult { + match self.state { + ExternalEditorState::Active => self.process_active(git_interactive), + ExternalEditorState::Error => self.process_error(git_interactive), + ExternalEditorState::Finish => self.process_finish(git_interactive), + } + } + + fn handle_input( + &mut self, + input_handler: &InputHandler, + _git_interactive: &mut GitInteractive, + ) -> HandleInputResult + { + match self.state { + ExternalEditorState::Active => self.handle_input_active(input_handler), + _ => HandleInputResult::new(Input::Other), + } + } + + fn render(&self, _view: &View, _git_interactive: &GitInteractive) {} +} + +impl<'e> ExternalEditor<'e> { + pub fn new(config: &'e Config) -> Self { + Self { + config, + state: ExternalEditorState::Active, + } + } + + pub fn run_editor(&mut self, git_interactive: &GitInteractive) -> Result<(), String> { + git_interactive.write_file()?; + let filepath = git_interactive.get_filepath(); + let callback = || -> Result<ProcessExitStatus, String> { + // TODO: This doesn't handle editor with arguments (e.g. EDITOR="edit --arg") + Command::new(&self.config.editor) + .arg(filepath.as_os_str()) + .status() + .map_err(|e| { + format!( + "Unable to run editor ({}):\n{}", + self.config.editor.to_string_lossy(), + e.to_string() + ) + }) + }; + let exit_status: ProcessExitStatus = Window::leave_temporarily(callback)?; + + if !exit_status.success() { + return Err(String::from("Editor returned non-zero exit status.")); + } + + Ok(()) + } + + fn process_active(&mut self, git_interactive: &GitInteractive) -> ProcessResult { + let mut result = ProcessResultBuilder::new(); + if let Err(e) = self.run_editor(git_interactive) { + result = result.error(e.as_str(), State::ExternalEditor); + self.state = ExternalEditorState::Error; + } + else { + self.state = ExternalEditorState::Finish; + } + result.build() + } + + fn process_finish(&mut self, git_interactive: &mut GitInteractive) -> ProcessResult { + let mut result = ProcessResultBuilder::new(); + if let Err(e) = git_interactive.reload_file(self.config.comment_char.as_str()) { + result = result.error(e.as_str(), State::ExternalEditor); + self.state = ExternalEditorState::Error; + } + else if git_interactive.get_lines().is_empty() { + result = result.error("Rebase TODO list is empty", State::ExternalEditor); + self.state = ExternalEditorState::Error; + } + else { + result = result.state(State::List); + } + result.build() + } + + fn process_error(&self, git_interactive: &GitInteractive) -> ProcessResult { + let mut result = ProcessResultBuilder::new().state(State::Exiting); + + if git_interactive.get_lines().is_empty() { + result = result.exit_status(ExitStatus::Good); + } + else { + result = result.exit_status(ExitStatus::StateError); + } + result.build() + } + + pub fn handle_input_active(&self, input_handler: &InputHandler) -> HandleInputResult { + let input = input_handler.get_input(); + let mut result = HandleInputResultBuilder::new(input); + match input { + Input::Resize => {}, + _ => { + result = result.state(State::List); + }, + } + result.build() + } +} diff --git a/src/external_editor/mod.rs b/src/external_editor/mod.rs new file mode 100644 index 0000000..efa7480 --- /dev/null +++ b/src/external_editor/mod.rs @@ -0,0 +1,4 @@ +#[allow(clippy::module_inception)] +mod external_editor; + +pub use self::external_editor::ExternalEditor; diff --git a/src/main.rs b/src/main.rs index a4983d3..4231db2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod confirm_abort; mod confirm_rebase; mod constants; mod edit; +mod external_editor; mod git_interactive; mod input; mod line; diff --git a/src/process/state.rs b/src/process/state.rs index d750982..b286cb9 100644 --- a/src/process/state.rs +++ b/src/process/state.rs @@ -5,9 +5,7 @@ pub enum State { Edit, Error { return_state: Box<State>, message: String }, Exiting, - ExternalEditor(Box<State>), - ExternalEditorError, - ExternalEditorFinish(Box<State>), + ExternalEditor, Help(Box<State>), List, ShowCommit, |