use buffer::operation::Operation;
use buffer::{Buffer, Position, Range};
use std::clone::Clone;
#[derive(Clone)]
pub struct Insert {
content: String,
position: Position,
}
impl Operation for Insert {
fn run(&mut self, buffer: &mut Buffer) {
buffer.data.borrow_mut().insert(&self.content, &self.position);
buffer.clear_caches()
}
fn reverse(&mut self, buffer: &mut Buffer) {
let line_count = self.content.chars().filter(|&c| c == '\n').count() + 1;
let end_line = self.position.line + line_count - 1;
let end_offset = if line_count == 1 {
self.position.offset + self.content.chars().count()
} else {
match self.content.split("\n").last() {
Some(line) => line.chars().count(),
None => return,
}
};
let end_position = Position{
line: end_line,
offset: end_offset,
};
let range = Range::new(
self.position.clone(),
end_position
);
buffer.data.borrow_mut().delete(&range);
buffer.clear_caches()
}
fn clone_operation(&self) -> Box<Operation> {
Box::new(self.clone())
}
}
impl Insert {
pub fn new(content: String, position: Position) -> Insert {
Insert{ content: content, position: position }
}
}
impl Buffer {
pub fn insert(&mut self, data: &str) {
let mut op = Insert::new(data.to_string(), self.cursor.position.clone());
op.run(self);
match self.operation_group {
Some(ref mut group) => group.add(Box::new(op)),
None => self.history.add(Box::new(op)),
};
self.clear_caches();
}
}
#[cfg(test)]
mod tests {
use super::Insert;
use buffer::Buffer;
use buffer::position::Position;
use buffer::operation::Operation;
#[test]
fn run_and_reverse_add_and_remove_content_without_newlines_at_cursor_position() {
let mut buffer = Buffer::new();
buffer.insert(&"something");
let insert_position = Position{ line: 0, offset: 9 };
let mut insert_operation = Insert::new(" else".to_string(), insert_position);
insert_operation.run(&mut buffer);
assert_eq!(buffer.data(), "something else");
insert_operation.reverse(&mut buffer);
assert_eq!(buffer.data(), "something");
}
#[test]
fn run_and_reverse_add_and_remove_content_with_newlines_at_cursor_position() {
let mut buffer = Buffer::new();
buffer.insert(&"\n something");
let insert_position = Position{ line: 1, offset: 10 };
let mut insert_operation = Insert::new("\n else\n entirely".to_string(), insert_position);
insert_operation.run(&mut buffer);
assert_eq!(buffer.data(), "\n something\n else\n entirely");
insert_operation.reverse(&mut buffer);
assert_eq!(buffer.data(), "\n something");
}
#[test]
fn reverse_removes_a_newline() {
let mut buffer = Buffer::new();
let mut insert_operation = Insert::new("\n".to_string(), Position{ line: 0, offset: 0 });
insert_operation.run(&mut buffer);
assert_eq!(buffer.data(), "\n");
insert_operation.reverse(&mut buffer);
assert_eq!(buffer.data(), "");
}
#[test]
fn reverse_correctly_removes_line_ranges() {
let mut buffer = Buffer::new();
buffer.insert(&"scribe\nlibrary\n");
let mut insert_operation = Insert::new("editor\n".to_string(), Position{ line: 1, offset: 0 });
insert_operation.run(&mut buffer);
assert_eq!(buffer.data(), "scribe\neditor\nlibrary\n");
insert_operation.reverse(&mut buffer);
assert_eq!(buffer.data(), "scribe\nlibrary\n");
}
}