summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Oram <dev@mitmaro.ca>2019-06-17 18:58:54 -0230
committerGitHub <noreply@github.com>2019-06-17 18:58:54 -0230
commit9d30b910870aa8cac4d45b585c6f652be64d600f (patch)
tree2b987e656dbbf1f9242e1bf83e90512f399c900b
parent023c92bc6348a666b62e0b6d080361ae89b0250a (diff)
parent957a5d2dd8bc8eb38c88b1e7db7ac113c1e18c46 (diff)
Merge pull request #140 from MitMaro/tim/move-edit-into-module
Move edit into module
-rw-r--r--src/application.rs105
-rw-r--r--src/edit/edit.rs155
-rw-r--r--src/edit/mod.rs4
-rw-r--r--src/main.rs1
-rw-r--r--src/process/state.rs1
-rw-r--r--src/view/view.rs34
6 files changed, 172 insertions, 128 deletions
diff --git a/src/application.rs b/src/application.rs
index e91435d..63b2c37 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -3,6 +3,7 @@ use crate::git_interactive::GitInteractive;
use crate::config::Config;
use crate::constants::{LIST_HELP_LINES, VISUAL_MODE_HELP_LINES};
+use crate::edit::Edit;
use crate::input::{Input, InputHandler};
use crate::process::{
ExitStatus,
@@ -19,12 +20,10 @@ use crate::window::Window;
use core::borrow::Borrow;
use std::process::Command;
use std::process::ExitStatus as ProcessExitStatus;
-use unicode_segmentation::UnicodeSegmentation;
pub struct Application<'a> {
config: &'a Config,
- edit_content: String,
- edit_content_cursor: usize,
+ edit: Edit,
git_interactive: GitInteractive,
input_handler: &'a InputHandler<'a>,
show_commit: ShowCommit,
@@ -41,8 +40,7 @@ impl<'a> Application<'a> {
{
Self {
config,
- edit_content: String::from(""),
- edit_content_cursor: 0,
+ edit: Edit::new(),
git_interactive,
input_handler,
show_commit: ShowCommit::new(),
@@ -58,8 +56,7 @@ impl<'a> Application<'a> {
match state {
State::ConfirmAbort => {},
State::ConfirmRebase => {},
- State::Edit => {},
- State::EditFinish => {},
+ State::Edit => self.edit.activate(state, &self.git_interactive),
State::Error { .. } => {},
State::Exiting => {},
State::ExternalEditor(_) => {},
@@ -77,8 +74,7 @@ impl<'a> Application<'a> {
match state {
State::ConfirmAbort => {},
State::ConfirmRebase => {},
- State::Edit => {},
- State::EditFinish => {},
+ State::Edit => self.edit.deactivate(),
State::Error { .. } => {},
State::Exiting => {},
State::ExternalEditor(_) => {},
@@ -96,8 +92,7 @@ impl<'a> Application<'a> {
match state {
State::ConfirmAbort => ProcessResult::new(),
State::ConfirmRebase => ProcessResult::new(),
- State::Edit => ProcessResult::new(),
- State::EditFinish => self.process_edit_finish(),
+ State::Edit => self.edit.process(&mut self.git_interactive),
State::Error { .. } => ProcessResult::new(),
State::Exiting => ProcessResult::new(),
State::ExternalEditor(return_state) => self.process_external_editor(return_state.borrow()),
@@ -111,11 +106,6 @@ impl<'a> Application<'a> {
}
}
- pub fn process_edit_finish(&mut self) -> ProcessResult {
- self.git_interactive.edit_selected_line(self.edit_content.as_str());
- ProcessResultBuilder::new().state(State::List).build()
- }
-
pub fn process_external_editor(&mut self, return_state: &State) -> ProcessResult {
let mut result = ProcessResultBuilder::new();
@@ -174,8 +164,7 @@ impl<'a> Application<'a> {
match state {
State::ConfirmAbort => self.draw_confirm_abort(),
State::ConfirmRebase => self.draw_confirm_rebase(),
- State::Edit => self.draw_edit(),
- State::EditFinish => {},
+ State::Edit => self.edit.render(&self.view, &self.git_interactive),
State::Error { message, .. } => self.draw_error(message.as_str()),
State::Exiting => self.draw_exiting(),
State::ExternalEditor(_) => {},
@@ -215,11 +204,6 @@ impl<'a> Application<'a> {
);
}
- fn draw_edit(&self) {
- self.view
- .draw_edit(self.edit_content.as_str(), self.edit_content_cursor);
- }
-
fn draw_help(&self, help_state: &State) {
self.view.draw_help(
if *help_state == State::List {
@@ -247,16 +231,11 @@ impl<'a> Application<'a> {
self.input_handler.get_confirm()
}
- pub fn get_character(&self) -> Input {
- self.input_handler.get_character()
- }
-
pub fn handle_input(&mut self, state: State) -> HandleInputResult {
match state {
State::ConfirmAbort => self.handle_confirm_abort_input(),
State::ConfirmRebase => self.handle_confirm_rebase_input(),
- State::Edit => self.handle_edit(),
- State::EditFinish => HandleInputResult::new(Input::Other),
+ State::Edit => self.edit.handle_input(&self.input_handler, &mut self.git_interactive),
State::Error { return_state, .. } => self.handle_error_input(return_state.borrow()),
State::Exiting => HandleInputResult::new(Input::Other),
State::ExternalEditor(return_state) => self.handle_external_editor_input(return_state.borrow()),
@@ -368,72 +347,6 @@ impl<'a> Application<'a> {
result.build()
}
- fn handle_edit(&mut self) -> HandleInputResult {
- let mut input;
- let mut result;
- loop {
- input = self.get_character();
- result = HandleInputResultBuilder::new(input);
- match input {
- Input::Character(c) => {
- let start = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .take(self.edit_content_cursor)
- .collect::<String>();
- let end = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .skip(self.edit_content_cursor)
- .collect::<String>();
- self.edit_content = format!("{}{}{}", start, c, end);
- self.edit_content_cursor += 1;
- },
- Input::Backspace => {
- if self.edit_content_cursor == 0 {
- break;
- }
- let start = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .take(self.edit_content_cursor - 1)
- .collect::<String>();
- let end = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .skip(self.edit_content_cursor)
- .collect::<String>();
- self.edit_content = format!("{}{}", start, end);
- self.edit_content_cursor -= 1;
- },
- Input::Delete => {
- let length = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true).count();
- if self.edit_content_cursor == length {
- break;
- }
- let start = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .take(self.edit_content_cursor)
- .collect::<String>();
- let end = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true)
- .skip(self.edit_content_cursor + 1)
- .collect::<String>();
- self.edit_content = format!("{}{}", start, end);
- },
- Input::MoveCursorRight => {
- let length = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true).count();
- if self.edit_content_cursor < length {
- self.edit_content_cursor += 1;
- }
- },
- Input::MoveCursorLeft => {
- if self.edit_content_cursor != 0 {
- self.edit_content_cursor -= 1;
- }
- },
- Input::Enter => {
- result = result.state(State::EditFinish);
- },
- _ => {
- continue;
- },
- }
- break;
- }
- result.build()
- }
-
pub fn handle_error_input(&mut self, return_state: &State) -> HandleInputResult {
let input = self.get_input();
let mut result = HandleInputResultBuilder::new(input);
@@ -493,8 +406,6 @@ impl<'a> Application<'a> {
Input::ActionSquash => self.set_selected_line_action(Action::Squash),
Input::Edit => {
if *self.git_interactive.get_selected_line_action() == Action::Exec {
- self.edit_content = self.git_interactive.get_selected_line_edit_content().clone();
- self.edit_content_cursor = UnicodeSegmentation::graphemes(self.edit_content.as_str(), true).count();
result = result.state(State::Edit);
}
},
diff --git a/src/edit/edit.rs b/src/edit/edit.rs
new file mode 100644
index 0000000..e7a6fa9
--- /dev/null
+++ b/src/edit/edit.rs
@@ -0,0 +1,155 @@
+use crate::git_interactive::GitInteractive;
+use crate::input::{Input, InputHandler};
+use crate::process::{HandleInputResult, ProcessModule, ProcessResult, ProcessResultBuilder, State};
+use crate::view::View;
+use crate::window::WindowColor;
+use unicode_segmentation::UnicodeSegmentation;
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum EditState {
+ Active,
+ Finish,
+}
+
+pub struct Edit {
+ content: String,
+ cursor_position: usize,
+ state: EditState,
+}
+
+impl ProcessModule for Edit {
+ fn activate(&mut self, _state: State, application: &GitInteractive) {
+ self.state = EditState::Active;
+ self.content = application.get_selected_line_edit_content().clone();
+ self.cursor_position = UnicodeSegmentation::graphemes(self.content.as_str(), true).count();
+ }
+
+ fn deactivate(&mut self) {
+ self.content.clear();
+ self.cursor_position = 0;
+ }
+
+ fn process(&mut self, git_interactive: &mut GitInteractive) -> ProcessResult {
+ let mut result = ProcessResultBuilder::new();
+ match self.state {
+ EditState::Active => {},
+ EditState::Finish => {
+ git_interactive.edit_selected_line(self.content.as_str());
+ result = result.state(State::List);
+ },
+ };
+ result.build()
+ }
+
+ fn handle_input(
+ &mut self,
+ input_handler: &InputHandler,
+ _git_interactive: &mut GitInteractive,
+ ) -> HandleInputResult
+ {
+ if self.state == EditState::Finish {
+ return HandleInputResult::new(Input::Enter);
+ }
+ let mut input;
+ loop {
+ input = input_handler.get_character();
+ match input {
+ Input::Character(c) => {
+ let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .take(self.cursor_position)
+ .collect::<String>();
+ let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .skip(self.cursor_position)
+ .collect::<String>();
+ self.content = format!("{}{}{}", start, c, end);
+ self.cursor_position += 1;
+ },
+ Input::Backspace => {
+ if self.cursor_position == 0 {
+ break;
+ }
+ let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .take(self.cursor_position - 1)
+ .collect::<String>();
+ let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .skip(self.cursor_position)
+ .collect::<String>();
+ self.content = format!("{}{}", start, end);
+ self.cursor_position -= 1;
+ },
+ Input::Delete => {
+ let length = UnicodeSegmentation::graphemes(self.content.as_str(), true).count();
+ if self.cursor_position == length {
+ break;
+ }
+ let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .take(self.cursor_position)
+ .collect::<String>();
+ let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
+ .skip(self.cursor_position + 1)
+ .collect::<String>();
+ self.content = format!("{}{}", start, end);
+ },
+ Input::MoveCursorRight => {
+ let length = UnicodeSegmentation::graphemes(self.content.as_str(), true).count();
+ if self.cursor_position < length {
+ self.cursor_position += 1;
+ }
+ },
+ Input::MoveCursorLeft => {
+ if self.cursor_position != 0 {
+ self.cursor_position -= 1;
+ }
+ },
+ Input::Enter => self.state = EditState::Finish,
+ _ => {
+ continue;
+ },
+ }
+ break;
+ }
+ HandleInputResult::new(input)
+ }
+
+ fn render(&self, view: &View, _git_interactive: &GitInteractive) {
+ let line = self.content.as_str();
+ let pointer = self.cursor_position;
+
+ view.draw_title(false);
+ view.set_style(false, true, false);
+ view.set_color(WindowColor::Foreground);
+
+ // this could probably be made way more efficient
+ let graphemes = UnicodeSegmentation::graphemes(line, true);
+ let segment_length = graphemes.clone().count();
+ for (counter, c) in graphemes.enumerate() {
+ if counter == pointer {
+ view.set_style(false, true, false);
+ view.draw_str(c);
+ view.set_style(false, false, false);
+ }
+ else {
+ view.draw_str(c);
+ }
+ }
+ if pointer >= segment_length {
+ view.set_style(false, true, false);
+ view.draw_str(" ");
+ view.set_style(false, false, false);
+ }
+
+ view.draw_str("\n\n");
+ view.set_color(WindowColor::IndicatorColor);
+ view.draw_str("Enter to finish");
+ }
+}
+
+impl Edit {
+ pub fn new() -> Self {
+ Self {
+ content: String::from(""),
+ cursor_position: 0,
+ state: EditState::Active,
+ }
+ }
+}
diff --git a/src/edit/mod.rs b/src/edit/mod.rs
new file mode 100644
index 0000000..7083f01
--- /dev/null
+++ b/src/edit/mod.rs
@@ -0,0 +1,4 @@
+#[allow(clippy::module_inception)]
+mod edit;
+
+pub use self::edit::Edit;
diff --git a/src/main.rs b/src/main.rs
index 79854f5..07919cd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,6 +8,7 @@ mod color;
mod commit;
mod config;
mod constants;
+mod edit;
mod git_interactive;
mod input;
mod line;
diff --git a/src/process/state.rs b/src/process/state.rs
index 3d98c29..d750982 100644
--- a/src/process/state.rs
+++ b/src/process/state.rs
@@ -3,7 +3,6 @@ pub enum State {
ConfirmAbort,
ConfirmRebase,
Edit,
- EditFinish,
Error { return_state: Box<State>, message: String },
Exiting,
ExternalEditor(Box<State>),
diff --git a/src/view/view.rs b/src/view/view.rs
index 0ab26f9..93da142 100644
--- a/src/view/view.rs
+++ b/src/view/view.rs
@@ -28,7 +28,6 @@ use crate::view::{LineSegment, ViewLine};
use crate::window::Window;
use crate::window::WindowColor;
use std::cmp;
-use unicode_segmentation::UnicodeSegmentation;
pub struct View<'v> {
help_top: ScrollPosition,
@@ -53,6 +52,10 @@ impl<'v> View<'v> {
self.window.color(color);
}
+ pub fn set_style(&self, dim: bool, underline: bool, reverse: bool) {
+ self.window.set_style(dim, underline, reverse);
+ }
+
pub fn check_window_size(&self) -> bool {
let (window_width, window_height) = self.window.get_window_size();
!(window_width <= MINIMUM_COMPACT_WINDOW_WIDTH || window_height <= MINIMUM_WINDOW_HEIGHT)
@@ -408,33 +411,4 @@ impl<'v> View<'v> {
pub fn draw_exiting(&self) {
self.window.draw_str("Exiting...")
}
-
- pub fn draw_edit(&self, line: &str, pointer: usize) {
- self.draw_title(false);
- self.window.set_style(false, true, false);
- self.window.color(WindowColor::Foreground);
-
- // this could probably be made way more efficient
- let graphemes = UnicodeSegmentation::graphemes(line, true);
- let segment_length = graphemes.clone().count();
- for (counter, c) in graphemes.enumerate() {
- if counter == pointer {
- self.window.set_style(false, true, false);
- self.window.draw_str(c);
- self.window.set_style(false, false, false);
- }
- else {
- self.window.draw_str(c);
- }
- }
- if pointer >= segment_length {
- self.window.set_style(false, true, false);
- self.window.draw_str(" ");
- self.window.set_style(false, false, false);
- }
-
- self.window.draw_str("\n\n");
- self.window.color(WindowColor::IndicatorColor);
- self.window.draw_str("Enter to finish");
- }
}