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;
use crate::list::line::Line;
use crate::process::exit_status::ExitStatus;
use crate::process::process_module::ProcessModule;
use crate::process::process_result::ProcessResult;
use crate::process::state::State;
use crate::todo_file::TodoFile;
use crate::view::line_segment::LineSegment;
use crate::view::view_data::ViewData;
use crate::view::view_line::ViewLine;
use crate::view::View;
use anyhow::{anyhow, Error, Result};
use std::ffi::OsString;
use std::process::Command;
use std::process::ExitStatus as ProcessExitStatus;
#[derive(Debug)]
enum ExternalEditorState {
Active,
Empty,
Error(Error),
}
pub struct ExternalEditor<'e> {
editor: String,
display: &'e Display<'e>,
state: ExternalEditorState,
view_data: ViewData,
invalid_selection: bool,
lines: Vec<Line>,
}
impl<'e> ProcessModule for ExternalEditor<'e> {
fn activate(&mut self, todo_file: &TodoFile, _: State) -> ProcessResult {
let mut result = ProcessResult::new();
self.state = ExternalEditorState::Active;
if let Err(err) = todo_file.write_file() {
result = result.error(err).state(State::List);
}
else if self.lines.is_empty() {
self.lines = todo_file.get_lines().to_owned();
}
result
}
fn deactivate(&mut self) {
self.lines.clear();
self.invalid_selection = false;
self.view_data.reset();
}
fn build_view_data(&mut self, view: &View<'_>, _: &TodoFile) -> &ViewData {
let (window_width, window_height) = view.get_view_size();
self.view_data.clear();
match self.state {
ExternalEditorState::Active => self.view_data.push_leading_line(ViewLine::from("Editing...")),
ExternalEditorState::Empty => {
self.view_data
.push_leading_line(ViewLine::from("The rebase file is empty."));
self.view_data.push_line(ViewLine::new_empty_line());
self.view_data.push_line(ViewLine::from("1) Abort rebase"));
self.view_data.push_line(ViewLine::from("2) Edit rebase file"));
self.view_data
.push_line(ViewLine::from("3) Undo modifications and edit rebase file"));
self.view_data.push_line(ViewLine::new_empty_line());
},
ExternalEditorState::Error(ref error) => {
for cause in error.chain() {
self.view_data.push_line(ViewLine::from(format!("{:#}", cause)));
}
self.view_data.push_line(ViewLine::new_empty_line());
self.view_data.push_line(ViewLine::from("1) Abort rebase"));
self.view_data.push_line(ViewLine::from("2) Edit rebase file"));
self.view_data
.push_line(ViewLine::from("3) Restore rebase file and abort edit"));
self.view_data
.push_line(ViewLine::from("4) Undo modifications and edit rebase file"));
self.view_data.push_line(ViewLine::new_empty_line());
},
}
match &self.state {
&ExternalEditorState::Active => {},
&ExternalEditorState::Empty | &ExternalEditorState::Error(_) => {
if self.invalid_selection {
self.view_data.push_line(ViewLine::from(LineSegment::new_with_color(
"Invalid option selected. Please choose an option.",
DisplayColor::IndicatorColor,
)));
}
else {
self.view_data.push_line(ViewLine::from(LineSegment::new_with_color(
"Please choose an option.",
DisplayColor::IndicatorColor,
)));
}
},
}
self.view_data.set_view_size(window_width, window_height);
self.view_data.rebuild();
&self.view_data
}
fn handle_input(
&mut self,
input_handler: &InputHandler<'_>,
todo_file: &mut TodoFile,
view: &View<'_>,
) -> ProcessResult
{
let mut result = ProcessResul