Repeated insert and replace char
diff --git a/src/lib.rs b/src/lib.rs
index 1b0c625..52a0bc7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -309,9 +309,9 @@
/// Insert the character `ch` at cursor current position.
fn edit_insert(s: &mut State, ch: char, count: u16) -> Result<()> {
- if let Some(push) = s.line.insert(ch) {
+ if let Some(push) = s.line.insert(ch, count) {
if push {
- if s.cursor.col + ch.width().unwrap_or(0) < s.cols {
+ if count == 1 && s.cursor.col + ch.width().unwrap_or(0) < s.cols {
// Avoid a full update of the line in the trivial case.
let cursor = calculate_position(&s.line[..s.line.pos()], s.prompt_size, s.cols);
s.cursor = cursor;
@@ -327,6 +327,17 @@
}
}
+/// Replace a single (or count) character(s) under the cursor (Vi mode)
+fn edit_replace_char(s: &mut State, ch: char, count: u16) -> Result<()> {
+ if s.line.delete(count) {
+ s.line.insert(ch, count);
+ s.line.move_left(1);
+ s.refresh_line()
+ } else {
+ Ok(())
+ }
+}
+
// Yank/paste `text` at current position.
fn edit_yank(s: &mut State, text: &str, anchor: Anchor, count: u16) -> Result<()> {
if s.line.yank(text, anchor, count).is_some() {
@@ -874,9 +885,7 @@
}
Cmd::Replace(count, c) => {
editor.kill_ring.reset();
- try!(edit_delete(&mut s, count));
- try!(edit_insert(&mut s, c, count));
- try!(edit_move_left(&mut s, 1))
+ try!(edit_replace_char(&mut s, c, count));
}
Cmd::EndOfFile => {
editor.kill_ring.reset();
diff --git a/src/line_buffer.rs b/src/line_buffer.rs
index bd05986..fa113d0 100644
--- a/src/line_buffer.rs
+++ b/src/line_buffer.rs
@@ -1,4 +1,5 @@
//! Line buffer with current cursor position
+use std::iter;
use std::ops::{Deref, Range};
use keymap::{Anchor, At, CharSearch, Word};
@@ -108,16 +109,25 @@
/// and advance cursor position accordingly.
/// Return `None` when maximum buffer size has been reached,
/// `true` when the character has been appended to the end of the line.
- pub fn insert(&mut self, ch: char) -> Option<bool> {
- let shift = ch.len_utf8();
+ pub fn insert(&mut self, ch: char, count: u16) -> Option<bool> {
+ let shift = ch.len_utf8() * count as usize;
if self.buf.len() + shift > self.buf.capacity() {
return None;
}
let push = self.pos == self.buf.len();
if push {
- self.buf.push(ch);
+ self.buf.reserve(shift);
+ for _ in 0..count {
+ self.buf.push(ch);
+ }
} else {
- self.buf.insert(self.pos, ch);
+ if count == 1 {
+ self.buf.insert(self.pos, ch);
+ } else {
+ let text = iter::repeat(ch).take(count as usize).collect::<String>();
+ let pos = self.pos;
+ self.insert_str(pos, &text);
+ }
}
self.pos += shift;
Some(push)
@@ -195,15 +205,6 @@
}
}
- /// Replace a single character under the cursor (Vi mode)
- pub fn replace_char(&mut self, ch: char) -> Option<bool> {
- if self.delete(1) {
- self.insert(ch)
- } else {
- None
- }
- }
-
/// Delete the character at the right of the cursor without altering the cursor
/// position. Basically this is what happens with the "Delete" keyboard key.
pub fn delete(&mut self, count: u16) -> bool {
@@ -639,18 +640,18 @@
#[test]
fn insert() {
let mut s = LineBuffer::with_capacity(MAX_LINE);
- let push = s.insert('α').unwrap();
+ let push = s.insert('α', 1).unwrap();
assert_eq!("α", s.buf);
assert_eq!(2, s.pos);
assert_eq!(true, push);
- let push = s.insert('ß').unwrap();
+ let push = s.insert('ß', 1).unwrap();
assert_eq!("αß", s.buf);
assert_eq!(4, s.pos);
assert_eq!(true, push);
s.pos = 0;
- let push = s.insert('γ').unwrap();
+ let push = s.insert('γ', 1).unwrap();
assert_eq!("γαß", s.buf);
assert_eq!(2, s.pos);
assert_eq!(false, push);