summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Oram <dev@mitmaro.ca>2021-01-17 19:36:19 -0330
committerTim Oram <dev@mitmaro.ca>2021-01-27 19:03:19 -0330
commitca089a55bd8ab3c7387bff0a92a4aab674e73d05 (patch)
tree541ed80c3cf197fdf8bb4c9ecac723568adf0131
parent65ffadbe8481cd1c852f585fe1e14820f2c74f67 (diff)
Return result in display
-rw-r--r--src/display/mod.rs59
-rw-r--r--src/display/virtual_curses.rs2
-rw-r--r--src/process/mod.rs9
-rw-r--r--src/view/mod.rs121
4 files changed, 104 insertions, 87 deletions
diff --git a/src/display/mod.rs b/src/display/mod.rs
index 1d7fdfd..3114e28 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -20,6 +20,7 @@ use crate::display::display_color::DisplayColor;
pub use crate::display::size::Size;
use crate::input::input_handler::{InputHandler, InputMode};
use crate::input::Input;
+use anyhow::Result;
use std::cell::RefCell;
use std::convert::TryInto;
@@ -165,21 +166,24 @@ impl<'d> Display<'d> {
}
}
- pub(crate) fn draw_str(&mut self, s: &str) {
+ pub(crate) fn draw_str(&mut self, s: &str) -> Result<()> {
self.curses.addstr(s);
+ Ok(())
}
- pub(crate) fn clear(&mut self) {
- self.color(DisplayColor::Normal, false);
- self.set_style(false, false, false);
+ pub(crate) fn clear(&mut self) -> Result<()> {
+ self.color(DisplayColor::Normal, false)?;
+ self.set_style(false, false, false)?;
self.curses.erase();
+ Ok(())
}
- pub(crate) fn refresh(&mut self) {
+ pub(crate) fn refresh(&mut self) -> Result<()> {
self.curses.refresh();
+ Ok(())
}
- pub(crate) fn color(&mut self, color: DisplayColor, selected: bool) {
+ pub(crate) fn color(&mut self, color: DisplayColor, selected: bool) -> Result<()> {
self.curses.attrset(
if selected {
match color {
@@ -220,24 +224,26 @@ impl<'d> Display<'d> {
}
},
);
+ Ok(())
}
- pub(crate) fn set_style(&mut self, dim: bool, underline: bool, reverse: bool) {
- self.set_dim(dim);
- self.set_underline(underline);
- self.set_reverse(reverse);
+ pub(crate) fn set_style(&mut self, dim: bool, underline: bool, reverse: bool) -> Result<()> {
+ self.set_dim(dim)?;
+ self.set_underline(underline)?;
+ self.set_reverse(reverse)
}
- fn set_dim(&mut self, on: bool) {
+ fn set_dim(&mut self, on: bool) -> Result<()> {
if on {
self.curses.attron(A_DIM);
}
else {
self.curses.attroff(A_DIM);
}
+ Ok(())
}
- fn set_underline(&mut self, on: bool) {
+ fn set_underline(&mut self, on: bool) -> Result<()> {
// Windows uses blue text for underlined words
if !cfg!(windows) && on {
self.curses.attron(A_UNDERLINE);
@@ -245,15 +251,17 @@ impl<'d> Display<'d> {
else {
self.curses.attroff(A_UNDERLINE);
}
+ Ok(())
}
- fn set_reverse(&mut self, on: bool) {
+ fn set_reverse(&mut self, on: bool) -> Result<()> {
if on {
self.curses.attron(A_REVERSE);
}
else {
self.curses.attroff(A_REVERSE);
}
+ Ok(())
}
pub(crate) fn get_input(&self, mode: InputMode) -> Input {
@@ -275,16 +283,19 @@ impl<'d> Display<'d> {
Size::new(*self.width.borrow(), *self.height.borrow())
}
- pub(crate) fn fill_end_of_line(&mut self) {
+ pub(crate) fn fill_end_of_line(&mut self) -> Result<()> {
self.curses.hline(' ', self.curses.get_max_x());
+ Ok(())
}
- pub(crate) fn ensure_at_line_start(&mut self, y: i32) {
+ pub(crate) fn ensure_at_line_start(&mut self, y: i32) -> Result<()> {
self.curses.mv(y, 0);
+ Ok(())
}
- pub(crate) fn move_from_end_of_line(&mut self, right: i32) {
+ pub(crate) fn move_from_end_of_line(&mut self, right: i32) -> Result<()> {
self.curses.mv(self.curses.get_cur_y(), self.curses.get_max_x() - right);
+ Ok(())
}
pub(crate) fn def_prog_mode(&self) {
@@ -335,7 +346,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.draw_str("Test String");
+ display.draw_str("Test String").unwrap();
let output = Curses::get_output();
assert_eq!(output, vec!["Test String"]);
});
@@ -355,7 +366,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.clear();
+ display.clear().unwrap();
assert!(Curses::get_output().is_empty());
assert!(!test_context.curses.is_dimmed());
assert!(!test_context.curses.is_reverse());
@@ -372,7 +383,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.refresh();
+ display.refresh().unwrap();
assert_eq!(test_context.curses.get_state(), State::Refreshed);
});
}
@@ -420,7 +431,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.color(display_color, selected);
+ display.color(display_color, selected).unwrap();
assert!(test_context.curses.is_color_enabled(expected));
});
}
@@ -446,7 +457,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.set_style(dim, underline, reverse);
+ display.set_style(dim, underline, reverse).unwrap();
assert_eq!(test_context.curses.is_dimmed(), dim);
assert_eq!(test_context.curses.is_underline(), underline);
assert_eq!(test_context.curses.is_reverse(), reverse);
@@ -506,7 +517,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.fill_end_of_line();
+ display.fill_end_of_line().unwrap();
assert_eq!(Curses::get_output()[0], "{HLINE| |23}");
});
}
@@ -522,7 +533,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.ensure_at_line_start(5);
+ display.ensure_at_line_start(5).unwrap();
assert_eq!(test_context.curses.get_cur_y(), 5);
assert_eq!(test_context.curses.get_cur_x(), 0);
});
@@ -539,7 +550,7 @@ mod tests {
&mut test_context.curses,
&test_context.config.theme,
);
- display.move_from_end_of_line(5);
+ display.move_from_end_of_line(5).unwrap();
assert_eq!(test_context.curses.get_cur_x(), 20);
});
}
diff --git a/src/display/virtual_curses.rs b/src/display/virtual_curses.rs
index 6497de0..decd0ee 100644
--- a/src/display/virtual_curses.rs
+++ b/src/display/virtual_curses.rs
@@ -114,7 +114,7 @@ impl Curses {
}
#[allow(clippy::unused_self)]
- pub(super) fn erase(&self) {
+ pub(crate) fn erase(&self) {
OUTPUT.lock().unwrap().clear();
}
diff --git a/src/process/mod.rs b/src/process/mod.rs
index c11bfc3..8e3541b 100644
--- a/src/process/mod.rs
+++ b/src/process/mod.rs
@@ -48,8 +48,13 @@ impl<'r> Process<'r> {
}
self.activate(&mut modules, State::List);
while self.exit_status.is_none() {
- self.view
- .render(modules.build_view_data(self.state, &self.view, &self.rebase_todo));
+ if let Err(_) = self
+ .view
+ .render(modules.build_view_data(self.state, &self.view, &self.rebase_todo))
+ {
+ self.exit_status = Some(ExitStatus::StateError);
+ continue;
+ }
let result = modules.handle_input(self.state, &self.view, &mut self.rebase_todo);
self.handle_process_result(&mut modules, &result);
}
diff --git a/src/view/mod.rs b/src/view/mod.rs
index 629f14d..1458f00 100644
--- a/src/view/mod.rs
+++ b/src/view/mod.rs
@@ -13,6 +13,7 @@ use crate::input::Input;
use crate::view::view_data::ViewData;
use crate::view::view_line::ViewLine;
use crate::Config;
+use anyhow::Result;
pub struct View<'v> {
config: &'v Config,
@@ -39,34 +40,33 @@ impl<'v> View<'v> {
}
pub(crate) fn end(&self) {
- self.display.end();
+ self.display.end()
}
pub(crate) fn get_input(&self, mode: InputMode) -> Input {
self.display.get_input(mode)
}
- pub(crate) fn render(&mut self, view_data: &ViewData) {
- self.display.clear();
+ pub(crate) fn render(&mut self, view_data: &ViewData) -> Result<()> {
+ self.display.clear()?;
let window_height = self.display.get_window_size().height();
let mut line_index = 0;
if view_data.show_title() {
- self.display.ensure_at_line_start(line_index);
+ self.display.ensure_at_line_start(line_index)?;
line_index += 1;
- self.draw_title(view_data.show_help());
+ self.draw_title(view_data.show_help())?;
}
if let Some(ref prompt) = *view_data.get_prompt() {
- self.display.set_style(false, false, false);
- self.display.draw_str("\n");
+ self.display.set_style(false, false, false)?;
+ self.display.draw_str("\n")?;
self.display.draw_str(&format!(
- "{} ({}/{})?",
+ "{} ({}/{})? ",
prompt, self.config.key_bindings.confirm_yes, self.config.key_bindings.confirm_no
- ));
- self.display.draw_str(" ");
- return;
+ ))?;
+ return Ok(());
}
let leading_lines = view_data.get_leading_lines();
@@ -79,100 +79,100 @@ impl<'v> View<'v> {
let scroll_indicator_index = view_data.get_scroll_index();
for line in leading_lines {
- self.display.ensure_at_line_start(line_index);
+ self.display.ensure_at_line_start(line_index)?;
line_index += 1;
- self.draw_view_line(line);
+ self.draw_view_line(line)?;
}
for (index, line) in lines.iter().enumerate() {
- self.display.ensure_at_line_start(line_index);
- self.draw_view_line(line);
+ self.display.ensure_at_line_start(line_index)?;
+ self.draw_view_line(line)?;
if show_scroll_bar {
- self.display.ensure_at_line_start(line_index);
- self.display.move_from_end_of_line(1);
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(scroll_indicator_index != index, false, true);
- self.display.draw_str(" ");
+ self.display.ensure_at_line_start(line_index)?;
+ self.display.move_from_end_of_line(1)?;
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(scroll_indicator_index != index, false, true)?;
+ self.display.draw_str(" ")?;
}
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(false, false, false);
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(false, false, false)?;
line_index += 1;
}
if view_height > lines.len() {
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(false, false, false);
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(false, false, false)?;
let draw_height = view_height - lines.len() - if view_data.show_title() { 1 } else { 0 };
- self.display.ensure_at_line_start(line_index);
+ self.display.ensure_at_line_start(line_index)?;
for _x in 0..draw_height {
line_index += 1;
self.display
- .draw_str(format!("{}\n", self.config.theme.character_vertical_spacing).as_str());
+ .draw_str(format!("{}\n", self.config.theme.character_vertical_spacing).as_str())?;
}
}
for line in trailing_lines {
- self.display.ensure_at_line_start(line_index);
+ self.display.ensure_at_line_start(line_index)?;
line_index += 1;
- self.draw_view_line(line);
+ self.draw_view_line(line)?;
}
- self.display.refresh();
+ self.display.refresh()
}
- fn draw_view_line(&mut self, line: &ViewLine) {
+ fn draw_view_line(&mut self, line: &ViewLine) -> Result<()> {
for segment in line.get_segments() {
- self.display.color(segment.get_color(), line.get_selected());
+ self.display.color(segment.get_color(), line.get_selected())?;
self.display
- .set_style(segment.is_dimmed(), segment.is_underlined(), segment.is_reversed());
- self.display.draw_str(segment.get_content());
+ .set_style(segment.is_dimmed(), segment.is_underlined(), segment.is_reversed())?;
+ self.display.draw_str(segment.get_content())?;
}
// reset style
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(false, false, false);
- self.display.fill_end_of_line();
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(false, false, false)?;
+ self.display.fill_end_of_line()
}
- fn draw_title(&mut self, show_help: bool) {
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(false, true, false);
+ fn draw_title(&mut self, show_help: bool) -> Result<()> {
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(false, true, false)?;
let window_width = self.display.get_window_size().width();
let title_help_indicator_total_length = TITLE_HELP_INDICATOR_LENGTH + self.config.key_bindings.help.len();
if window_width >= TITLE_LENGTH {
- self.display.draw_str(TITLE);
+ self.display.draw_str(TITLE)?;
// only draw help if there is room
if window_width > TITLE_LENGTH + title_help_indicator_total_length {
if (window_width - TITLE_LENGTH - title_help_indicator_total_length) > 0 {
let padding = " ".repeat(window_width - TITLE_LENGTH - title_help_indicator_total_length);
- self.display.draw_str(padding.as_str());
+ self.display.draw_str(padding.as_str())?;
}
if show_help {
self.display
- .draw_str(format!("Help: {}", self.config.key_bindings.help).as_str());
+ .draw_str(format!("Help: {}", self.config.key_bindings.help).as_str())?;
}
else {
let padding = " ".repeat(title_help_indicator_total_length);
- self.display.draw_str(padding.as_str());
+ self.display.draw_str(padding.as_str())?;
}
}
else if (window_width - TITLE_LENGTH) > 0 {
let padding = " ".repeat(window_width - TITLE_LENGTH);
- self.display.draw_str(padding.as_str());
+ self.display.draw_str(padding.as_str())?;
}
}
else {
- self.display.draw_str(TITLE_SHORT);
+ self.display.draw_str(TITLE_SHORT)?;
if (window_width - TITLE_SHORT_LENGTH) > 0 {
let padding = " ".repeat(window_width - TITLE_SHORT_LENGTH);
- self.display.draw_str(padding.as_str());
+ self.display.draw_str(padding.as_str())?;
}
}
// reset style
- self.display.color(DisplayColor::Normal, false);
- self.display.set_style(false, false, false);
+ self.display.color(DisplayColor::Normal, false)?;
+ self.display.set_style(false, false, false)
}
}
@@ -210,6 +210,7 @@ mod tests {
);
let config = Config::new().unwrap();
let mut curses = Curses::new();
+ curses.erase();
curses.resize_term(size.height().try_into().unwrap(), size.width().try_into().unwrap());
let input_handler = InputHandler::new(&config.key_bindings);
let display = Display::new(input_handler, &mut curses, &config.theme);
@@ -228,7 +229,7 @@ mod tests {
fn render_empty() {
view_module_test(&Size::new(20, 10), |mut test_context| {
let view_data = ViewData::new();
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
TestContext::assert_output(&["~\n"; 10]);
});
}
@@ -238,7 +239,7 @@ mod tests {
view_module_test(&Size::new(35, 10), |mut test_context| {
let mut view_data = ViewData::new();
view_data.set_show_title(true);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["Git Interactive Rebase Tool "];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -250,7 +251,7 @@ mod tests {
view_module_test(&Size::new(26, 10), |mut test_context| {
let mut view_data = ViewData::new();
view_data.set_show_title(true);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["Git Rebase "];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -263,7 +264,7 @@ mod tests {
let mut view_data = ViewData::new();
view_data.set_show_title(true);
view_data.set_show_help(true);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["Git Interactive Rebase Tool Help: ?"];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -276,7 +277,7 @@ mod tests {
let mut view_data = ViewData::new();
view_data.set_show_title(true);
view_data.set_show_help(true);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["Git Interactive Rebase Tool "];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -287,7 +288,7 @@ mod tests {
fn render_prompt() {
view_module_test(&Size::new(35, 10), |mut test_context| {
let view_data = ViewData::new_confirm("This is a prompt");
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let expected = vec!["Git Interactive Rebase Tool ", "\nThis is a prompt (y/n)? "];
TestContext::assert_output(&expected);
});
@@ -299,7 +300,7 @@ mod tests {
let mut view_data = ViewData::new();
view_data.push_leading_line(ViewLine::from("This is a leading line"));
view_data.set_view_size(30, 10);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["This is a leading line {HLINE| |30}"];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -312,7 +313,7 @@ mod tests {
let mut view_data = ViewData::new();
view_data.push_line(ViewLine::from("This is a line"));
view_data.set_view_size(30, 10);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["This is a line {HLINE| |30}"];
expected.extend(vec!["~\n"; 9]);
TestContext::assert_output(&expected);
@@ -325,7 +326,7 @@ mod tests {
let mut view_data = ViewData::new();
view_data.push_trailing_line(ViewLine::from("This is a trailing line"));
view_data.set_view_size(30, 10);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec!["~\n"; 9];
expected.push("This is a trailing line {HLINE| |30}");
TestContext::assert_output(&expected);
@@ -340,7 +341,7 @@ mod tests {
view_data.push_line(ViewLine::from("This is a line"));
view_data.push_trailing_line(ViewLine::from("This is a trailing line"));
view_data.set_view_size(30, 10);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let mut expected = vec![
"This is a leading line {HLINE| |30}",
"This is a line {HLINE| |30}",
@@ -362,7 +363,7 @@ mod tests {
view_data.push_line(ViewLine::from("This is line 4"));
view_data.push_trailing_line(ViewLine::from("This is a trailing line"));
view_data.set_view_size(30, 6);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let expected = vec![
"This is a leading line {HLINE| |30}",
"This is line 1 {HLINE| |30}",
@@ -387,7 +388,7 @@ mod tests {
view_data.push_line(ViewLine::from("This is line 5"));
view_data.push_trailing_line(ViewLine::from("This is a trailing line"));
view_data.set_view_size(30, 6);
- test_context.view.render(&view_data);
+ test_context.view.render(&view_data).unwrap();
let expected = vec![
"This is a leading line {HLINE| |30}",
"This is line 1 {HLINE| |30} ",