Reorganized the code a bit, and started updating unit tests.

This commit is contained in:
Nathan Vegdahl 2015-01-25 13:20:16 -08:00
parent 518b9a7e42
commit 0557f5f6ce
9 changed files with 160 additions and 108 deletions

View File

@ -0,0 +1,61 @@
use buffer::line::Line;
use std::cmp::min;
#[derive(Copy, PartialEq)]
pub enum RoundingBehavior {
Round,
Floor,
Ceiling,
}
pub trait LineFormatter {
fn single_line_height(&self) -> usize;
fn dimensions(&self, line: &Line) -> (usize, usize);
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize);
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize;
}
//================================================================
// A simple implementation of LineFormatter, for testing purposes
//================================================================
pub struct TestLineFormatter {
tab_width: u8
}
impl TestLineFormatter {
pub fn new() -> TestLineFormatter {
TestLineFormatter {
tab_width: 4,
}
}
}
impl LineFormatter for TestLineFormatter {
fn single_line_height(&self) -> usize {
1
}
fn dimensions(&self, line: &Line) -> (usize, usize) {
(1, line.grapheme_count())
}
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize) {
(0, min(line.grapheme_count(), index))
}
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize {
if v2d.0 > 0 {
line.grapheme_count()
}
else {
min(line.grapheme_count(), v2d.1)
}
}
}

View File

