Expand tabs correctly with multibyte characters

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld
2021-05-20 12:47:08 +02:00
committed by Antonio Scandurra
co-authored by Nathan Sobo
parent c62a679e12
commit 6621b9b552
4 changed files with 120 additions and 98 deletions
+2 -2
View File
@@ -643,11 +643,11 @@ impl Buffer {
self.visible_text.chunks_in_range(start..end)
}
pub fn chars(&self) -> rope::Chars {
pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars_at(0)
}
pub fn chars_at<T: ToOffset>(&self, position: T) -> rope::Chars {
pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
let offset = position.to_offset(self);
self.visible_text.chars_at(offset)
}
+4 -42
View File
@@ -2,7 +2,7 @@ use super::Point;
use crate::sum_tree::{self, SeekBias, SumTree};
use arrayvec::ArrayString;
use smallvec::SmallVec;
use std::{cmp, iter::Skip, ops::Range, str};
use std::{cmp, ops::Range, str};
#[cfg(test)]
const CHUNK_BASE: usize = 6;
@@ -107,12 +107,12 @@ impl Rope {
Cursor::new(self, offset)
}
pub fn chars(&self) -> Chars {
pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars_at(0)
}
pub fn chars_at(&self, start: usize) -> Chars {
Chars::new(self, start)
pub fn chars_at(&self, start: usize) -> impl Iterator<Item = char> + '_ {
self.chunks_in_range(start..self.len()).flat_map(str::chars)
}
pub fn chunks<'a>(&'a self) -> ChunksIter<'a> {
@@ -446,44 +446,6 @@ impl<'a> sum_tree::Dimension<'a, TextSummary> for Point {
}
}
pub struct Chars<'a> {
cursor: sum_tree::Cursor<'a, Chunk, usize, usize>,
chars: Skip<str::Chars<'a>>,
}
impl<'a> Chars<'a> {
pub fn new(rope: &'a Rope, start: usize) -> Self {
let mut cursor = rope.chunks.cursor::<usize, usize>();
cursor.seek(&start, SeekBias::Left, &());
let chars = if let Some(chunk) = cursor.item() {
let ix = start - cursor.start();
assert_char_boundary(&chunk.0, ix);
cursor.next();
chunk.0.chars().skip(ix)
} else {
"".chars().skip(0)
};
Self { cursor, chars }
}
}
impl<'a> Iterator for Chars<'a> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
if let Some(ch) = self.chars.next() {
Some(ch)
} else if let Some(chunk) = self.cursor.item() {
self.chars = chunk.0.chars().skip(0);
self.cursor.next();
Some(self.chars.next().unwrap())
} else {
None
}
}
}
fn find_split_ix(text: &str) -> usize {
let mut ix = text.len() / 2;
while !text.is_char_boundary(ix) {