summaryrefslogtreecommitdiffstats
path: root/src/core/modules/error/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/modules/error/mod.rs')
-rw-r--r--src/core/modules/error/mod.rs204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/core/modules/error/mod.rs b/src/core/modules/error/mod.rs
new file mode 100644
index 0000000..dd77eaa
--- /dev/null
+++ b/src/core/modules/error/mod.rs
@@ -0,0 +1,204 @@
+use display::DisplayColor;
+use input::{Event, EventHandler, InputOptions};
+use lazy_static::lazy_static;
+use todo_file::TodoFile;
+use view::{handle_view_data_scroll, LineSegment, RenderContext, ViewData, ViewLine, ViewSender};
+
+use crate::module::{Module, ProcessResult, State};
+
+lazy_static! {
+ static ref INPUT_OPTIONS: InputOptions = InputOptions::new().movement(true);
+}
+
+pub struct Error {
+ return_state: State,
+ view_data: ViewData,
+}
+
+impl Module for Error {
+ fn activate(&mut self, _: &TodoFile, previous_state: State) -> ProcessResult {
+ self.return_state = previous_state;
+ ProcessResult::new()
+ }
+
+ fn build_view_data(&mut self, _: &RenderContext, _: &TodoFile) -> &ViewData {
+ &self.view_data
+ }
+
+ fn handle_events(
+ &mut self,
+ event_handler: &EventHandler,
+ view_sender: &ViewSender,
+ _: &mut TodoFile,
+ ) -> ProcessResult {
+ let event = event_handler.read_event(&INPUT_OPTIONS, |event, _| event);
+ let mut result = ProcessResult::from(event);
+ if handle_view_data_scroll(event, view_sender).is_none() {
+ if let Event::Key(_) = event {
+ result = result.state(self.return_state);
+ }
+ }
+ result
+ }
+
+ fn handle_error(&mut self, error: &anyhow::Error) {
+ self.view_data.update_view_data(|updater| {
+ updater.clear();
+ for cause in error.chain() {
+ let error_text = format!("{:#}", cause);
+ for err in error_text.split('\n') {
+ updater.push_line(ViewLine::from(err));
+ }
+ }
+ updater.push_trailing_line(ViewLine::from(LineSegment::new_with_color(
+ "Press any key to continue",
+ DisplayColor::IndicatorColor,
+ )));
+ });
+ }
+}
+
+impl Error {
+ pub fn new() -> Self {
+ Self {
+ return_state: State::List,
+ view_data: ViewData::new(|updater| {
+ updater.set_show_title(true);
+ updater.set_retain_scroll_position(false);
+ }),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use anyhow::anyhow;
+ use input::{Event, MetaEvent};
+ use view::assert_rendered_output;
+
+ use super::*;
+ use crate::{assert_process_result, module::testutil::module_test};
+
+ #[test]
+ fn simple_error() {
+ module_test(&[], &[], |test_context| {
+ let mut module = Error::new();
+ module.handle_error(&anyhow!("Test Error"));
+ let view_data = test_context.build_view_data(&mut module);
+ assert_rendered_output!(
+ view_data,
+ "{TITLE}",
+ "{BODY}",
+ "{Normal}Test Error",
+ "{TRAILING}",
+ "{IndicatorColor}Press any key to continue"
+ );
+ });
+ }
+
+ #[test]
+ fn error_with_contest() {
+ module_test(&[], &[], |test_context| {
+ let mut module = Error::new();
+ module.handle_error(&anyhow!("Test Error").context("Context"));
+ let view_data = test_context.build_view_data(&mut module);
+ assert_rendered_output!(
+ view_data,
+ "{TITLE}",
+ "{BODY}",
+ "{Normal}Context",
+ "{Normal}Test Error",
+ "{TRAILING}",
+ "{IndicatorColor}Press any key to continue"
+ );
+ });
+ }
+
+ #[test]
+ fn error_with_newlines() {
+ module_test(&[], &[], |test_context| {
+ let mut module = Error::new();
+ module.handle_error(&anyhow!("Test\nError").context("With\nContext"));
+ let view_data = test_context.build_view_data(&mut module);
+ assert_rendered_output!(
+ view_data,
+ "{TITLE}",
+ "{BODY}",
+ "{Normal}With",
+ "{Normal}Context",
+ "{Normal}Test",
+ "{Normal}Error",
+ "{TRAILING}",
+ "{IndicatorColor}Press any key to continue"
+ );
+ });
+ }
+
+ #[test]
+ fn return_state() {
+ module_test(&[], &[Event::from('a')], |mut test_context| {
+ let mut module = Error::new();
+ test_context.activate(&mut module, State::ConfirmRebase);
+ module.handle_error(&anyhow!("Test Error"));
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from('a'),
+ state = State::ConfirmRebase
+ );
+ });
+ }
+
+ #[test]
+ fn resize() {
+ module_test(&[], &[Event::Resize(100, 100)], |mut test_context| {
+ let mut module = Error::new();
+ test_context.activate(&mut module, State::ConfirmRebase);
+ module.handle_error(&anyhow!("Test Error"));
+ assert_process_result!(test_context.handle_event(&mut module), event = Event::Resize(100, 100));
+ });
+ }
+
+ #[test]
+ fn scroll_events() {
+ module_test(
+ &[],
+ &[
+ Event::from(MetaEvent::ScrollLeft),
+ Event::from(MetaEvent::ScrollRight),
+ Event::from(MetaEvent::ScrollDown),
+ Event::from(MetaEvent::ScrollUp),
+ Event::from(MetaEvent::ScrollJumpDown),
+ Event::from(MetaEvent::ScrollJumpUp),
+ ],
+ |mut test_context| {
+ let mut module = Error::new();
+ test_context.activate(&mut module, State::ConfirmRebase);
+ module.handle_error(&anyhow!("Test Error"));
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollLeft)
+ );
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollRight)
+ );
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollDown)
+ );
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollUp)
+ );
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollJumpDown)
+ );
+ assert_process_result!(
+ test_context.handle_event(&mut module),
+ event = Event::from(MetaEvent::ScrollJumpUp)
+ );
+ },
+ );
+ }
+}