@ -6,10 +6,11 @@ use self::line::{Line, LineEnding};
use self::node::{BufferNode, BufferNodeGraphemeIter, BufferNodeLineIter}; use self::node::{BufferNode, BufferNodeGraphemeIter, BufferNodeLineIter};
use self::undo_stack::{UndoStack}; use self::undo_stack::{UndoStack};
use self::undo_stack::Operation::*; use self::undo_stack::Operation::*;
use line_formatter::{LineFormatter, RoundingBehavior}; use self::line_formatter::{LineFormatter, RoundingBehavior};
use string_utils::{is_line_ending, grapheme_count}; use string_utils::{is_line_ending, grapheme_count};
pub mod line; pub mod line;
pub mod line_formatter;
mod node; mod node;
mod undo_stack; mod undo_stack;
@ -503,11 +504,12 @@ impl<'a> Iterator for BufferLineIter<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::line_formatter::TestLineFormatter;
use super::{Buffer, BufferGraphemeIter, BufferLineIter}; use super::{Buffer, BufferGraphemeIter, BufferLineIter};
#[test] #[test]
fn insert_text() { fn insert_text() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello 世界!", 0); buf.insert_text("Hello 世界!", 0);
@ -530,7 +532,7 @@ mod tests {
#[test] #[test]
fn insert_text_with_newlines() { fn insert_text_with_newlines() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
@ -555,7 +557,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_1() { fn insert_text_in_non_empty_buffer_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("Again ", 0); buf.insert_text("Again ", 0);
@ -587,7 +589,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_2() { fn insert_text_in_non_empty_buffer_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text(" again", 5); buf.insert_text(" again", 5);
@ -619,7 +621,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_3() { fn insert_text_in_non_empty_buffer_3() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("again", 6); buf.insert_text("again", 6);
@ -650,7 +652,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_4() { fn insert_text_in_non_empty_buffer_4() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("again", 11); buf.insert_text("again", 11);
@ -681,7 +683,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_5() { fn insert_text_in_non_empty_buffer_5() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("again", 2); buf.insert_text("again", 2);
@ -713,7 +715,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_6() { fn insert_text_in_non_empty_buffer_6() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("again", 8); buf.insert_text("again", 8);
@ -745,7 +747,7 @@ mod tests {
#[test] #[test]
fn insert_text_in_non_empty_buffer_7() { fn insert_text_in_non_empty_buffer_7() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\n 世界\r\n!", 0); buf.insert_text("Hello\n 世界\r\n!", 0);
buf.insert_text("\nag\n\nain\n", 2); buf.insert_text("\nag\n\nain\n", 2);
@ -781,7 +783,7 @@ mod tests {
#[test] #[test]
fn remove_text_1() { fn remove_text_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -825,7 +827,7 @@ mod tests {
#[test] #[test]
fn remove_text_2() { fn remove_text_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -860,7 +862,7 @@ mod tests {
#[test] #[test]
fn remove_text_3() { fn remove_text_3() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -895,7 +897,7 @@ mod tests {
#[test] #[test]
fn remove_text_4() { fn remove_text_4() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -936,7 +938,7 @@ mod tests {
#[test] #[test]
fn remove_text_5() { fn remove_text_5() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -971,7 +973,7 @@ mod tests {
#[test] #[test]
fn remove_text_6() { fn remove_text_6() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\nworld!", 0); buf.insert_text("Hello\nworld!", 0);
assert!(buf.grapheme_count() == 12); assert!(buf.grapheme_count() == 12);
@ -992,7 +994,7 @@ mod tests {
#[test] #[test]
fn remove_text_7() { fn remove_text_7() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\nworld!", 0); buf.insert_text("Hi\nthere\nworld!", 0);
assert!(buf.grapheme_count() == 15); assert!(buf.grapheme_count() == 15);
@ -1015,7 +1017,7 @@ mod tests {
#[test] #[test]
fn remove_text_8() { fn remove_text_8() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\nworld!", 0); buf.insert_text("Hello\nworld!", 0);
assert!(buf.grapheme_count() == 12); assert!(buf.grapheme_count() == 12);
@ -1037,7 +1039,7 @@ mod tests {
#[test] #[test]
fn remove_text_9() { fn remove_text_9() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hello\nworld!", 0); buf.insert_text("Hello\nworld!", 0);
assert!(buf.grapheme_count() == 12); assert!(buf.grapheme_count() == 12);
@ -1063,7 +1065,7 @@ mod tests {
#[test] #[test]
fn remove_text_10() { fn remove_text_10() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("12\n34\n56\n78", 0); buf.insert_text("12\n34\n56\n78", 0);
assert!(buf.grapheme_count() == 11); assert!(buf.grapheme_count() == 11);
@ -1085,7 +1087,7 @@ mod tests {
#[test] #[test]
fn remove_text_11() { fn remove_text_11() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("1234567890", 0); buf.insert_text("1234567890", 0);
assert!(buf.grapheme_count() == 10); assert!(buf.grapheme_count() == 10);
@ -1112,7 +1114,7 @@ mod tests {
#[test] #[test]
fn move_text_1() { fn move_text_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
@ -1157,7 +1159,7 @@ mod tests {
#[test] #[test]
fn move_text_2() { fn move_text_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
@ -1202,7 +1204,7 @@ mod tests {
#[test] #[test]
fn move_text_3() { fn move_text_3() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
@ -1247,7 +1249,7 @@ mod tests {
#[test] #[test]
fn move_text_4() { fn move_text_4() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
@ -1292,7 +1294,7 @@ mod tests {
#[test] #[test]
fn move_text_5() { fn move_text_5() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
@ -1337,7 +1339,7 @@ mod tests {
#[test] #[test]
fn remove_lines_1() { fn remove_lines_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -1368,7 +1370,7 @@ mod tests {
#[test] #[test]
fn remove_lines_2() { fn remove_lines_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -1399,7 +1401,7 @@ mod tests {
#[test] #[test]
fn remove_lines_3() { fn remove_lines_3() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
assert!(buf.grapheme_count() == 29); assert!(buf.grapheme_count() == 29);
@ -1432,7 +1434,7 @@ mod tests {
#[test] #[test]
fn line_col_to_index_1() { fn line_col_to_index_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.line_col_to_index((2, 3)); let pos = buf.line_col_to_index((2, 3));
@ -1443,7 +1445,7 @@ mod tests {
#[test] #[test]
fn line_col_to_index_2() { fn line_col_to_index_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.line_col_to_index((2, 10)); let pos = buf.line_col_to_index((2, 10));
@ -1453,7 +1455,7 @@ mod tests {
#[test] #[test]
fn line_col_to_index_3() { fn line_col_to_index_3() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.line_col_to_index((10, 2)); let pos = buf.line_col_to_index((10, 2));
@ -1464,7 +1466,7 @@ mod tests {
#[test] #[test]
fn index_to_line_col_1() { fn index_to_line_col_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.index_to_line_col(5); let pos = buf.index_to_line_col(5);
@ -1475,7 +1477,7 @@ mod tests {
#[test] #[test]
fn index_to_line_col_2() { fn index_to_line_col_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.index_to_line_col(50); let pos = buf.index_to_line_col(50);
@ -1486,7 +1488,7 @@ mod tests {
#[test] #[test]
fn string_from_range_1() { fn string_from_range_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let s = buf.string_from_range(1, 12); let s = buf.string_from_range(1, 12);
@ -1497,7 +1499,7 @@ mod tests {
#[test] #[test]
fn string_from_range_2() { fn string_from_range_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let s = buf.string_from_range(0, 29); let s = buf.string_from_range(0, 29);
@ -1508,7 +1510,7 @@ mod tests {
#[test] #[test]
fn grapheme_iter_at_index_1() { fn grapheme_iter_at_index_1() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let mut iter = buf.grapheme_iter_at_index(16); let mut iter = buf.grapheme_iter_at_index(16);
@ -1532,7 +1534,7 @@ mod tests {
#[test] #[test]
fn grapheme_iter_at_index_2() { fn grapheme_iter_at_index_2() {
let mut buf = Buffer::new(); let mut buf = Buffer::new(TestLineFormatter::new());
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0); buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let mut iter = buf.grapheme_iter_at_index(29); let mut iter = buf.grapheme_iter_at_index(29);

View File

@ -1,7 +1,7 @@
use std::mem; use std::mem;
use std::cmp::{min, max}; use std::cmp::{min, max};
use line_formatter::{LineFormatter, RoundingBehavior}; use super::line_formatter::{LineFormatter, RoundingBehavior};
use string_utils::is_line_ending; use string_utils::is_line_ending;
use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending}; use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending};

View File

@ -5,7 +5,7 @@ use std::ops::{Index, IndexMut};
use std::cmp::Ordering; use std::cmp::Ordering;
use buffer::Buffer; use buffer::Buffer;
use line_formatter::LineFormatter; use buffer::line_formatter::LineFormatter;
/// A text cursor. Also represents selections when range.0 != range.1. /// A text cursor. Also represents selections when range.0 != range.1.
/// ///

View File

@ -1,8 +1,9 @@
#![allow(dead_code)] #![allow(dead_code)]
use buffer::Buffer; use buffer::Buffer;
use line_formatter::{LineFormatter, ConsoleLineFormatter}; use buffer::line_formatter::LineFormatter;
use line_formatter::RoundingBehavior::*; use buffer::line_formatter::RoundingBehavior::*;
use term_ui::formatter::ConsoleLineFormatter;
use std::path::Path; use std::path::Path;
use std::cmp::min; use std::cmp::min;
use files::{load_file_to_buffer, save_buffer_to_file}; use files::{load_file_to_buffer, save_buffer_to_file};

View File

@ -3,7 +3,7 @@ use std::io::fs::File;
use std::path::Path; use std::path::Path;
use buffer::line::{Line, LineEnding, line_ending_to_str}; use buffer::line::{Line, LineEnding, line_ending_to_str};
use line_formatter::LineFormatter; use buffer::line_formatter::LineFormatter;
use buffer::Buffer as TextBuffer; use buffer::Buffer as TextBuffer;
pub fn load_file_to_buffer<T: LineFormatter>(path: &Path, lf: T) -> IoResult<TextBuffer<T>> { pub fn load_file_to_buffer<T: LineFormatter>(path: &Path, lf: T) -> IoResult<TextBuffer<T>> {

View File

@ -14,7 +14,6 @@ use term_ui::TermUI;
mod string_utils; mod string_utils;
mod buffer; mod buffer;
mod line_formatter;
mod files; mod files;
mod editor; mod editor;
mod term_ui; mod term_ui;
@ -59,18 +58,16 @@ fn main() {
}; };
// Initialize and start UI // Initialize and start UI
// if args.flag_gui { //if args.flag_gui {
// // GUI // // GUI
// sdl2::init(sdl2::INIT_VIDEO); // sdl2::init(sdl2::INIT_VIDEO);
// let mut ui = GUI::new_from_editor(editor); // let mut ui = GUI::new_from_editor(editor);
// ui.main_ui_loop(); // ui.main_ui_loop();
// sdl2::quit(); // sdl2::quit();
// } //}
// else { //else {
// Console UI // Console UI
let mut ui = TermUI::new_from_editor(editor); let mut ui = TermUI::new_from_editor(editor);
ui.main_ui_loop(); ui.main_ui_loop();
// } //}
//println!("{}", editor.buffer.root.tree_height);
} }

View File

@ -1,56 +1,10 @@
use buffer::line::{Line, LineGraphemeIter};
use string_utils::{is_line_ending}; use string_utils::{is_line_ending};
use buffer::line::{Line, LineGraphemeIter};
use buffer::line_formatter::{LineFormatter, RoundingBehavior};
#[derive(Copy, PartialEq)] //===================================================================
pub enum RoundingBehavior { // LineFormatter implementation for terminals/consoles.
Round, //===================================================================
Floor,
Ceiling,
}
pub trait LineFormatter {
fn single_line_height(&self) -> usize;
fn dimensions(&self, line: &Line) -> (usize, usize);
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize);
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize;
}
//============================================================
// An implementation of the LineFormatter stuff for consoles
pub struct ConsoleLineFormatterVisIter<'a> {
grapheme_iter: LineGraphemeIter<'a>,
f: &'a ConsoleLineFormatter,
pos: (usize, usize),
}
impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
type Item = (&'a str, (usize, usize), usize);
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
if let Some(g) = self.grapheme_iter.next() {
let pos = self.pos;
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
self.pos = (self.pos.0, self.pos.1 + width);
return Some((g, (pos.0, pos.1), width));
}
else {
return None;
}
}
}
pub struct ConsoleLineFormatter { pub struct ConsoleLineFormatter {
pub tab_width: u8, pub tab_width: u8,
@ -147,6 +101,41 @@ impl<'a> LineFormatter for ConsoleLineFormatter {
} }
//===================================================================
// An iterator that iterates over the graphemes in a line in a
// manner consistent with the ConsoleFormatter.
//===================================================================
pub struct ConsoleLineFormatterVisIter<'a> {
grapheme_iter: LineGraphemeIter<'a>,
f: &'a ConsoleLineFormatter,
pos: (usize, usize),
}
impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
type Item = (&'a str, (usize, usize), usize);
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
if let Some(g) = self.grapheme_iter.next() {
let pos = self.pos;
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
self.pos = (self.pos.0, self.pos.1 + width);
return Some((g, (pos.0, pos.1), width));
}
else {
return None;
}
}
}
//===================================================================
// Helper functions
//===================================================================
/// Returns the visual width of a grapheme given a starting /// Returns the visual width of a grapheme given a starting
/// position on a line. /// position on a line.

View File

@ -7,7 +7,9 @@ use std::char;
use std::time::duration::Duration; use std::time::duration::Duration;
use string_utils::{is_line_ending}; use string_utils::{is_line_ending};
use buffer::line::{line_ending_to_str, LineEnding}; use buffer::line::{line_ending_to_str, LineEnding};
use line_formatter::{LineFormatter, RoundingBehavior}; use buffer::line_formatter::{LineFormatter, RoundingBehavior};
pub mod formatter;
// Key codes // Key codes
const K_ENTER: u16 = 13; const K_ENTER: u16 = 13;