summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Oram <dev@mitmaro.ca>2021-01-17 19:12:51 -0330
committerTim Oram <dev@mitmaro.ca>2021-01-27 19:03:19 -0330
commit65ffadbe8481cd1c852f585fe1e14820f2c74f67 (patch)
tree470d17b0bc9faca6726fbd0f0120f2735bd47013
parent8fd1c53e23d91ccb3051ab030042966eebe327f4 (diff)
Add mutable to curses
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--src/confirm_abort/mod.rs11
-rw-r--r--src/confirm_rebase/mod.rs6
-rw-r--r--src/display/mod.rs198
-rw-r--r--src/display/ncurses.rs20
-rw-r--r--src/display/size.rs19
-rw-r--r--src/display/testutil.rs16
-rw-r--r--src/display/virtual_curses.rs21
-rw-r--r--src/edit/mod.rs11
-rw-r--r--src/external_editor/mod.rs104
-rw-r--r--src/input/input_handler.rs47
-rw-r--r--src/list/mod.rs11
-rw-r--r--src/main.rs9
-rw-r--r--src/process/error.rs6
-rw-r--r--src/process/help.rs6
-rw-r--r--src/process/mod.rs14
-rw-r--r--src/process/modules.rs32
-rw-r--r--src/process/process_module.rs8
-rw-r--r--src/process/tests.rs80
-rw-r--r--src/process/testutil.rs22
-rw-r--r--src/process/window_size_error.rs6
-rw-r--r--src/show_commit/mod.rs6
-rw-r--r--src/view/mod.rs174
24 files changed, 385 insertions, 444 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9092cb8..acd451b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -135,6 +135,7 @@ dependencies = [
"clap",
"concat-idents",
"git2",
+ "lazy_static",
"num-format",
"pancurses",
"rstest",
diff --git a/Cargo.toml b/Cargo.toml
index 1c9ed58..1ab10e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -56,6 +56,7 @@ concat-idents = "1.1.2"
rstest = "0.6.4"
serial_test = "0.5.1"
tempfile = "3.2.0"
+lazy_static = "1.4.0"
[features]
default = []
diff --git a/src/confirm_abort/mod.rs b/src/confirm_abort/mod.rs
index d0a05ac..a6e7d6d 100644
--- a/src/confirm_abort/mod.rs
+++ b/src/confirm_abort/mod.rs
@@ -1,4 +1,4 @@
-use crate::input::input_handler::{InputHandler, InputMode};
+use crate::input::input_handler::InputMode;
use crate::input::Input;
use crate::process::exit_status::ExitStatus;
use crate::process::process_module::ProcessModule;
@@ -21,13 +21,8 @@ impl ProcessModule for ConfirmAbort {
&self.view_data
}
- fn handle_input(
- &mut self,
- input_handler: &InputHandler<'_>,
- rebase_todo: &mut TodoFile,
- _view: &View<'_>,
- ) -> ProcessResult {
- let input = input_handler.get_input(InputMode::Confirm);
+ fn handle_input(&mut self, view: &View<'_>, rebase_todo: &mut TodoFile) -> ProcessResult {
+ let input = view.get_input(InputMode::Confirm);
let mut result = ProcessResult::new().input(input);
match input {
Input::Yes => {
diff --git a/src/confirm_rebase/mod.rs b/src/confirm_rebase/mod.rs
index 362a515..7da9484 100644
--- a/src/confirm_rebase/mod.rs
+++ b/src/confirm_rebase/mod.rs
@@ -1,4 +1,4 @@
-use crate::input::input_handler::{InputHandler, InputMode};
+use crate::input::input_handler::InputMode;
use crate::input::Input;
use crate::process::exit_status::ExitStatus;
use crate::process::process_module::ProcessModule;
@@ -21,8 +21,8 @@ impl ProcessModule for ConfirmRebase {
&self.view_data
}
- fn handle_input(&mut self, input_handler: &InputHandler<'_>, _: &mut TodoFile, _view: &View<'_>) -> ProcessResult {
- let input = input_handler.get_input(InputMode::Confirm);
+ fn handle_input(&mut self, view: &View<'_>, _: &mut TodoFile) -> ProcessResult {
+ let input = view.get_input(InputMode::Confirm);
let mut result = ProcessResult::new().input(input);
match input {
Input::Yes => {
diff --git a/src/display/mod.rs b/src/display/mod.rs
index d8621b7..1d7fdfd 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -15,14 +15,17 @@ mod utils;
use crate::config::theme::Theme;
use crate::display::color_manager::ColorManager;
-use crate::display::curses::{chtype, Curses, Input, A_DIM, A_REVERSE, A_UNDERLINE};
+use crate::display::curses::{chtype, Curses, A_DIM, A_REVERSE, A_UNDERLINE};
use crate::display::display_color::DisplayColor;
pub use crate::display::size::Size;
+use crate::input::input_handler::{InputHandler, InputMode};
+use crate::input::Input;
use std::cell::RefCell;
use std::convert::TryInto;
pub struct Display<'d> {
- curses: &'d Curses,
+ curses: &'d mut Curses,
+ input_handler: InputHandler<'d>,
height: RefCell<usize>,
width: RefCell<usize>,
action_break: (chtype, chtype),
@@ -43,7 +46,7 @@ pub struct Display<'d> {
}
impl<'d> Display<'d> {
- pub(crate) fn new(curses: &'d mut Curses, theme: &'d Theme) -> Self {
+ pub(crate) fn new(input_handler: InputHandler<'d>, curses: &'d mut Curses, theme: &'d Theme) -> Self {
let mut color_manager = ColorManager::new();
let normal = color_manager.register_selectable_color_pairs(
curses,
@@ -135,10 +138,15 @@ impl<'d> Display<'d> {
theme.color_background,
theme.color_selected_background,
);
+
+ let height = curses.get_max_y().try_into().expect("Invalid window height");
+ let width = curses.get_max_x().try_into().expect("Invalid window height");
+
Self {
curses,
- height: RefCell::new(curses.get_max_y().try_into().expect("Invalid window height")),
- width: RefCell::new(curses.get_max_x().try_into().expect("Invalid window width")),
+ input_handler,
+ height: RefCell::new(height),
+ width: RefCell::new(width),
normal,
indicator,
action_break,
@@ -157,21 +165,21 @@ impl<'d> Display<'d> {
}
}
- pub(crate) fn draw_str(&self, s: &str) {
+ pub(crate) fn draw_str(&mut self, s: &str) {
self.curses.addstr(s);
}
- pub(crate) fn clear(&self) {
+ pub(crate) fn clear(&mut self) {
self.color(DisplayColor::Normal, false);
self.set_style(false, false, false);
self.curses.erase();
}
- pub(crate) fn refresh(&self) {
+ pub(crate) fn refresh(&mut self) {
self.curses.refresh();
}
- pub(crate) fn color(&self, color: DisplayColor, selected: bool) {
+ pub(crate) fn color(&mut self, color: DisplayColor, selected: bool) {
self.curses.attrset(
if selected {
match color {
@@ -214,13 +222,13 @@ impl<'d> Display<'d> {
);
}
- pub(crate) fn set_style(&self, dim: bool, underline: bool, reverse: bool) {
+ 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);
}
- fn set_dim(&self, on: bool) {
+ fn set_dim(&mut self, on: bool) {
if on {
self.curses.attron(A_DIM);
}
@@ -229,7 +237,7 @@ impl<'d> Display<'d> {
}
}
- fn set_underline(&self, on: bool) {
+ fn set_underline(&mut self, on: bool) {
// Windows uses blue text for underlined words
if !cfg!(windows) && on {
self.curses.attron(A_UNDERLINE);
@@ -239,7 +247,7 @@ impl<'d> Display<'d> {
}
}
- fn set_reverse(&self, on: bool) {
+ fn set_reverse(&mut self, on: bool) {
if on {
self.curses.attron(A_REVERSE);
}
@@ -248,44 +256,43 @@ impl<'d> Display<'d> {
}
}
- #[allow(clippy::unwrap_in_result)]
- pub(crate) fn getch(&self) -> Option<Input> {
- let input = self.curses.getch();
+ pub(crate) fn get_input(&self, mode: InputMode) -> Input {
+ self.curses.getch().map_or(Input::Other, |input| {
+ let input = self.input_handler.get_input(mode, input);
- if let Some(Input::KeyResize) = input {
- self.curses.resize_term(0, 0);
- self.height
- .replace(self.curses.get_max_y().try_into().expect("Invalid window height"));
- self.width
- .replace(self.curses.get_max_x().try_into().expect("Invalid window width"));
- }
- input
+ if input == Input::Resize {
+ self.curses.resize_term(0, 0);
+ self.height
+ .replace(self.curses.get_max_y().try_into().expect("Invalid window height"));
+ self.width
+ .replace(self.curses.get_max_x().try_into().expect("Invalid window width"));
+ }
+ input
+ })
}
pub(crate) fn get_window_size(&self) -> Size {
Size::new(*self.width.borrow(), *self.height.borrow())
}
- pub(crate) fn fill_end_of_line(&self) {
+ pub(crate) fn fill_end_of_line(&mut self) {
self.curses.hline(' ', self.curses.get_max_x());
}
- pub(crate) fn ensure_at_line_start(&self, y: i32) {
+ pub(crate) fn ensure_at_line_start(&mut self, y: i32) {
self.curses.mv(y, 0);
}
- pub(crate) fn move_from_end_of_line(&self, right: i32) {
+ pub(crate) fn move_from_end_of_line(&mut self, right: i32) {
self.curses.mv(self.curses.get_cur_y(), self.curses.get_max_x() - right);
}
- /// Leaves curses mode, runs the specified callback, and re-enables curses.
- pub(crate) fn leave_temporarily<F, T>(&self, callback: F) -> T
- where F: FnOnce() -> T {
+ pub(crate) fn def_prog_mode(&self) {
self.curses.def_prog_mode();
- self.curses.endwin();
- let rv = callback();
+ }
+
+ pub(crate) fn reset_prog_mode(&self) {
self.curses.reset_prog_mode();
- rv
}
pub(crate) fn end(&self) {
@@ -301,7 +308,7 @@ mod tests {
#[test]
#[serial_test::serial()]
fn windows_set_style_underline_disabled() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
let display = Display::new(&mut test_context.curses, &test_context.config.theme);
display.set_style(true, true, true);
assert!(test_context.curses.is_dimmed());
@@ -314,6 +321,7 @@ mod tests {
#[cfg(all(unix, test))]
mod tests {
use super::*;
+ use crate::display::curses::Input as CursesInput;
use crate::display::testutil::{display_module_test, TestContext};
use crate::display::virtual_curses::State;
use rstest::rstest;
@@ -321,10 +329,14 @@ mod tests {
#[test]
#[serial_test::serial]
fn draw_str() {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ display_module_test(|mut test_context: TestContext<'_>| {
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.draw_str("Test String");
- let output = test_context.curses.get_output();
+ let output = Curses::get_output();
assert_eq!(output, vec!["Test String"]);
});
}
@@ -332,15 +344,19 @@ mod tests {
#[test]
#[serial_test::serial]
fn clear() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
test_context.curses.addstr("Test String");
test_context.curses.attron(curses::A_DIM);
test_context.curses.attron(curses::A_REVERSE);
test_context.curses.attron(curses::A_UNDERLINE);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.clear();
- assert!(test_context.curses.get_output().is_empty());
+ assert!(Curses::get_output().is_empty());
assert!(!test_context.curses.is_dimmed());
assert!(!test_context.curses.is_reverse());
assert!(!test_context.curses.is_underline());
@@ -350,8 +366,12 @@ mod tests {
#[test]
#[serial_test::serial]
fn reset() {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ display_module_test(|mut test_context: TestContext<'_>| {
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.refresh();
assert_eq!(test_context.curses.get_state(), State::Refreshed);
});
@@ -394,8 +414,12 @@ mod tests {
)]
#[serial_test::serial()]
fn color(display_color: DisplayColor, selected: bool, expected: chtype) {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ display_module_test(|mut test_context: TestContext<'_>| {
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.color(display_color, selected);
assert!(test_context.curses.is_color_enabled(expected));
});
@@ -416,8 +440,12 @@ mod tests {
)]
#[serial_test::serial()]
fn style(dim: bool, underline: bool, reverse: bool) {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ display_module_test(|mut test_context: TestContext<'_>| {
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.set_style(dim, underline, reverse);
assert_eq!(test_context.curses.is_dimmed(), dim);
assert_eq!(test_context.curses.is_underline(), underline);
@@ -428,20 +456,28 @@ mod tests {
#[test]
#[serial_test::serial]
fn getch_normal_input() {
- display_module_test(|mut test_context: TestContext| {
- test_context.curses.set_inputs(vec![Input::Character('z')]);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
- assert_eq!(display.getch().unwrap(), Input::Character('z'));
+ display_module_test(|mut test_context: TestContext<'_>| {
+ test_context.curses.set_inputs(vec![CursesInput::Character('z')]);
+ let display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
+ assert_eq!(display.get_input(InputMode::Default), Input::Character('z'));
});
}
#[test]
#[serial_test::serial]
- fn getch_resize() {
- display_module_test(|mut test_context: TestContext| {
- test_context.curses.set_inputs(vec![Input::KeyResize]);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
- assert_eq!(display.getch().unwrap(), Input::KeyResize);
+ fn get_input_resize() {
+ display_module_test(|mut test_context: TestContext<'_>| {
+ test_context.curses.set_inputs(vec![CursesInput::KeyResize]);
+ let display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
+ assert_eq!(display.get_input(InputMode::Default), Input::Resize);
assert_eq!(test_context.curses.get_state(), State::Resized);
});
}
@@ -449,9 +485,13 @@ mod tests {
#[test]
#[serial_test::serial]
fn get_window_size() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
test_context.curses.resize_term(10, 12);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ let display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
assert_eq!(display.get_window_size(), Size::new(12, 10));
});
}
@@ -459,21 +499,29 @@ mod tests {
#[test]
#[serial_test::serial]
fn fill_end_of_line() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
test_context.curses.resize_term(10, 23);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.fill_end_of_line();
- assert_eq!(test_context.curses.get_output()[0], "{HLINE| |23}");
+ assert_eq!(Curses::get_output()[0], "{HLINE| |23}");
});
}
#[test]
#[serial_test::serial]
fn ensure_at_line_start() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
test_context.curses.resize_term(5, 25);
test_context.curses.mv(10, 12);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.ensure_at_line_start(5);
assert_eq!(test_context.curses.get_cur_y(), 5);
assert_eq!(test_context.curses.get_cur_x(), 0);
@@ -483,10 +531,14 @@ mod tests {
#[test]
#[serial_test::serial]
fn move_from_end_of_line() {
- display_module_test(|mut test_context: TestContext| {
+ display_module_test(|mut test_context: TestContext<'_>| {
test_context.curses.resize_term(5, 25);
test_context.curses.mv(5, 20);
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ let mut display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.move_from_end_of_line(5);
assert_eq!(test_context.curses.get_cur_x(), 20);
});
@@ -494,19 +546,13 @@ mod tests {
#[test]
#[serial_test::serial]
- fn leave_temporarily() {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
- assert_eq!(display.leave_temporarily(|| "Done"), "Done");
- assert_eq!(test_context.curses.get_state(), State::Normal);
- });
- }
-
- #[test]
- #[serial_test::serial]
fn end() {
- display_module_test(|mut test_context: TestContext| {
- let display = Display::new(&mut test_context.curses, &test_context.config.theme);
+ display_module_test(|mut test_context: TestContext<'_>| {
+ let display = Display::new(
+ test_context.input_handler,
+ &mut test_context.curses,
+ &test_context.config.theme,
+ );
display.end();
assert_eq!(test_context.curses.get_state(), State::Ended);
});
diff --git a/src/display/ncurses.rs b/src/display/ncurses.rs
index 731e592..bac101f 100644
--- a/src/display/ncurses.rs
+++ b/src/display/ncurses.rs
@@ -50,12 +50,12 @@ impl Curses {
}
#[allow(clippy::unused_self)]
- pub(super) fn init_color(&self, index: i16, red: i16, green: i16, blue: i16) {
+ pub(super) fn init_color(&mut self, index: i16, red: i16, green: i16, blue: i16) {
pancurses::init_color(index, red, green, blue);
}
#[allow(clippy::unused_self)]
- pub(super) fn init_color_pair(&self, index: i16, foreground: i16, background: i16) -> chtype {
+ pub(super) fn init_color_pair(&mut self, index: i16, foreground: i16, background: i16) -> chtype {
pancurses::init_pair(index, foreground, background);
// curses seems to init a pair for i16 but read with u64
pancurses::COLOR_PAIR(index as chtype)
@@ -65,27 +65,27 @@ impl Curses {
&self.color_mode
}
- pub(super) fn erase(&self) {
+ pub(super) fn erase(&mut self) {
self.window.erase();
}
- pub(super) fn refresh(&self) {
+ pub(super) fn refresh(&mut self) {
self.window.refresh();
}
- pub(super) fn addstr(&self, s: &str) {
+ pub(super) fn addstr(&mut self, s: &str) {
self.window.addstr(s);
}
- pub(super) fn attrset<T: Into<chtype>>(&self, attributes: T) {
+ pub(super) fn attrset<T: Into<chtype>>(&mut self, attributes: T) {
self.window.attrset(attributes);
}
- pub(super) fn attron<T: Into<chtype>>(&self, attributes: T) {
+ pub(super) fn attron<T: Into<chtype>>(&mut self, attributes: T) {
self.window.attron(attributes);
}
- pub(super) fn attroff<T: Into<chtype>>(&self, attributes: T) {
+ pub(super) fn attroff<T: Into<chtype>>(&mut self, attributes: T) {
self.window.attroff(attributes);
}
@@ -105,11 +105,11 @@ impl Curses {
self.window.get_max_x()
}
- pub(crate) fn hline(&self, ch: char, width: i32) {
+ pub(crate) fn hline(&mut self, ch: char, width: i32) {
self.window.hline(ch, width);
}
- pub(crate) fn mv(&self, y: i32, x: i32) {
+ pub(crate) fn mv(&mut self, y: i32, x: i32) {
self.window.mv(y, x);
}
diff --git a/src/display/size.rs b/src/display/size.rs
new file mode 100644
index 0000000..7509f48
--- /dev/null
+++ b/src/display/size.rs
@@ -0,0 +1,19 @@
+#[derive(Debug, PartialEq)]
+pub struct Size {
+ width: usize,
+ height: usize,
+}
+
+impl Size {
+ pub const fn new(width: usize, height: usize) -> Self {
+ Self { width, height }
+ }
+
+ pub const fn width(&self) -> usize {
+ self.width
+ }
+
+ pub const fn height(&self) -> usize {
+ self.height
+ }
+}
diff --git a/src/display/testutil.rs b/src/display/testutil.rs
index 3b1ddfe..e0d9e2f 100644
--- a/src/display/testutil.rs
+++ b/src/display/testutil.rs
@@ -1,15 +1,17 @@
use crate::config::Config;
use crate::display::curses::Curses;
+use crate::input::input_handler::InputHandler;
use std::env::set_var;
use std::path::Path;
-pub struct TestContext {
- pub config: Config,
+pub struct TestContext<'t> {
+ pub config: &'t Config,
pub curses: Curses,
+ pub input_handler: InputHandler<'t>,
}
pub fn display_module_test<F>(callback: F)
-where F: FnOnce(TestContext) {
+where F: FnOnce(TestContext<'_>) {
set_var(
"GIT_DIR",
Path::new(env!("CARGO_MANIFEST_DIR"))
@@ -21,5 +23,11 @@ where F: FnOnce(TestContext) {
);
let config = Config::new().unwrap();
let curses = Curses::new();
- callback(TestContext { config, curses });
+ curses.erase();
+ let input_handler = InputHandler::new(&config.key_bindings);
+ callback(TestContext {
+ config: &config,
+ curses,
+ input_handler,
+ });
}
diff --git a/src/display/virtual_curses.rs b/src/display/virtual_curses.rs
index 39d2d63..6497de0 100644
--- a/src/display/virtual_curses.rs
+++ b/src/display/virtual_curses.rs
@@ -1,7 +1,9 @@
use crate::display::color_mode::ColorMode;
use crate::display::utils::detect_color_mode;
+use lazy_static::lazy_static;
pub use pancurses::{chtype, Input};
use std::cell::RefCell;
+use std::sync::Mutex;
pub const A_DIM: chtype = 64;
pub const A_REVERSE: chtype = 128;
@@ -15,6 +17,10 @@ pub const COLOR_MAGENTA: i16 = 5;
pub const COLOR_CYAN: i16 = 6;
pub const COLOR_WHITE: i16 = 7;
+lazy_static! {
+ static ref OUTPUT: Mutex<Vec<String>> = Mutex::new(vec![]);
+}
+
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum State {
Normal,
@@ -30,7 +36,6 @@ pub struct Curses {
color_pairs: [(i16, i16); 255],
colors: [(i16, i16, i16); 255],
input: RefCell<Vec<Input>>,
- output: RefCell<Vec<String>>,
position: RefCell<(i32, i32)>,
size: RefCell<(i32, i32)>,
state: RefCell<State>,
@@ -44,7 +49,6 @@ impl Curses {
color_pairs: [(0, 0); 255],
colors: [(0, 0, 0); 255],
input: RefCell::new(vec![Input::KeyExit]),
- output: RefCell::new(vec![]),
position: RefCell::new((0, 0)),
size: RefCell::new((10, 10)),
state: RefCell::new(State::Normal),
@@ -57,8 +61,8 @@ impl Curses {
&self.colors
}
- pub(crate) fn get_output(&self) -> Vec<String> {
- self.output.borrow().clone()
+ pub(crate) fn get_output() -> Vec<String> {
+ OUTPUT.lock().unwrap().clone()
}
pub(crate) const fn get_color_pairs(&self) -> &[(i16, i16); 255] {
@@ -109,16 +113,18 @@ impl Curses {
&self.color_mode
}
+ #[allow(clippy::unused_self)]
pub(super) fn erase(&self) {
- self.output.borrow_mut().clear();
+ OUTPUT.lock().unwrap().clear();
}
pub(super) fn refresh(&self) {
self.state.replace(State::Refreshed);
}
+ #[allow(clippy::unused_self)]
pub(super) fn addstr(&self, s: &str) {
- self.output.borrow_mut().push(String::from(s));
+ OUTPUT.lock().unwrap().push(String::from(s));
}
pub(super) fn attrset<T: Into<chtype>>(&self, attributes: T) {
@@ -158,8 +164,9 @@ impl Curses {
(*self.size.borrow()).1
}
+ #[allow(clippy::unused_self)]
pub(crate) fn hline(&self, ch: char, width: i32) {
- self.output.borrow_mut().push(format!("{{HLINE|{}|{}}}", ch, width));
+ OUTPUT.lock().unwrap().push(format!("{{HLINE|{}|{}}}", ch, width));
}
pub(crate) fn mv(&self, y: i32, x: i32) {
diff --git a/src/edit/mod.rs b/src/edit/mod.rs
index fc67f50..8ea6b47 100644
--- a/src/edit/mod.rs
+++ b/src/edit/mod.rs
@@ -1,5 +1,5 @@
use crate::display::display_color::DisplayColor;
-use crate::input::input_handler::{InputHandler, InputMode};
+use crate::input::input_handler::InputMode;
use crate::input::Input;
use crate::process::process_module::ProcessModule;
use crate::process::process_result::ProcessResult;
@@ -70,14 +70,9 @@ impl ProcessModule for Edit {
&self.view_data
}
- fn handle_input(
- &mut self,
- input_handler: &InputHandler<'_>,
- todo_file: &mut TodoFile,
- view: &View<'_>,
- ) -> ProcessResult {
+ fn handle_input(&mut self, view: &View<'_>, todo_file: &mut TodoFile) -> ProcessResult {
let result = loop {
- let input = input_handler.get_input(InputMode::Raw);
+ let input = view.get_input(InputMode::Raw);
let result = ProcessResult::new().input(input);
match input {
Input::Character(c) => {
diff --git a/src/external_editor/mod.rs b/src/external_editor/mod.rs
index f61973f..3a0d5e1 100644
--- a/src/external_editor/mod.rs
+++ b/src/external_editor/mod.rs
@@ -1,9 +1,8 @@
mod argument_tolkenizer;
use crate::display::display_color::DisplayColor;
-use crate::display::Display;
use crate::external_editor::argument_tolkenizer::tolkenize;
-use crate::input::input_handler::{InputHandler, InputMode};
+use crate::input::input_handler::InputMode;
use crate::input::Input;
use crate::process::exit_status::ExitStatus;
use crate::process::process_module::ProcessModule;
@@ -27,16 +26,15 @@ enum ExternalEditorState {
Error(Error),
}
-pub struct ExternalEditor<'e> {
+pub struct ExternalEditor {
editor: String,
- display: &'e Display<'e>,
state: ExternalEditorState,
view_data: ViewData,
invalid_selection: bool,
lines: Vec<Line>,
}
-impl<'e> ProcessModule for ExternalEditor<'e> {
+impl ProcessModule for ExternalEditor {
fn activate(&mut self, todo_file: &TodoFile, _: State) -> ProcessResult {
let mut result = ProcessResult::new();
self.state = ExternalEditorState::Active;
@@ -110,16 +108,11 @@ impl<'e> ProcessModule for ExternalEditor<'e> {
&self.view_data
}
- fn handle_input(
- &mut self,
- input_handler: &InputHandler<'_>,
- todo_file: &mut TodoFile,
- view: &View<'_>,
- ) -> ProcessResult {
+ fn handle_input(&mut self, view: &View<'_>, todo_file: &mut TodoFile) -> ProcessResult {
let mut result = ProcessResult::new();
match self.state {
ExternalEditorState::Active => {
- if let Err(e) = self.run_editor(todo_file) {
+ if let Err(e) = self.run_editor(view, todo_file) {
self.state = ExternalEditorState::Error(e);
}
else {
@@ -138,7 +131,7 @@ impl<'e> ProcessModule for ExternalEditor<'e> {
result = result.input(Input::Other);
},
ExternalEditorState::Empty => {
- let input = input_handler.get_input(InputMode::Default);
+ let input = view.get_input(InputMode::Default);
result = result.input(input);
if let Some(input) = self.handle_standard_inputs(view, input) {
self.invalid_selection = false;
@@ -154,7 +147,7 @@ impl<'e> ProcessModule for ExternalEditor<'e> {
}
},
ExternalEditorState::Error(_) => {
- let input = input_handler.get_input(InputMode::Default);
+ let input = view.get_input(InputMode::Default);
result = result.input(input);
if let Some(input) = self.handle_standard_inputs(view, input) {
self.invalid_selection = false;
@@ -184,14 +177,13 @@ impl<'e> ProcessModule for ExternalEditor<'e> {
}
}
-impl<'e> ExternalEditor<'e> {
- pub(crate) fn new(display: &'e Display<'_>, editor: &str) -> Self {
+impl ExternalEditor {
+ pub(crate) fn new(editor: &str) -> Self {
let mut view_data = ViewData::new();
view_data.set_show_title(true);
Self {
editor: String::from(editor),
- display,
state: ExternalEditorState::Active,
view_data,
invalid_selection: false,
@@ -215,7 +207,7 @@ impl<'e> ExternalEditor<'e> {
None
}
- fn run_editor(&mut self, todo_file: &TodoFile) -> Result<()> {
+ fn run_editor(&mut self, view: &View<'_>, todo_file: &TodoFile) -> Result<()> {
let mut arguments = tolkenize(self.editor.as_str())
.map_or(Err(anyhow!("Invalid editor: \"{}\"", self.editor)), |args| {
if args.is_empty() {
@@ -245,7 +237,7 @@ impl<'e> ExternalEditor<'e> {
}
cmd.status().map_err(|e| anyhow!(e).context("Unable to run editor"))
};
- let exit_status: ProcessExitStatus = self.display.leave_temporarily(callback)?;
+ let exit_status: ProcessExitStatus = view.leave_temporarily(callback)?;
if !exit_status.success() {
return Err(anyhow!("Editor returned a non-zero exit status"));
@@ -319,10 +311,7 @@ mod te