Fixed bug in LineFormatter::index_offset_vertical_v2d()
The bug was causing very incorrect behavior when a single line was long enough to be split into multiple blocks.
This commit is contained in:
parent
9c462ee332
commit
1b3acfd29f
|
@ -1400,6 +1400,41 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_8() {
|
||||||
|
let rope = Rope::new_from_str("Hello everyone! How are you doing, eh?");
|
||||||
|
let s = rope.slice(15, 39);
|
||||||
|
|
||||||
|
let mut iter = s.grapheme_iter_between_indices(0, 25);
|
||||||
|
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some("H") == iter.next());
|
||||||
|
assert!(Some("o") == iter.next());
|
||||||
|
assert!(Some("w") == iter.next());
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some("a") == iter.next());
|
||||||
|
assert!(Some("r") == iter.next());
|
||||||
|
assert!(Some("e") == iter.next());
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some("y") == iter.next());
|
||||||
|
assert!(Some("o") == iter.next());
|
||||||
|
assert!(Some("u") == iter.next());
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some("d") == iter.next());
|
||||||
|
assert!(Some("o") == iter.next());
|
||||||
|
assert!(Some("i") == iter.next());
|
||||||
|
assert!(Some("n") == iter.next());
|
||||||
|
assert!(Some("g") == iter.next());
|
||||||
|
assert!(Some(",") == iter.next());
|
||||||
|
assert!(Some(" ") == iter.next());
|
||||||
|
assert!(Some("e") == iter.next());
|
||||||
|
assert!(Some("h") == iter.next());
|
||||||
|
assert!(Some("?") == iter.next());
|
||||||
|
assert!(None == iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn line_index_to_grapheme_index_1() {
|
fn line_index_to_grapheme_index_1() {
|
||||||
let rope = Rope::new_from_str("Hello\nworld!\n");
|
let rope = Rope::new_from_str("Hello\nworld!\n");
|
||||||
|
|
|
@ -65,14 +65,14 @@ pub trait LineFormatter {
|
||||||
let (line_block, col_i_adjusted) = block_index_and_offset(col_i);
|
let (line_block, col_i_adjusted) = block_index_and_offset(col_i);
|
||||||
|
|
||||||
let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH), col_i_adjusted);
|
let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH), col_i_adjusted);
|
||||||
let mut new_y = y as isize + offset;
|
|
||||||
|
|
||||||
// First, find the right line while keeping track of the vertical offset
|
// First, find the right line while keeping track of the vertical offset
|
||||||
|
let mut new_y = y as isize + offset;
|
||||||
let mut line;
|
let mut line;
|
||||||
let mut block_index: usize = line_block;
|
let mut block_index: usize = line_block;
|
||||||
loop {
|
loop {
|
||||||
line = buf.get_line(line_i);
|
line = buf.get_line(line_i);
|
||||||
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH));
|
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(block_index * LINE_BLOCK_LENGTH, (block_index+1) * LINE_BLOCK_LENGTH));
|
||||||
|
|
||||||
if new_y >= 0 && new_y < h as isize {
|
if new_y >= 0 && new_y < h as isize {
|
||||||
y = new_y as usize;
|
y = new_y as usize;
|
||||||
|
@ -80,14 +80,14 @@ pub trait LineFormatter {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if new_y > 0 {
|
if new_y > 0 {
|
||||||
let last_block = block_index >= (line.grapheme_count() / LINE_BLOCK_LENGTH);
|
let is_last_block = block_index >= last_block_index(line.grapheme_count());
|
||||||
|
|
||||||
// Check for off-the-end
|
// Check for off-the-end
|
||||||
if last_block && (line_i + 1) >= buf.line_count() {
|
if is_last_block && (line_i + 1) >= buf.line_count() {
|
||||||
return buf.grapheme_count();
|
return buf.grapheme_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
if last_block {
|
if is_last_block {
|
||||||
line_i += 1;
|
line_i += 1;
|
||||||
block_index = 0;
|
block_index = 0;
|
||||||
}
|
}
|
||||||
|
@ -105,12 +105,12 @@ pub trait LineFormatter {
|
||||||
if block_index == 0 {
|
if block_index == 0 {
|
||||||
line_i -= 1;
|
line_i -= 1;
|
||||||
line = buf.get_line(line_i);
|
line = buf.get_line(line_i);
|
||||||
block_index = line.grapheme_count() / LINE_BLOCK_LENGTH;
|
block_index = last_block_index(line.grapheme_count());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
block_index -= 1;
|
block_index -= 1;
|
||||||
}
|
}
|
||||||
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH));
|
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(block_index * LINE_BLOCK_LENGTH, (block_index+1) * LINE_BLOCK_LENGTH));
|
||||||
new_y += h as isize;
|
new_y += h as isize;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -121,7 +121,7 @@ pub trait LineFormatter {
|
||||||
|
|
||||||
// Next, convert the resulting coordinates back into buffer-wide
|
// Next, convert the resulting coordinates back into buffer-wide
|
||||||
// coordinates.
|
// coordinates.
|
||||||
col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH), (y, x), rounding);
|
col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_between_indices(block_index * LINE_BLOCK_LENGTH, (block_index+1) * LINE_BLOCK_LENGTH), (y, x), rounding);
|
||||||
|
|
||||||
return buf.line_col_to_index((line_i, col_i));
|
return buf.line_col_to_index((line_i, col_i));
|
||||||
}
|
}
|
||||||
|
@ -158,3 +158,17 @@ pub trait LineFormatter {
|
||||||
pub fn block_index_and_offset(index: usize) -> (usize, usize) {
|
pub fn block_index_and_offset(index: usize) -> (usize, usize) {
|
||||||
(index / LINE_BLOCK_LENGTH, index % LINE_BLOCK_LENGTH)
|
(index / LINE_BLOCK_LENGTH, index % LINE_BLOCK_LENGTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn last_block_index(gc: usize) -> usize {
|
||||||
|
let mut block_count = gc / LINE_BLOCK_LENGTH;
|
||||||
|
if (gc % LINE_BLOCK_LENGTH) > 0 {
|
||||||
|
block_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if block_count > 0 {
|
||||||
|
return block_count - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ fn grapheme_vis_width_at_vis_pos(g: &str, pos: usize, tab_width: usize) -> usize
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
use super::*;
|
use super::*;
|
||||||
use formatter::LineFormatter;
|
use formatter::{LineFormatter, LINE_BLOCK_LENGTH};
|
||||||
use formatter::RoundingBehavior::{Round, Floor, Ceiling};
|
use formatter::RoundingBehavior::{Round, Floor, Ceiling};
|
||||||
use buffer::Buffer;
|
use buffer::Buffer;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user