Start indexing UTF-16 offsets
This is needed because cocoa will report ranges as UTF-16 indices.
This commit is contained in:
parent
eda60effed
commit
32662b6b92
6 changed files with 261 additions and 55 deletions
|
@ -9,7 +9,7 @@ pub use language::Completion;
|
|||
use language::{
|
||||
char_kind, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, DiagnosticEntry, Event, File,
|
||||
IndentSize, Language, OffsetRangeExt, Outline, OutlineItem, Selection, ToOffset as _,
|
||||
ToPoint as _, ToPointUtf16 as _, TransactionId,
|
||||
ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
|
||||
};
|
||||
use settings::Settings;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -29,7 +29,7 @@ use text::{
|
|||
locator::Locator,
|
||||
rope::TextDimension,
|
||||
subscription::{Subscription, Topic},
|
||||
Edit, Point, PointUtf16, TextSummary,
|
||||
Edit, OffsetUtf16, Point, PointUtf16, TextSummary,
|
||||
};
|
||||
use theme::SyntaxTheme;
|
||||
use util::post_inc;
|
||||
|
@ -72,6 +72,10 @@ pub trait ToOffset: 'static + fmt::Debug {
|
|||
fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
|
||||
}
|
||||
|
||||
pub trait ToOffsetUtf16: 'static + fmt::Debug {
|
||||
fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16;
|
||||
}
|
||||
|
||||
pub trait ToPoint: 'static + fmt::Debug {
|
||||
fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
|
||||
}
|
||||
|
@ -809,7 +813,7 @@ impl MultiBuffer {
|
|||
let mut cursor = snapshot.excerpts.cursor::<Option<&ExcerptId>>();
|
||||
let mut new_excerpts = cursor.slice(&Some(prev_excerpt_id), Bias::Right, &());
|
||||
|
||||
let edit_start = new_excerpts.summary().text.bytes;
|
||||
let edit_start = new_excerpts.summary().text.len;
|
||||
new_excerpts.update_last(
|
||||
|excerpt| {
|
||||
excerpt.has_trailing_newline = true;
|
||||
|
@ -862,7 +866,7 @@ impl MultiBuffer {
|
|||
&(),
|
||||
);
|
||||
|
||||
let edit_end = new_excerpts.summary().text.bytes;
|
||||
let edit_end = new_excerpts.summary().text.len;
|
||||
|
||||
let suffix = cursor.suffix(&());
|
||||
let changed_trailing_excerpt = suffix.is_empty();
|
||||
|
@ -1068,7 +1072,7 @@ impl MultiBuffer {
|
|||
|
||||
// Push an edit for the removal of this run of excerpts.
|
||||
let old_end = cursor.start().1;
|
||||
let new_start = new_excerpts.summary().text.bytes;
|
||||
let new_start = new_excerpts.summary().text.len;
|
||||
edits.push(Edit {
|
||||
old: old_start..old_end,
|
||||
new: new_start..new_start,
|
||||
|
@ -1297,7 +1301,7 @@ impl MultiBuffer {
|
|||
)
|
||||
.map(|mut edit| {
|
||||
let excerpt_old_start = cursor.start().1;
|
||||
let excerpt_new_start = new_excerpts.summary().text.bytes;
|
||||
let excerpt_new_start = new_excerpts.summary().text.len;
|
||||
edit.old.start += excerpt_old_start;
|
||||
edit.old.end += excerpt_old_start;
|
||||
edit.new.start += excerpt_new_start;
|
||||
|
@ -1527,7 +1531,7 @@ impl MultiBufferSnapshot {
|
|||
let mut cursor = self.excerpts.cursor::<usize>();
|
||||
cursor.seek(&offset, Bias::Left, &());
|
||||
let mut excerpt_chunks = cursor.item().map(|excerpt| {
|
||||
let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
|
||||
let end_before_footer = cursor.start() + excerpt.text_summary.len;
|
||||
let start = excerpt.range.context.start.to_offset(&excerpt.buffer);
|
||||
let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
|
||||
excerpt.buffer.reversed_chunks_in_range(start..end)
|
||||
|
@ -1629,7 +1633,7 @@ impl MultiBufferSnapshot {
|
|||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.excerpts.summary().text.bytes
|
||||
self.excerpts.summary().text.len
|
||||
}
|
||||
|
||||
pub fn max_buffer_row(&self) -> u32 {
|
||||
|
@ -1824,7 +1828,53 @@ impl MultiBufferSnapshot {
|
|||
.point_to_offset(excerpt_start_point + overshoot);
|
||||
*start_offset + buffer_offset - excerpt_start_offset
|
||||
} else {
|
||||
self.excerpts.summary().text.bytes
|
||||
self.excerpts.summary().text.len
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset_utf16_to_offset(&self, offset_utf16: OffsetUtf16) -> usize {
|
||||
if let Some((_, _, buffer)) = self.as_singleton() {
|
||||
return buffer.offset_utf16_to_offset(offset_utf16);
|
||||
}
|
||||
|
||||
let mut cursor = self.excerpts.cursor::<(OffsetUtf16, usize)>();
|
||||
cursor.seek(&offset_utf16, Bias::Right, &());
|
||||
if let Some(excerpt) = cursor.item() {
|
||||
let (start_offset_utf16, start_offset) = cursor.start();
|
||||
let overshoot = offset_utf16 - start_offset_utf16;
|
||||
let excerpt_start_offset = excerpt.range.context.start.to_offset(&excerpt.buffer);
|
||||
let excerpt_start_offset_utf16 =
|
||||
excerpt.buffer.offset_to_offset_utf16(excerpt_start_offset);
|
||||
let buffer_offset = excerpt
|
||||
.buffer
|
||||
.offset_utf16_to_offset(excerpt_start_offset_utf16 + overshoot);
|
||||
*start_offset + (buffer_offset - excerpt_start_offset)
|
||||
} else {
|
||||
self.excerpts.summary().text.len
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset_to_offset_utf16(&self, offset: usize) -> OffsetUtf16 {
|
||||
if let Some((_, _, buffer)) = self.as_singleton() {
|
||||
return buffer.offset_to_offset_utf16(offset);
|
||||
}
|
||||
|
||||
let mut cursor = self.excerpts.cursor::<(usize, OffsetUtf16)>();
|
||||
cursor.seek(&offset, Bias::Right, &());
|
||||
if let Some(excerpt) = cursor.item() {
|
||||
let (start_offset, start_offset_utf16) = cursor.start();
|
||||
let overshoot = offset - start_offset;
|
||||
let excerpt_start_offset_utf16 =
|
||||
excerpt.range.context.start.to_offset_utf16(&excerpt.buffer);
|
||||
let excerpt_start_offset = excerpt
|
||||
.buffer
|
||||
.offset_utf16_to_offset(excerpt_start_offset_utf16);
|
||||
let buffer_offset_utf16 = excerpt
|
||||
.buffer
|
||||
.offset_to_offset_utf16(excerpt_start_offset + overshoot);
|
||||
*start_offset_utf16 + (buffer_offset_utf16 - excerpt_start_offset_utf16)
|
||||
} else {
|
||||
OffsetUtf16(self.excerpts.summary().text.len_utf16)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1847,7 +1897,7 @@ impl MultiBufferSnapshot {
|
|||
.point_utf16_to_offset(excerpt_start_point + overshoot);
|
||||
*start_offset + (buffer_offset - excerpt_start_offset)
|
||||
} else {
|
||||
self.excerpts.summary().text.bytes
|
||||
self.excerpts.summary().text.len
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2311,7 +2361,7 @@ impl MultiBufferSnapshot {
|
|||
.context
|
||||
.start
|
||||
.to_offset(&start_excerpt.buffer);
|
||||
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
|
||||
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.len;
|
||||
|
||||
let start_in_buffer =
|
||||
excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
|
||||
|
@ -2415,7 +2465,7 @@ impl MultiBufferSnapshot {
|
|||
.context
|
||||
.start
|
||||
.to_offset(&start_excerpt.buffer);
|
||||
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
|
||||
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.len;
|
||||
|
||||
let start_in_buffer =
|
||||
excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
|
||||
|
@ -2717,11 +2767,11 @@ impl Excerpt {
|
|||
) -> ExcerptChunks<'a> {
|
||||
let content_start = self.range.context.start.to_offset(&self.buffer);
|
||||
let chunks_start = content_start + range.start;
|
||||
let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
|
||||
let chunks_end = content_start + cmp::min(range.end, self.text_summary.len);
|
||||
|
||||
let footer_height = if self.has_trailing_newline
|
||||
&& range.start <= self.text_summary.bytes
|
||||
&& range.end > self.text_summary.bytes
|
||||
&& range.start <= self.text_summary.len
|
||||
&& range.end > self.text_summary.len
|
||||
{
|
||||
1
|
||||
} else {
|
||||
|
@ -2739,10 +2789,10 @@ impl Excerpt {
|
|||
fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
|
||||
let content_start = self.range.context.start.to_offset(&self.buffer);
|
||||
let bytes_start = content_start + range.start;
|
||||
let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
|
||||
let bytes_end = content_start + cmp::min(range.end, self.text_summary.len);
|
||||
let footer_height = if self.has_trailing_newline
|
||||
&& range.start <= self.text_summary.bytes
|
||||
&& range.end > self.text_summary.bytes
|
||||
&& range.start <= self.text_summary.len
|
||||
&& range.end > self.text_summary.len
|
||||
{
|
||||
1
|
||||
} else {
|
||||
|
@ -2836,13 +2886,13 @@ impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for TextSummary {
|
|||
|
||||
impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for usize {
|
||||
fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
|
||||
*self += summary.text.bytes;
|
||||
*self += summary.text.len;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for usize {
|
||||
fn cmp(&self, cursor_location: &ExcerptSummary, _: &()) -> cmp::Ordering {
|
||||
Ord::cmp(self, &cursor_location.text.bytes)
|
||||
Ord::cmp(self, &cursor_location.text.len)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2852,6 +2902,12 @@ impl<'a> sum_tree::SeekTarget<'a, ExcerptSummary, ExcerptSummary> for Option<&'a
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for OffsetUtf16 {
|
||||
fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
|
||||
self.0 += summary.text.len_utf16;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Point {
|
||||
fn add_summary(&mut self, summary: &'a ExcerptSummary, _: &()) {
|
||||
*self += summary.text.lines;
|
||||
|
@ -3060,6 +3116,24 @@ impl ToOffset for usize {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToOffset for OffsetUtf16 {
|
||||
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
|
||||
snapshot.offset_utf16_to_offset(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOffsetUtf16 for OffsetUtf16 {
|
||||
fn to_offset_utf16(&self, _snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOffsetUtf16 for usize {
|
||||
fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
|
||||
snapshot.offset_to_offset_utf16(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPoint for usize {
|
||||
fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
|
||||
snapshot.offset_to_point(*self)
|
||||
|
@ -3823,7 +3897,7 @@ mod tests {
|
|||
buffer.text_summary_for_range::<PointUtf16, _>(0..buffer_range.start);
|
||||
|
||||
let excerpt_start = excerpt_starts.next().unwrap();
|
||||
let mut offset = excerpt_start.bytes;
|
||||
let mut offset = excerpt_start.len;
|
||||
let mut buffer_offset = buffer_range.start;
|
||||
let mut point = excerpt_start.lines;
|
||||
let mut buffer_point = buffer_start_point;
|
||||
|
@ -3841,7 +3915,7 @@ mod tests {
|
|||
let buffer_right_offset = buffer.clip_offset(buffer_offset, Bias::Right);
|
||||
assert_eq!(
|
||||
left_offset,
|
||||
excerpt_start.bytes + (buffer_left_offset - buffer_range.start),
|
||||
excerpt_start.len + (buffer_left_offset - buffer_range.start),
|
||||
"clip_offset({:?}, Left). buffer: {:?}, buffer offset: {:?}",
|
||||
offset,
|
||||
buffer_id,
|
||||
|
@ -3849,7 +3923,7 @@ mod tests {
|
|||
);
|
||||
assert_eq!(
|
||||
right_offset,
|
||||
excerpt_start.bytes + (buffer_right_offset - buffer_range.start),
|
||||
excerpt_start.len + (buffer_right_offset - buffer_range.start),
|
||||
"clip_offset({:?}, Right). buffer: {:?}, buffer offset: {:?}",
|
||||
offset,
|
||||
buffer_id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue