summaryrefslogtreecommitdiffstats
path: root/src/process
diff options
context:
space:
mode:
authorTim Oram <dev@mitmaro.ca>2020-09-17 10:45:49 -0230
committerTim Oram <dev@mitmaro.ca>2020-09-17 22:01:14 -0230
commitc6dbcc6017a7a1b343a585729239ad52ccb6ceba (patch)
tree5f27828bc435ef9eed85ebd835d55418985c07cb /src/process
parent10d797ebf3910f45f6ed3cd01573e531f388f31d (diff)
Move error handling to process module
The error handling module needed to have state provided to it from other modules, which meant that the other modules needed to understand how the error module worked. This was awkward and fragile. This moves the error handling code into the process module and makes it a global system. This has the advantage of not requiring tracking of the previous state and allows for the removal of the HandleInputResult struct.
Diffstat (limited to 'src/process')
-rw-r--r--src/process/error.rs29
-rw-r--r--src/process/handle_input_result.rs52
-rw-r--r--src/process/help.rs8
-rw-r--r--src/process/mod.rs169
-rw-r--r--src/process/process_module.rs5
-rw-r--r--src/process/process_result.rs41
-rw-r--r--src/process/state.rs1
-rw-r--r--src/process/testutil.rs8
8 files changed, 136 insertions, 177 deletions
diff --git a/src/process/error.rs b/src/process/error.rs
new file mode 100644
index 0000000..65e4766
--- /dev/null
+++ b/src/process/error.rs
@@ -0,0 +1,29 @@
+use crate::input::input_handler::{InputHandler, InputMode};
+use crate::process::process_result::ProcessResult;
+use crate::view::view_data::ViewData;
+use crate::view::View;
+
+pub struct Error {
+ view_data: ViewData,
+}
+
+impl Error {
+ pub fn new(message: &str) -> Self {
+ Self {
+ view_data: ViewData::new_error(message),
+ }
+ }
+
+ pub fn get_view_data(&mut self, view: &View<'_>) -> &ViewData {
+ let (view_width, view_height) = view.get_view_size();
+ self.view_data.set_view_size(view_width, view_height);
+ self.view_data.rebuild();
+ &self.view_data
+ }
+
+ #[allow(clippy::unused_self)]
+ pub fn handle_input(&mut self, input_handler: &InputHandler<'_>) -> ProcessResult {
+ let input = input_handler.get_input(InputMode::Default);
+ ProcessResult::new().input(input)
+ }
+}
diff --git a/src/process/handle_input_result.rs b/src/process/handle_input_result.rs
deleted file mode 100644
index 9f63ee6..0000000
--- a/src/process/handle_input_result.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use crate::input::Input;
-use crate::process::exit_status::ExitStatus;
-use crate::process::state::State;
-
-#[derive(Debug, PartialEq)]
-pub struct HandleInputResult {
- pub(super) exit_status: Option<ExitStatus>,
- pub(super) input: Input,
- pub(super) state: Option<State>,
-}
-
-impl HandleInputResult {
- pub(crate) const fn new(input: Input) -> Self {
- Self {
- exit_status: None,
- input,
- state: None,
- }
- }
-}
-
-pub struct HandleInputResultBuilder {
- handle_input: HandleInputResult,
-}
-
-impl HandleInputResultBuilder {
- pub(crate) const fn new(input: Input) -> Self {
- Self {
- handle_input: HandleInputResult {
- exit_status: None,
- input,
- state: None,
- },
- }
- }
-
- pub(crate) const fn exit_status(mut self, status: ExitStatus) -> Self {
- self.handle_input.exit_status = Some(status);
- self
- }
-
- #[allow(clippy::missing_const_for_fn)]
- pub(crate) fn state(mut self, new_state: State) -> Self {
- self.handle_input.state = Some(new_state);
- self
- }
-
- #[allow(clippy::missing_const_for_fn)]
- pub(crate) fn build(self) -> HandleInputResult {
- self.handle_input
- }
-}
diff --git a/src/process/help.rs b/src/process/help.rs
index 304ea4c..4be9cdd 100644
--- a/src/process/help.rs
+++ b/src/process/help.rs
@@ -1,7 +1,7 @@
use crate::display::display_color::DisplayColor;
use crate::input::input_handler::{InputHandler, InputMode};
use crate::input::Input;
-use crate::process::handle_input_result::HandleInputResult;
+use crate::process::process_result::ProcessResult;
use crate::view::line_segment::LineSegment;
use crate::view::view_data::ViewData;
use crate::view::view_line::ViewLine;
@@ -84,7 +84,7 @@ impl Help {
&self.view_data
}
- pub fn handle_input(&mut self, input_handler: &InputHandler<'_>, view: &View<'_>) -> HandleInputResult {
+ pub fn handle_input(&mut self, input_handler: &InputHandler<'_>, view: &View<'_>) -> ProcessResult {
let input = input_handler.get_input(InputMode::Default);
match input {
Input::MoveCursorLeft => self.view_data.scroll_left(),
@@ -97,8 +97,8 @@ impl Help {
let (view_width, view_height) = view.get_view_size();
self.view_data.set_view_size(view_width, view_height);
},
- _ => return HandleInputResult::new(Input::Help),
+ _ => return ProcessResult::new().input(Input::Help),
}
- HandleInputResult::new(input)
+ ProcessResult::new().input(input)
}
}
diff --git a/src/process/mod.rs b/src/process/mod.rs
index b794856..039c2cc 100644
--- a/src/process/mod.rs
+++ b/src/process/mod.rs
@@ -1,5 +1,5 @@
+mod error;
pub mod exit_status;
-pub mod handle_input_result;
mod help;
pub mod process_module;
pub mod process_result;
@@ -13,16 +13,17 @@ use crate::confirm_rebase::ConfirmRebase;
use crate::constants::{MINIMUM_COMPACT_WINDOW_WIDTH, MINIMUM_WINDOW_HEIGHT};
use crate::display::Display;
use crate::edit::Edit;
-use crate::error::Error;
use crate::exiting::Exiting;
use crate::external_editor::ExternalEditor;
use crate::git_interactive::GitInteractive;
use crate::input::input_handler::InputHandler;
use crate::input::Input;
use crate::list::List;
+use crate::process::error::Error;
use crate::process::exit_status::ExitStatus;
use crate::process::help::Help;
use crate::process::process_module::ProcessModule;
+use crate::process::process_result::ProcessResult;
use crate::process::state::State;
use crate::show_commit::ShowCommit;
use crate::view::View;
@@ -32,7 +33,7 @@ pub struct Process<'r> {
confirm_abort: ConfirmAbort,
confirm_rebase: ConfirmRebase,
edit: Edit,
- error: Error,
+ error: Option<Error>,
exit_status: Option<ExitStatus>,
exiting: Exiting,
external_editor: ExternalEditor<'r>,
@@ -59,7 +60,7 @@ impl<'r> Process<'r> {
confirm_abort: ConfirmAbort::new(),
confirm_rebase: ConfirmRebase::new(),
edit: Edit::new(),
- error: Error::new(),
+ error: None,
exit_status: None,
exiting: Exiting::new(),
external_editor: ExternalEditor::new(display, config.git.editor.as_str()),
@@ -77,7 +78,9 @@ impl<'r> Process<'r> {
pub(crate) fn run(&mut self) -> Result<Option<ExitStatus>, String> {
self.check_window_size();
while self.exit_status.is_none() {
- self.process();
+ if self.help.is_none() && self.error.is_none() {
+ self.process();
+ }
self.render();
self.handle_input();
}
@@ -90,7 +93,6 @@ impl<'r> Process<'r> {
State::ConfirmAbort => self.confirm_abort.activate(&self.state, &self.git_interactive),
State::ConfirmRebase => self.confirm_rebase.activate(&self.state, &self.git_interactive),
State::Edit => self.edit.activate(&self.state, &self.git_interactive),
- State::Error { .. } => self.error.activate(&self.state, &self.git_interactive),
State::Exiting => self.exiting.activate(&self.state, &self.git_interactive),
State::ExternalEditor => self.external_editor.activate(&self.state, &self.git_interactive),
State::List => self.list.activate(&self.state, &self.git_interactive),
@@ -104,7 +106,6 @@ impl<'r> Process<'r> {
State::ConfirmAbort => self.confirm_abort.deactivate(),
State::ConfirmRebase => self.confirm_rebase.deactivate(),
State::Edit => self.edit.deactivate(),
- State::Error { .. } => self.error.deactivate(),
State::Exiting => self.exiting.deactivate(),
State::ExternalEditor => self.external_editor.deactivate(),
State::List => self.list.deactivate(),
@@ -114,31 +115,18 @@ impl<'r> Process<'r> {
}
fn process(&mut self) {
- if self.help.is_none() {
- let result = match self.state {
- State::ConfirmAbort => self.confirm_abort.process(&mut self.git_interactive, self.view),
- State::ConfirmRebase => self.confirm_rebase.process(&mut self.git_interactive, self.view),
- State::Edit => self.edit.process(&mut self.git_interactive, self.view),
- State::Error { .. } => self.error.process(&mut self.git_interactive, self.view),
- State::Exiting => self.exiting.process(&mut self.git_interactive, self.view),
- State::ExternalEditor => self.external_editor.process(&mut self.git_interactive, self.view),
- State::List => self.list.process(&mut self.git_interactive, self.view),
- State::ShowCommit => self.show_commit.process(&mut self.git_interactive, self.view),
- State::WindowSizeError(_) => self.window_size_error.process(&mut self.git_interactive, self.view),
- };
-
- if let Some(exit_status) = result.exit_status {
- self.exit_status = Some(exit_status);
- }
-
- if let Some(new_state) = result.state {
- if new_state != self.state {
- self.deactivate();
- self.state = new_state;
- self.activate();
- }
- }
+ let result = match self.state {
+ State::ConfirmAbort => self.confirm_abort.process(&mut self.git_interactive, self.view),
+ State::ConfirmRebase => self.confirm_rebase.process(&mut self.git_interactive, self.view),
+ State::Edit => self.edit.process(&mut self.git_interactive, self.view),
+ State::Exiting => self.exiting.process(&mut self.git_interactive, self.view),
+ State::ExternalEditor => self.external_editor.process(&mut self.git_interactive, self.view),
+ State::List => self.list.process(&mut self.git_interactive, self.view),
+ State::ShowCommit => self.show_commit.process(&mut self.git_interactive, self.view),
+ State::WindowSizeError(_) => self.window_size_error.process(&mut self.git_interactive, self.view),
};
+
+ self.handle_process_result(result);
}
fn render(&mut self) {
@@ -146,12 +134,14 @@ impl<'r> Process<'r> {
if let Some(ref mut help) = self.help {
help.get_view_data(self.view)
}
+ else if let Some(ref mut error) = self.error {
+ error.get_view_data(self.view)
+ }
else {
match self.state {
State::ConfirmAbort => self.confirm_abort.build_view_data(self.view, &self.git_interactive),
State::ConfirmRebase => self.confirm_rebase.build_view_data(self.view, &self.git_interactive),
State::Edit => self.edit.build_view_data(self.view, &self.git_interactive),
- State::Error { .. } => self.error.build_view_data(self.view, &self.git_interactive),
State::Exiting => self.exiting.build_view_data(self.view, &self.git_interactive),
State::ExternalEditor => self.external_editor.build_view_data(self.view, &self.git_interactive),
State::List => self.list.build_view_data(self.view, &self.git_interactive),
@@ -164,41 +154,15 @@ impl<'r> Process<'r> {
);
}
- fn activate_help(&mut self) {
- self.help = match self.state {
- State::List => {
- Some(Help::new_from_view_data(
- self.list.get_help_keybindings_descriptions(),
- self.list.get_help_view(),
- ))
- },
- State::ShowCommit => {
- Some(Help::new_from_view_data(
- self.show_commit.get_help_keybindings_descriptions(),
- self.show_commit.get_help_view(),
- ))
- },
- State::ConfirmAbort
- | State::ConfirmRebase
- | State::Edit
- | State::Error { .. }
- | State::Exiting
- | State::ExternalEditor
- | State::WindowSizeError(_) => None,
- };
- }
-
fn handle_input(&mut self) {
- if let Some(ref mut help) = self.help {
- let result = help.handle_input(self.input_handler, self.view);
- match result.input {
- Input::Resize => self.check_window_size(),
- Input::Help => self.help = None,
- _ => {},
- }
+ let result = if let Some(ref mut help) = self.help {
+ help.handle_input(self.input_handler, self.view)
+ }
+ else if let Some(ref mut error) = self.error {
+ error.handle_input(self.input_handler)
}
else {
- let result = match self.state {
+ match self.state {
State::ConfirmAbort => {
self.confirm_abort
.handle_input(self.input_handler, &mut self.git_interactive, self.view)
@@ -211,10 +175,6 @@ impl<'r> Process<'r> {
self.edit
.handle_input(self.input_handler, &mut self.git_interactive, self.view)
},
- State::Error { .. } => {
- self.error
- .handle_input(self.input_handler, &mut self.git_interactive, self.view)
- },
State::Exiting => {
self.exiting
.handle_input(self.input_handler, &mut self.git_interactive, self.view)
@@ -235,29 +195,66 @@ impl<'r> Process<'r> {
self.window_size_error
.handle_input(self.input_handler, &mut self.git_interactive, self.view)
},
- };
-
- if Input::Help == result.input {
- self.activate_help();
}
- else {
- if let Some(exit_status) = result.exit_status {
- self.exit_status = Some(exit_status);
- }
+ };
+ self.handle_process_result(result);
+ }
- if let Some(new_state) = result.state {
- if new_state != self.state {
- self.deactivate();
- self.state = new_state;
- self.activate();
- }
- }
+ fn handle_process_result(&mut self, result: ProcessResult) {
+ if let Some(exit_status) = result.exit_status {
+ self.exit_status = Some(exit_status);
+ }
+
+ if let Some(error_message) = result.error_message {
+ self.error = Some(Error::new(error_message.as_str()));
+ }
- if Input::Resize == result.input {
- self.check_window_size();
+ match result.input {
+ Some(Input::Help) => self.toggle_help(),
+ Some(Input::Resize) => self.check_window_size(),
+ Some(_) => {
+ if self.error.is_some() {
+ self.error = None;
}
- }
+ },
+ None => {},
};
+
+ if let Some(new_state) = result.state {
+ if new_state != self.state {
+ self.deactivate();
+ self.state = new_state;
+ self.activate();
+ }
+ }
+ }
+
+ fn toggle_help(&mut self) {
+ if self.help.is_some() {
+ self.help = None;
+ }
+ else {
+ self.help = match self.state {
+ State::List => {
+ Some(Help::new_from_view_data(
+ self.list.get_help_keybindings_descriptions(),
+ self.list.get_help_view(),
+ ))
+ },
+ State::ShowCommit => {
+ Some(Help::new_from_view_data(
+ self.show_commit.get_help_keybindings_descriptions(),
+ self.show_commit.get_help_view(),
+ ))
+ },
+ State::ConfirmAbort
+ | State::ConfirmRebase
+ | State::Edit
+ | State::Exiting
+ | State::ExternalEditor
+ | State::WindowSizeError(_) => None,
+ };
+ }
}
fn check_window_size(&mut self) {
diff --git a/src/process/process_module.rs b/src/process/process_module.rs
index aa5e1d8..baeb079 100644
--- a/src/process/process_module.rs
+++ b/src/process/process_module.rs
@@ -1,7 +1,6 @@
use crate::git_interactive::GitInteractive;
use crate::input::input_handler::InputHandler;
use crate::input::Input;
-use crate::process::handle_input_result::HandleInputResult;
use crate::process::process_result::ProcessResult;
use crate::process::state::State;
use crate::view::view_data::ViewData;
@@ -23,9 +22,9 @@ pub trait ProcessModule {
_input_handler: &InputHandler<'_>,
_git_interactive: &mut GitInteractive,
_view: &View<'_>,
- ) -> HandleInputResult
+ ) -> ProcessResult
{
- HandleInputResult::new(Input::Other)
+ ProcessResult::new().input(Input::Other)
}
fn get_help_keybindings_descriptions(&self) -> Option<&[(&str, &str)]> {
diff --git a/src/process/process_result.rs b/src/process/process_result.rs
index edd038f..939fc8f 100644
--- a/src/process/process_result.rs
+++ b/src/process/process_result.rs
@@ -1,56 +1,43 @@
+use crate::input::Input;
use crate::process::exit_status::ExitStatus;
use crate::process::state::State;
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
pub struct ProcessResult {
+ pub(super) error_message: Option<String>,
pub(super) exit_status: Option<ExitStatus>,
+ pub(super) input: Option<Input>,
pub(super) state: Option<State>,
}
impl ProcessResult {
pub(crate) const fn new() -> Self {
Self {
+ error_message: None,
exit_status: None,
+ input: None,
state: None,
}
}
-}
-
-pub struct ProcessResultBuilder {
- process_result: ProcessResult,
-}
-impl ProcessResultBuilder {
- pub(crate) const fn new() -> Self {
- Self {
- process_result: ProcessResult {
- exit_status: None,
- state: None,
- },
- }
+ pub(crate) const fn input(mut self, input: Input) -> Self {
+ self.input = Some(input);
+ self
}
- pub(crate) fn error(mut self, message: &str, return_state: State) -> Self {
- self.process_result.state = Some(State::Error {
- return_state: Box::new(return_state),
- message: String::from(message),
- });
+ pub(crate) fn error(mut self, message: &str) -> Self {
+ self.error_message = Some(String::from(message));
self
}
pub(crate) const fn exit_status(mut self, status: ExitStatus) -> Self {
- self.process_result.exit_status = Some(status);
+ self.exit_status = Some(status);
self
}
- #[allow(clippy::missing_const_for_fn)]
+ #[allow(clippy::missing_const_for_fn)] // false positive
pub(crate) fn state(mut self, new_state: State) -> Self {
- self.process_result.state = Some(new_state);
+ self.state = Some(new_state);
self
}
-
- #[allow(clippy::missing_const_for_fn)]
- pub(crate) fn build(self) -> ProcessResult {
- self.process_result
- }
}
diff --git a/src/process/state.rs b/src/process/state.rs
index 2445ccb..228dc02 100644
--- a/src/process/state.rs
+++ b/src/process/state.rs
@@ -3,7 +3,6 @@ pub enum State {
ConfirmAbort,
ConfirmRebase,
Edit,
- Error { return_state: Box<State>, message: String },
Exiting,
ExternalEditor,
List,
diff --git a/src/process/testutil.rs b/src/process/testutil.rs
index 965f65c..f515ae4 100644
--- a/src/process/testutil.rs
+++ b/src/process/testutil.rs
@@ -7,8 +7,8 @@ use crate::input::input_handler::InputHandler;
use crate::input::Input;
use crate::list::line::Line;
use crate::process::exit_status::ExitStatus;
-use crate::process::handle_input_result::{HandleInputResult, HandleInputResultBuilder};
use crate::process::process_module::ProcessModule;
+use crate::process::process_result::ProcessResult;
use crate::process::state::State;
use crate::view::testutil::render_view_data;
use crate::view::View;
@@ -263,20 +263,20 @@ macro_rules! process_module_handle_input_test {
}
pub fn _assert_handle_input_result(
- actual: &HandleInputResult,
+ actual: &ProcessResult,
input: Input,
state: Option<State>,
exit_status: Option<ExitStatus>,
)
{
- let mut expected = HandleInputResultBuilder::new(input);
+ let mut expected = ProcessResult::new().input(input);
if let Some(state) = state {
expected = expected.state(state);
}
if let Some(exit_status) = exit_status {
expected = expected.exit_status(exit_status);
}
- assert_eq!(actual, &expected.build());
+ assert_eq!(actual, &expected);
}
#[macro_export]