Commit 751d4da7 authored by AdminXVII's avatar AdminXVII

Extract display from movements

parent 75790748
Pipeline #4512 passed with stage
in 2 minutes
......@@ -98,7 +98,7 @@ pub struct Editor<'a, W: io::Write> {
// for Vi's normal mode.
pub no_eol: bool,
no_newline: bool,
pub no_newline: bool,
reverse_search: bool,
forward_search: bool,
......@@ -180,7 +180,8 @@ impl<'a, W: io::Write> Editor<'a, W> {
};
if !ed.new_buf.is_empty() {
ed.move_cursor_to_end_of_line()?;
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
}
ed.display()?;
Ok(ed)
......@@ -336,33 +337,30 @@ impl<'a, W: io::Write> Editor<'a, W> {
pub fn undo(&mut self) -> io::Result<bool> {
let did = cur_buf_mut!(self).undo();
if did {
self.move_cursor_to_end_of_line()?;
} else {
self.no_newline = true;
self.display()?;
self.move_cursor_to_end_of_line();
}
self.no_newline = true;
self.display()?;
Ok(did)
}
pub fn redo(&mut self) -> io::Result<bool> {
let did = cur_buf_mut!(self).redo();
if did {
self.move_cursor_to_end_of_line()?;
} else {
self.no_newline = true;
self.display()?;
self.move_cursor_to_end_of_line();
}
self.no_newline = true;
self.display()?;
Ok(did)
}
pub fn revert(&mut self) -> io::Result<bool> {
let did = cur_buf_mut!(self).revert();
if did {
self.move_cursor_to_end_of_line()?;
} else {
self.no_newline = true;
self.display()?;
self.move_cursor_to_end_of_line();
}
self.no_newline = true;
self.display()?;
Ok(did)
}
......@@ -381,7 +379,7 @@ impl<'a, W: io::Write> Editor<'a, W> {
let col_width = 2 + w as usize / cols;
let cols = max(1, w as usize / col_width);
let mut lines = completions.len() / cols;
let lines = completions.len() / cols;
let mut i = 0;
for (index, com) in completions.iter().enumerate() {
......@@ -580,7 +578,9 @@ impl<'a, W: io::Write> Editor<'a, W> {
_ => (),
}
}
self.move_cursor_to_end_of_line()
self.move_cursor_to_end_of_line();
self.no_newline = true;
self.display()
}
}
......@@ -610,7 +610,9 @@ impl<'a, W: io::Write> Editor<'a, W> {
_ => self.history_fresh = false,
}
}
self.move_cursor_to_end_of_line()
self.move_cursor_to_end_of_line();
self.no_newline = true;
self.display()
}
}
......@@ -619,12 +621,12 @@ impl<'a, W: io::Write> Editor<'a, W> {
self.hist_buf_valid = false;
if self.context.history.len() > 0 {
self.cur_history_loc = Some(0);
self.move_cursor_to_end_of_line()
self.move_cursor_to_end_of_line();
} else {
self.cur_history_loc = None;
self.no_newline = true;
self.display()
}
self.no_newline = true;
self.display()
}
/// Moves to the end of history (ie. the new buffer).
......@@ -632,11 +634,10 @@ impl<'a, W: io::Write> Editor<'a, W> {
self.hist_buf_valid = false;
if self.cur_history_loc.is_some() {
self.cur_history_loc = None;
self.move_cursor_to_end_of_line()
} else {
self.no_newline = true;
self.display()
self.move_cursor_to_end_of_line();
}
self.no_newline = true;
self.display()
}
/// Inserts a string directly after the cursor, moving the cursor to the right.
......@@ -738,20 +739,17 @@ impl<'a, W: io::Write> Editor<'a, W> {
/// Moves the cursor to the left by `count` characters.
/// The cursor will not go past the start of the buffer.
pub fn move_cursor_left(&mut self, mut count: usize) -> io::Result<()> {
pub fn move_cursor_left(&mut self, mut count: usize) {
if count > self.cursor {
count = self.cursor;
}
self.cursor -= count;
self.no_newline = true;
self.display()
}
/// Moves the cursor to the right by `count` characters.
/// The cursor will not go past the end of the buffer.
pub fn move_cursor_right(&mut self, mut count: usize) -> io::Result<()> {
pub fn move_cursor_right(&mut self, mut count: usize) {
{
let buf = cur_buf!(self);
......@@ -761,34 +759,25 @@ impl<'a, W: io::Write> Editor<'a, W> {
self.cursor += count;
}
self.no_newline = true;
self.display()
}
/// Moves the cursor to `pos`. If `pos` is past the end of the buffer, it will be clamped.
pub fn move_cursor_to(&mut self, pos: usize) -> io::Result<()> {
pub fn move_cursor_to(&mut self, pos: usize) {
self.cursor = pos;
let buf_len = cur_buf!(self).num_chars();
if self.cursor > buf_len {
self.cursor = buf_len;
}
self.no_newline = true;
self.display()
}
/// Moves the cursor to the start of the line.
pub fn move_cursor_to_start_of_line(&mut self) -> io::Result<()> {
pub fn move_cursor_to_start_of_line(&mut self) {
self.cursor = 0;
self.no_newline = true;
self.display()
}
/// Moves the cursor to the end of the line.
pub fn move_cursor_to_end_of_line(&mut self) -> io::Result<()> {
pub fn move_cursor_to_end_of_line(&mut self) {
self.cursor = cur_buf!(self).num_chars();
self.no_newline = true;
self.display()
}
pub fn cursor_is_at_end_of_line(&self) -> bool {
......@@ -827,7 +816,9 @@ impl<'a, W: io::Write> Editor<'a, W> {
}
}
self.clear_search();
self.move_cursor_to_end_of_line()
self.move_cursor_to_end_of_line();
self.no_newline = true;
self.display()
}
/// Returns current auto suggestion, for history search this is the current match if not
......@@ -1126,7 +1117,8 @@ mod tests {
let out = Vec::new();
let mut ed = Editor::new(out, "prompt".to_owned(), None, &mut context).unwrap();
ed.insert_str_after_cursor("delete all of this").unwrap();
ed.move_cursor_to_start_of_line().unwrap();
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.delete_all_after_cursor().unwrap();
ed.undo().unwrap();
assert_eq!(String::from(ed), "delete all of this");
......@@ -1140,7 +1132,8 @@ mod tests {
ed.insert_str_after_cursor("let").unwrap();
assert_eq!(ed.cursor, 3);
ed.move_cursor_left(1).unwrap();
ed.move_cursor_left(1);
ed.no_newline = true;
assert_eq!(ed.cursor, 2);
ed.insert_after_cursor('f').unwrap();
......@@ -1156,8 +1149,10 @@ mod tests {
ed.insert_str_after_cursor("right").unwrap();
assert_eq!(ed.cursor, 5);
ed.move_cursor_left(2).unwrap();
ed.move_cursor_right(1).unwrap();
ed.move_cursor_left(2);
ed.no_newline = true;
ed.move_cursor_right(1);
ed.no_newline = true;
assert_eq!(ed.cursor, 4);
}
......
......@@ -25,10 +25,29 @@ impl Emacs {
fn handle_ctrl_key<'a, W: Write>(&mut self, c: char, ed: &mut Editor<'a, W>) -> io::Result<()> {
match c {
'l' => ed.clear(),
'a' => ed.move_cursor_to_start_of_line(),
'e' => ed.move_cursor_to_end_of_line(),
'b' => ed.move_cursor_left(1),
'f' => ed.move_cursor_right(1),
'a' => {
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()
}
'e' => {
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
ed.display()
}
'b' => {
ed.move_cursor_left(1);
ed.no_newline = true;
ed.display()
}
'f' => {
ed.move_cursor_right(1);
ed.no_newline = true;
ed.display()
}
'd' => ed.delete_after_cursor(),
'p' => ed.move_up(),
'n' => ed.move_down(),
......@@ -48,8 +67,18 @@ impl Emacs {
'<' => ed.move_to_start_of_history(),
'>' => ed.move_to_end_of_history(),
'\x7F' => ed.delete_word_before_cursor(true),
'f' => emacs_move_word(ed, EmacsMoveDir::Right),
'b' => emacs_move_word(ed, EmacsMoveDir::Left),
'f' => {
emacs_move_word(ed, EmacsMoveDir::Right);
ed.no_newline = true;
ed.display()
}
'b' => {
emacs_move_word(ed, EmacsMoveDir::Left);
ed.no_newline = true;
ed.display()
}
'r' => {
ed.revert()?;
Ok(())
......@@ -110,12 +139,32 @@ impl KeyMap for Emacs {
Key::Char(c) => ed.insert_after_cursor(c),
Key::Alt(c) => self.handle_alt_key(c, ed),
Key::Ctrl(c) => self.handle_ctrl_key(c, ed),
Key::Left => ed.move_cursor_left(1),
Key::Right => ed.move_cursor_right(1),
Key::Left => {
ed.move_cursor_left(1);
ed.no_newline = true;
ed.display()
}
Key::Right => {
ed.move_cursor_right(1);
ed.no_newline = true;
ed.display()
}
Key::Up => ed.move_up(),
Key::Down => ed.move_down(),
Key::Home => ed.move_cursor_to_start_of_line(),
Key::End => ed.move_cursor_to_end_of_line(),
Key::Home => {
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()
}
Key::End => {
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
ed.display()
}
Key::Backspace => ed.delete_before_cursor(),
Key::Delete => ed.delete_after_cursor(),
Key::Null => Ok(()),
......@@ -130,7 +179,7 @@ enum EmacsMoveDir {
Right,
}
fn emacs_move_word<W: Write>(ed: &mut Editor<W>, direction: EmacsMoveDir) -> io::Result<()> {
fn emacs_move_word<W: Write>(ed: &mut Editor<W>, direction: EmacsMoveDir) {
let (words, pos) = ed.get_words_and_cursor_position();
let word_index = match pos {
......@@ -154,7 +203,7 @@ fn emacs_move_word<W: Write>(ed: &mut Editor<W>, direction: EmacsMoveDir) -> io:
};
match word_index {
None => Ok(()),
None => {}
Some(i) => {
let (start, end) = words[i];
......
......@@ -201,7 +201,9 @@ fn vi_move_word<W: Write>(
}
}
ed.move_cursor_to(cursor)
ed.move_cursor_to(cursor);
ed.no_newline = true;
ed.display()
}
fn move_to_end_of_word<W: Write>(ed: &mut Editor<W>, count: usize) -> io::Result<()> {
......@@ -278,7 +280,9 @@ fn vi_move_word_end<W: Write>(
}
}
ed.move_cursor_to(cursor)
ed.move_cursor_to(cursor);
ed.no_newline = true;
ed.display()
}
fn find_char(buf: &::buffer::Buffer, start: usize, ch: char, count: usize) -> Option<usize> {
......@@ -496,12 +500,28 @@ impl Vi {
) -> io::Result<()> {
match key {
Key::Ctrl('l') => ed.clear(),
Key::Left => ed.move_cursor_left(1),
Key::Right => ed.move_cursor_right(1),
Key::Left => {
ed.move_cursor_left(1);
ed.no_newline = true;
ed.display()
}
Key::Right => {
ed.move_cursor_right(1);
ed.no_newline = true;
ed.display()
}
Key::Up => ed.move_up(),
Key::Down => ed.move_down(),
Key::Home => ed.move_cursor_to_start_of_line(),
Key::End => ed.move_cursor_to_end_of_line(),
Key::Home => {
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()
}
Key::End => {
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
ed.display()
}
Key::Backspace => ed.delete_before_cursor(),
Key::Delete => ed.delete_after_cursor(),
Key::Null => Ok(()),
......@@ -528,7 +548,9 @@ impl Vi {
self.count = 0;
}
// cursor moves to the left when switching from insert to normal mode
ed.move_cursor_left(1)?;
ed.move_cursor_left(1);
ed.no_newline = true;
ed.display()?;
self.pop_mode(ed);
Ok(())
}
......@@ -606,17 +628,23 @@ impl Vi {
Key::Char('a') => {
self.last_insert = Some(key);
self.set_mode(Insert, ed);
ed.move_cursor_right(1)
ed.move_cursor_right(1);
ed.no_newline = true;
ed.display()
}
Key::Char('A') => {
self.last_insert = Some(key);
self.set_mode(Insert, ed);
ed.move_cursor_to_end_of_line()
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
ed.display()
}
Key::Char('I') => {
self.last_insert = Some(key);
self.set_mode(Insert, ed);
ed.move_cursor_to_start_of_line()
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()
}
Key::Char('s') => {
self.last_insert = Some(key);
......@@ -686,12 +714,16 @@ impl Vi {
}
Key::Char('h') | Key::Left | Key::Backspace => {
let count = self.move_count_left(ed);
ed.move_cursor_left(count)?;
ed.move_cursor_left(count);
ed.no_newline = true;
ed.display()?;
self.pop_mode_after_movement(Exclusive, ed)
}
Key::Char('l') | Key::Right | Key::Char(' ') => {
let count = self.move_count_right(ed);
ed.move_cursor_right(count)?;
ed.move_cursor_right(count);
ed.no_newline = true;
ed.display()?;
self.pop_mode_after_movement(Exclusive, ed)
}
Key::Char('k') | Key::Up => {
......@@ -756,7 +788,9 @@ impl Vi {
}
// if count is 0, 0 should move to start of line
Key::Char('0') if self.count == 0 => {
ed.move_cursor_to_start_of_line()?;
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()?;
self.pop_mode_after_movement(Exclusive, ed)
}
Key::Char(i @ '0'...'9') => {
......@@ -766,7 +800,9 @@ impl Vi {
Ok(())
}
Key::Char('$') => {
ed.move_cursor_to_end_of_line()?;
ed.move_cursor_to_end_of_line();
ed.no_newline = true;
ed.display()?;
self.pop_mode_after_movement(Exclusive, ed)
}
Key::Char('x') | Key::Delete => {
......@@ -802,7 +838,9 @@ impl Vi {
ed.insert_after_cursor(c)?;
}
} else {
ed.move_cursor_right(1)?;
ed.move_cursor_right(1);
ed.no_newline = true;
ed.display()?;
}
}
self.pop_mode(ed);
......@@ -857,7 +895,9 @@ impl Vi {
}
ed.current_buffer_mut().end_undo_group();
ed.move_cursor_left(1)?;
ed.move_cursor_left(1);
ed.no_newline = true;
ed.display()?;
}
self.pop_mode(ed);
}
......@@ -910,7 +950,9 @@ impl Vi {
// delete the whole line
self.count = 0;
self.secondary_count = 0;
ed.move_cursor_to_start_of_line()?;
ed.move_cursor_to_start_of_line();
ed.no_newline = true;
ed.display()?;
ed.delete_all_after_cursor()?;
// return to the previous mode
......@@ -971,28 +1013,44 @@ impl Vi {
RightUntil => {
move_type = Inclusive;
match find_char(ed.current_buffer(), ed.cursor() + 1, c, count) {
Some(i) => ed.move_cursor_to(i - 1),
Some(i) => {
ed.move_cursor_to(i - 1);
ed.no_newline = true;
ed.display()
}
None => Ok(()),
}
}
RightAt => {
move_type = Inclusive;
match find_char(ed.current_buffer(), ed.cursor() + 1, c, count) {
Some(i) => ed.move_cursor_to(i),
Some(i) => {
ed.move_cursor_to(i);
ed.no_newline = true;
ed.display()
}
None => Ok(()),
}
}
LeftUntil => {
move_type = Exclusive;
match find_char_rev(ed.current_buffer(), ed.cursor(), c, count) {
Some(i) => ed.move_cursor_to(i + 1),
Some(i) => {
ed.move_cursor_to(i + 1);
ed.no_newline = true;
ed.display()
}
None => Ok(()),
}
}
LeftAt => {
move_type = Exclusive;
match find_char_rev(ed.current_buffer(), ed.cursor(), c, count) {
Some(i) => ed.move_cursor_to(i),
Some(i) => {
ed.move_cursor_to(i);
ed.no_newline = true;
ed.display()
}
None => Ok(()),
}
}
......@@ -2464,7 +2522,8 @@ mod tests {
ed.insert_str_after_cursor(" som").unwrap();
let end_pos = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos);
......@@ -2483,7 +2542,8 @@ mod tests {
ed.insert_str_after_cursor(", som").unwrap();
let end_pos2 = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos1);
......@@ -2504,7 +2564,8 @@ mod tests {
ed.insert_str_after_cursor(",som").unwrap();
let end_pos2 = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos1);
......@@ -2526,7 +2587,8 @@ mod tests {
assert_eq!(ed.cursor(), 17);
ed.insert_str_after_cursor("e words").unwrap();
assert_eq!(ed.cursor(), 24);
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
assert_eq!(ed.cursor(), 8);
super::move_to_end_of_word(&mut ed, 1).unwrap();
......@@ -2546,7 +2608,8 @@ mod tests {
ed.insert_str_after_cursor(", som").unwrap();
let end_pos2 = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos1);
......@@ -2565,7 +2628,8 @@ mod tests {
ed.insert_str_after_cursor(" som").unwrap();
let end_pos = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos);
......@@ -2584,7 +2648,8 @@ mod tests {
ed.insert_str_after_cursor(", som").unwrap();
let end_pos2 = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos1);
......@@ -2603,7 +2668,8 @@ mod tests {
ed.insert_str_after_cursor("e,,,,som").unwrap();
let end_pos = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos);
}
......@@ -2619,7 +2685,8 @@ mod tests {
ed.insert_str_after_cursor(" som").unwrap();
let end_pos = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();
ed.move_cursor_to(start_pos);
ed.no_newline = true;
super::move_to_end_of_word_ws(&mut ed, 1).unwrap();
assert_eq!(ed.cursor(), end_pos);
......@@ -2638,7 +2705,8 @@ mod tests {
ed.insert_str_after_cursor(", som").unwrap();
let end_pos2 = ed.cursor();
ed.insert_str_after_cursor("e words").unwrap();
ed.move_cursor_to(start_pos).unwrap();