Organized the code in buffer/mode.rs a bit more nicely.

This commit is contained in:
Nathan Vegdahl 2015-01-10 12:02:29 -08:00
parent 8fd1659292
commit e61149e514
2 changed files with 129 additions and 98 deletions

View File

@ -33,6 +33,11 @@ impl Buffer {
}
//------------------------------------------------------------------------
// Functions for getting information about the buffer.
//------------------------------------------------------------------------
pub fn grapheme_count(&self) -> usize {
self.text.grapheme_count
}
@ -43,101 +48,10 @@ impl Buffer {
}
pub fn get_grapheme<'a>(&'a self, index: usize) -> &'a str {
if index >= self.grapheme_count() {
panic!("Buffer::get_grapheme(): index past last grapheme.");
}
else {
return self.text.get_grapheme_recursive(index);
}
}
pub fn get_grapheme_width(&self, index: usize, tab_width: usize) -> usize {
if index >= self.grapheme_count() {
panic!("Buffer::get_grapheme_width(): index past last grapheme.");
}
else {
return self.text.get_grapheme_width_recursive(index, tab_width);
}
}
pub fn get_line<'a>(&'a self, index: usize) -> &'a Line {
if index >= self.line_count() {
panic!("get_line(): index out of bounds.");
}
// NOTE: this can be done non-recursively, which would be more
// efficient. However, it seems likely to require unsafe code
// if done that way.
return self.text.get_line_recursive(index);
}
/// Blindly appends a line to the end of the current text without
/// doing any sanity checks. This is primarily for efficient
/// file loading.
pub fn append_line_unchecked(&mut self, line: Line) {
self.text.append_line_unchecked_recursive(line);
}
/// Removes the lines in line indices [line_a, line_b).
pub fn remove_lines(&mut self, line_a: usize, line_b: usize) {
// Nothing to do
if line_a == line_b {
return;
}
// Bounds error
else if line_a > line_b {
panic!("Buffer::remove_lines(): line_a must be less than or equal to line_b.");
}
// Bounds error
else if line_b > self.line_count() {
panic!("Buffer::remove_lines(): attempt to remove lines past the last line of text.");
}
// Complete removal of all lines
else if line_a == 0 && line_b == self.text.line_count {
let mut temp_node = BufferNode::new();
mem::swap(&mut (self.text), &mut temp_node);
}
// All other cases
else {
self.text.remove_lines_recursive(line_a, line_b);
self.text.set_last_line_ending_recursive();
}
}
pub fn pos_2d_to_closest_1d(&self, pos: (usize, usize)) -> usize {
return self.text.pos_2d_to_closest_1d_recursive(pos);
}
pub fn pos_vis_2d_to_closest_1d(&self, pos: (usize, usize), tab_width: usize) -> usize {
if pos.0 >= self.line_count() {
return self.grapheme_count();
}
else {
let gs = self.pos_2d_to_closest_1d((pos.0, 0));
let h = self.get_line(pos.0).vis_pos_to_closest_grapheme_index(pos.1, tab_width);
return gs + h;
}
}
pub fn pos_1d_to_closest_2d(&self, pos: usize) -> (usize, usize) {
return self.text.pos_1d_to_closest_2d_recursive(pos);
}
pub fn pos_1d_to_closest_vis_2d(&self, pos: usize, tab_width: usize) -> (usize, usize) {
let (v, h) = self.text.pos_1d_to_closest_2d_recursive(pos);
let vis_h = self.get_line(v).grapheme_index_to_closest_vis_pos(h, tab_width);
return (v, vis_h);
}
//------------------------------------------------------------------------
// Editing operations
//------------------------------------------------------------------------
/// Insert 'text' at grapheme position 'pos'.
pub fn insert_text(&mut self, text: &str, pos: usize) {
@ -189,6 +103,46 @@ impl Buffer {
}
/// Removes the lines in line indices [line_a, line_b).
pub fn remove_lines(&mut self, line_a: usize, line_b: usize) {
// Nothing to do
if line_a == line_b {
return;
}
// Bounds error
else if line_a > line_b {
panic!("Buffer::remove_lines(): line_a must be less than or equal to line_b.");
}
// Bounds error
else if line_b > self.line_count() {
panic!("Buffer::remove_lines(): attempt to remove lines past the last line of text.");
}
// Complete removal of all lines
else if line_a == 0 && line_b == self.text.line_count {
let mut temp_node = BufferNode::new();
mem::swap(&mut (self.text), &mut temp_node);
}
// All other cases
else {
self.text.remove_lines_recursive(line_a, line_b);
self.text.set_last_line_ending_recursive();
}
}
/// Blindly appends a line to the end of the current text without
/// doing any sanity checks. This is primarily for efficient
/// file loading.
pub fn append_line_unchecked(&mut self, line: Line) {
self.text.append_line_unchecked_recursive(line);
}
//------------------------------------------------------------------------
// Undo/redo functionality
//------------------------------------------------------------------------
/// Undoes operations that were pushed to the undo stack, and returns a
/// cursor position that the cursor should jump to, if any.
pub fn undo(&mut self) -> Option<usize> {
@ -212,6 +166,77 @@ impl Buffer {
}
//------------------------------------------------------------------------
// Position conversions
//------------------------------------------------------------------------
pub fn pos_2d_to_closest_1d(&self, pos: (usize, usize)) -> usize {
return self.text.pos_2d_to_closest_1d_recursive(pos);
}
pub fn pos_vis_2d_to_closest_1d(&self, pos: (usize, usize), tab_width: usize) -> usize {
if pos.0 >= self.line_count() {
return self.grapheme_count();
}
else {
let gs = self.pos_2d_to_closest_1d((pos.0, 0));
let h = self.get_line(pos.0).vis_pos_to_closest_grapheme_index(pos.1, tab_width);
return gs + h;
}
}
pub fn pos_1d_to_closest_2d(&self, pos: usize) -> (usize, usize) {
return self.text.pos_1d_to_closest_2d_recursive(pos);
}
pub fn pos_1d_to_closest_vis_2d(&self, pos: usize, tab_width: usize) -> (usize, usize) {
let (v, h) = self.text.pos_1d_to_closest_2d_recursive(pos);
let vis_h = self.get_line(v).grapheme_index_to_closest_vis_pos(h, tab_width);
return (v, vis_h);
}
//------------------------------------------------------------------------
// Text reading functions
//------------------------------------------------------------------------
pub fn get_grapheme<'a>(&'a self, index: usize) -> &'a str {
if index >= self.grapheme_count() {
panic!("Buffer::get_grapheme(): index past last grapheme.");
}
else {
return self.text.get_grapheme_recursive(index);
}
}
pub fn get_grapheme_width(&self, index: usize, tab_width: usize) -> usize {
if index >= self.grapheme_count() {
panic!("Buffer::get_grapheme_width(): index past last grapheme.");
}
else {
return self.text.get_grapheme_width_recursive(index, tab_width);
}
}
pub fn get_line<'a>(&'a self, index: usize) -> &'a Line {
if index >= self.line_count() {
panic!("get_line(): index out of bounds.");
}
// NOTE: this can be done non-recursively, which would be more
// efficient. However, it seems likely to require unsafe code
// if done that way.
return self.text.get_line_recursive(index);
}
/// Creates a String from the buffer text in grapheme range [pos_a, posb).
fn string_from_range(&self, pos_a: usize, pos_b: usize) -> String {
// Bounds checks
@ -241,6 +266,12 @@ impl Buffer {
return s;
}
//------------------------------------------------------------------------
// Iterator creators
//------------------------------------------------------------------------
/// Creates an iterator at the first character
pub fn grapheme_iter<'a>(&'a self) -> BufferGraphemeIter<'a> {
BufferGraphemeIter {

View File

@ -13,8 +13,8 @@
a 2d representation of the text, for which it needs that information to
know the relative positions of things.
- Editing (these are undoable):
- insert_text
- remove_text
//- insert_text
//- remove_text
- move_text
- Undo functionality:
- Undo
@ -23,8 +23,8 @@
- Op section end
- Info:
- byte_count (useful when saving the file)
- grapheme_count
- line_count
//- grapheme_count
//- line_count
- Position conversions:
- index -> line_col
- line_col -> index