multi_buffer: Typed MultiBufferOffset (#42707)
This PR introduces a new `MultiBufferOffset` new type wrapping size. The goal of this is to make it clear at the type level when we are interacting with offsets of a multi buffer versus offsets of a language / text buffer. This improves readability of things quite a bit by making it clear what kind of offsets one is working with while also reducing accidental bugs by using the wrong kin of offset for the wrong API. This PR also uncovered two minor bugs due to that. Does not yet introduce the MultiBufferPoint equivalent, that is for a follow up PR. Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -6,8 +6,8 @@ mod select;
|
||||
|
||||
use editor::display_map::DisplaySnapshot;
|
||||
use editor::{
|
||||
DisplayPoint, Editor, EditorSettings, HideMouseCursorOrigin, SelectionEffects, ToOffset,
|
||||
ToPoint, movement,
|
||||
DisplayPoint, Editor, EditorSettings, HideMouseCursorOrigin, MultiBufferOffset,
|
||||
SelectionEffects, ToOffset, ToPoint, movement,
|
||||
};
|
||||
use gpui::actions;
|
||||
use gpui::{Context, Window};
|
||||
@@ -523,7 +523,7 @@ impl Vim {
|
||||
..range.end.to_offset(&display_map, Bias::Left);
|
||||
|
||||
if !byte_range.is_empty() {
|
||||
let replacement_text = text.repeat(byte_range.len());
|
||||
let replacement_text = text.repeat(byte_range.end - byte_range.start);
|
||||
edits.push((byte_range, replacement_text));
|
||||
}
|
||||
}
|
||||
@@ -620,7 +620,7 @@ impl Vim {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
let newest = editor
|
||||
.selections
|
||||
.newest::<usize>(&editor.display_snapshot(cx));
|
||||
.newest::<MultiBufferOffset>(&editor.display_snapshot(cx));
|
||||
editor.change_selections(Default::default(), window, cx, |s| s.select(vec![newest]));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Deref, DerefMut, Range},
|
||||
};
|
||||
use std::{cmp::Ordering, ops::Range};
|
||||
|
||||
use editor::{
|
||||
DisplayPoint,
|
||||
DisplayPoint, MultiBufferOffset,
|
||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||
movement,
|
||||
};
|
||||
@@ -104,8 +101,8 @@ trait BoundedObject {
|
||||
let next_end = self.next_end(map, end_search_start, outer)?;
|
||||
let maybe_next_start = self.next_start(map, start_search_start, outer);
|
||||
if let Some(next_start) = maybe_next_start
|
||||
&& (*next_start < *next_end
|
||||
|| *next_start == *next_end && self.can_be_zero_width(outer))
|
||||
&& (next_start.0 < next_end.0
|
||||
|| next_start.0 == next_end.0 && self.can_be_zero_width(outer))
|
||||
&& !self.ambiguous_outer()
|
||||
{
|
||||
let closing = self.close_at_end(next_start, map, outer)?;
|
||||
@@ -133,8 +130,8 @@ trait BoundedObject {
|
||||
let previous_start = self.previous_start(map, start_search_end, outer)?;
|
||||
let maybe_previous_end = self.previous_end(map, end_search_end, outer);
|
||||
if let Some(previous_end) = maybe_previous_end
|
||||
&& (*previous_end > *previous_start
|
||||
|| *previous_end == *previous_start && self.can_be_zero_width(outer))
|
||||
&& (previous_end.0 > previous_start.0
|
||||
|| previous_end.0 == previous_start.0 && self.can_be_zero_width(outer))
|
||||
&& !self.ambiguous_outer()
|
||||
{
|
||||
let closing = self.close_at_start(previous_end, map, outer)?;
|
||||
@@ -151,30 +148,22 @@ trait BoundedObject {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
struct Offset(usize);
|
||||
impl Deref for Offset {
|
||||
type Target = usize;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl DerefMut for Offset {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, Debug, PartialOrd, Ord, Eq)]
|
||||
struct Offset(MultiBufferOffset);
|
||||
impl Offset {
|
||||
fn next(self, map: &DisplaySnapshot) -> Option<Self> {
|
||||
let next = Self(map.buffer_snapshot().clip_offset(*self + 1, Bias::Right));
|
||||
(*next > *self).then(|| next)
|
||||
let next = Self(
|
||||
map.buffer_snapshot()
|
||||
.clip_offset(self.0 + 1usize, Bias::Right),
|
||||
);
|
||||
(next.0 > self.0).then(|| next)
|
||||
}
|
||||
fn previous(self, map: &DisplaySnapshot) -> Option<Self> {
|
||||
if *self == 0 {
|
||||
if self.0 == MultiBufferOffset(0) {
|
||||
return None;
|
||||
}
|
||||
Some(Self(
|
||||
map.buffer_snapshot().clip_offset(*self - 1, Bias::Left),
|
||||
map.buffer_snapshot().clip_offset(self.0 - 1, Bias::Left),
|
||||
))
|
||||
}
|
||||
fn range(
|
||||
@@ -211,7 +200,7 @@ impl<B: BoundedObject> HelixTextObject for B {
|
||||
let max_end = self.close_at_end(search_start, map, find_outer)?;
|
||||
let min_start = self.close_at_start(max_end, map, find_outer)?;
|
||||
|
||||
(*min_start <= *relative_to.start).then(|| min_start..max_end)
|
||||
(min_start <= relative_to.start).then(|| min_start..max_end)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -279,8 +268,8 @@ fn relative_range<B: BoundedObject>(
|
||||
min_start..max_end
|
||||
};
|
||||
|
||||
let start = wanted_range.start.clone().to_display_point(map);
|
||||
let end = wanted_range.end.clone().to_display_point(map);
|
||||
let start = wanted_range.start.0.to_display_point(map);
|
||||
let end = wanted_range.end.0.to_display_point(map);
|
||||
|
||||
Some(start..end)
|
||||
}
|
||||
@@ -390,7 +379,7 @@ impl ImmediateBoundary {
|
||||
impl BoundedObject for ImmediateBoundary {
|
||||
fn next_start(&self, map: &DisplaySnapshot, from: Offset, outer: bool) -> Option<Offset> {
|
||||
try_find_boundary(map, from, |left, right| {
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(*from);
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(from.0);
|
||||
if outer {
|
||||
self.is_outer_start(left, right, classifier)
|
||||
} else {
|
||||
@@ -400,7 +389,7 @@ impl BoundedObject for ImmediateBoundary {
|
||||
}
|
||||
fn next_end(&self, map: &DisplaySnapshot, from: Offset, outer: bool) -> Option<Offset> {
|
||||
try_find_boundary(map, from, |left, right| {
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(*from);
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(from.0);
|
||||
if outer {
|
||||
self.is_outer_end(left, right, classifier)
|
||||
} else {
|
||||
@@ -410,7 +399,7 @@ impl BoundedObject for ImmediateBoundary {
|
||||
}
|
||||
fn previous_start(&self, map: &DisplaySnapshot, from: Offset, outer: bool) -> Option<Offset> {
|
||||
try_find_preceding_boundary(map, from, |left, right| {
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(*from);
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(from.0);
|
||||
if outer {
|
||||
self.is_outer_start(left, right, classifier)
|
||||
} else {
|
||||
@@ -420,7 +409,7 @@ impl BoundedObject for ImmediateBoundary {
|
||||
}
|
||||
fn previous_end(&self, map: &DisplaySnapshot, from: Offset, outer: bool) -> Option<Offset> {
|
||||
try_find_preceding_boundary(map, from, |left, right| {
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(*from);
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(from.0);
|
||||
if outer {
|
||||
self.is_outer_end(left, right, classifier)
|
||||
} else {
|
||||
@@ -572,7 +561,7 @@ impl FuzzyBoundary {
|
||||
boundary_kind: Boundary,
|
||||
) -> Option<Offset> {
|
||||
let generate_boundary_data = |left, right, point: Offset| {
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(*from);
|
||||
let classifier = map.buffer_snapshot().char_classifier_at(from.0);
|
||||
let reach_boundary = if outer && boundary_kind == Boundary::Start {
|
||||
self.is_near_potential_outer_start(left, right, &classifier)
|
||||
} else if !outer && boundary_kind == Boundary::Start {
|
||||
@@ -598,9 +587,9 @@ impl FuzzyBoundary {
|
||||
Ordering::Greater => !backward,
|
||||
});
|
||||
if backward {
|
||||
boundaries.max_by_key(|boundary| **boundary)
|
||||
boundaries.max_by_key(|boundary| *boundary)
|
||||
} else {
|
||||
boundaries.min_by_key(|boundary| **boundary)
|
||||
boundaries.min_by_key(|boundary| *boundary)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -662,15 +651,15 @@ fn try_find_boundary_data<T>(
|
||||
) -> Option<T> {
|
||||
let mut prev_ch = map
|
||||
.buffer_snapshot()
|
||||
.reversed_chars_at(*from)
|
||||
.reversed_chars_at(from.0)
|
||||
.next()
|
||||
.unwrap_or('\0');
|
||||
|
||||
for ch in map.buffer_snapshot().chars_at(*from).chain(['\0']) {
|
||||
for ch in map.buffer_snapshot().chars_at(from.0).chain(['\0']) {
|
||||
if let Some(boundary_information) = boundary_information(prev_ch, ch, from) {
|
||||
return Some(boundary_information);
|
||||
}
|
||||
*from += ch.len_utf8();
|
||||
from.0 += ch.len_utf8();
|
||||
prev_ch = ch;
|
||||
}
|
||||
|
||||
@@ -702,13 +691,21 @@ fn try_find_preceding_boundary_data<T>(
|
||||
mut from: Offset,
|
||||
is_boundary: impl Fn(char, char, Offset) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let mut prev_ch = map.buffer_snapshot().chars_at(*from).next().unwrap_or('\0');
|
||||
let mut prev_ch = map
|
||||
.buffer_snapshot()
|
||||
.chars_at(from.0)
|
||||
.next()
|
||||
.unwrap_or('\0');
|
||||
|
||||
for ch in map.buffer_snapshot().reversed_chars_at(*from).chain(['\0']) {
|
||||
for ch in map
|
||||
.buffer_snapshot()
|
||||
.reversed_chars_at(from.0)
|
||||
.chain(['\0'])
|
||||
{
|
||||
if let Some(boundary_information) = is_boundary(ch, prev_ch, from) {
|
||||
return Some(boundary_information);
|
||||
}
|
||||
from.0 = from.0.saturating_sub(ch.len_utf8());
|
||||
from.0.0 = from.0.0.saturating_sub(ch.len_utf8());
|
||||
prev_ch = ch;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use editor::{DisplayPoint, display_map::DisplaySnapshot};
|
||||
use editor::{DisplayPoint, MultiBufferOffset, display_map::DisplaySnapshot};
|
||||
use gpui::Context;
|
||||
use text::Bias;
|
||||
use ui::Window;
|
||||
@@ -111,7 +111,7 @@ fn find_next_valid_duplicate_space(
|
||||
fn display_point_range_to_offset_range(
|
||||
range: &Range<DisplayPoint>,
|
||||
map: &DisplaySnapshot,
|
||||
) -> Range<usize> {
|
||||
) -> Range<MultiBufferOffset> {
|
||||
range.start.to_offset(map, Bias::Left)..range.end.to_offset(map, Bias::Right)
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ impl Vim {
|
||||
s.select_ranges(new_selections.into_iter().map(|(anchor, len)| {
|
||||
let offset = anchor.to_offset(&snapshot);
|
||||
if action.before {
|
||||
offset.saturating_sub(len)..offset
|
||||
offset.saturating_sub_usize(len)..offset
|
||||
} else {
|
||||
offset..(offset + len)
|
||||
}
|
||||
|
||||
+23
-16
@@ -1,5 +1,5 @@
|
||||
use editor::{
|
||||
Anchor, Bias, DisplayPoint, Editor, RowExt, ToOffset, ToPoint,
|
||||
Anchor, Bias, BufferOffset, DisplayPoint, Editor, MultiBufferOffset, RowExt, ToOffset, ToPoint,
|
||||
display_map::{DisplayRow, DisplaySnapshot, FoldPoint, ToDisplayPoint},
|
||||
movement::{
|
||||
self, FindRange, TextLayoutDetails, find_boundary, find_preceding_boundary_display_point,
|
||||
@@ -2143,7 +2143,7 @@ pub(crate) fn sentence_backwards(
|
||||
if start_of_next_sentence < start {
|
||||
times = times.saturating_sub(1);
|
||||
}
|
||||
if times == 0 || offset == 0 {
|
||||
if times == 0 || offset.0 == 0 {
|
||||
return map.clip_point(
|
||||
start_of_next_sentence
|
||||
.to_offset(&map.buffer_snapshot())
|
||||
@@ -2207,7 +2207,7 @@ pub(crate) fn sentence_forwards(
|
||||
map.max_point()
|
||||
}
|
||||
|
||||
fn next_non_blank(map: &DisplaySnapshot, start: usize) -> usize {
|
||||
fn next_non_blank(map: &DisplaySnapshot, start: MultiBufferOffset) -> MultiBufferOffset {
|
||||
for (c, o) in map.buffer_chars_at(start) {
|
||||
if c == '\n' || !c.is_whitespace() {
|
||||
return o;
|
||||
@@ -2219,7 +2219,10 @@ fn next_non_blank(map: &DisplaySnapshot, start: usize) -> usize {
|
||||
|
||||
// given the offset after a ., !, or ? find the start of the next sentence.
|
||||
// if this is not a sentence boundary, returns None.
|
||||
fn start_of_next_sentence(map: &DisplaySnapshot, end_of_sentence: usize) -> Option<usize> {
|
||||
fn start_of_next_sentence(
|
||||
map: &DisplaySnapshot,
|
||||
end_of_sentence: MultiBufferOffset,
|
||||
) -> Option<MultiBufferOffset> {
|
||||
let chars = map.buffer_chars_at(end_of_sentence);
|
||||
let mut seen_space = false;
|
||||
|
||||
@@ -2253,10 +2256,10 @@ fn go_to_line(map: &DisplaySnapshot, display_point: DisplayPoint, line: usize) -
|
||||
.clip_point(Point::new((line - 1) as u32, point.column), Bias::Left),
|
||||
);
|
||||
let buffer_range = excerpt.buffer_range();
|
||||
if offset >= buffer_range.start && offset <= buffer_range.end {
|
||||
if offset >= buffer_range.start.0 && offset <= buffer_range.end.0 {
|
||||
let point = map
|
||||
.buffer_snapshot()
|
||||
.offset_to_point(excerpt.map_offset_from_buffer(offset));
|
||||
.offset_to_point(excerpt.map_offset_from_buffer(BufferOffset(offset)));
|
||||
return map.clip_point(map.point_to_display_point(point, Bias::Left), Bias::Left);
|
||||
}
|
||||
let mut last_position = None;
|
||||
@@ -2360,6 +2363,9 @@ fn matching_tag(map: &DisplaySnapshot, head: DisplayPoint) -> Option<DisplayPoin
|
||||
}
|
||||
|
||||
fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint {
|
||||
if !map.is_singleton() {
|
||||
return display_point;
|
||||
}
|
||||
// https://github.com/vim/vim/blob/1d87e11a1ef201b26ed87585fba70182ad0c468a/runtime/doc/motion.txt#L1200
|
||||
let display_point = map.clip_at_line_end(display_point);
|
||||
let point = display_point.to_point(map);
|
||||
@@ -2375,9 +2381,10 @@ fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint
|
||||
// Attempt to find the smallest enclosing bracket range that also contains
|
||||
// the offset, which only happens if the cursor is currently in a bracket.
|
||||
let range_filter = |_buffer: &language::BufferSnapshot,
|
||||
opening_range: Range<usize>,
|
||||
closing_range: Range<usize>| {
|
||||
opening_range.contains(&offset) || closing_range.contains(&offset)
|
||||
opening_range: Range<BufferOffset>,
|
||||
closing_range: Range<BufferOffset>| {
|
||||
opening_range.contains(&BufferOffset(offset.0))
|
||||
|| closing_range.contains(&BufferOffset(offset.0))
|
||||
};
|
||||
|
||||
let bracket_ranges = snapshot
|
||||
@@ -2840,7 +2847,7 @@ fn method_motion(
|
||||
|
||||
for _ in 0..times {
|
||||
let point = map.display_point_to_point(display_point, Bias::Left);
|
||||
let offset = point.to_offset(&map.buffer_snapshot());
|
||||
let offset = point.to_offset(&map.buffer_snapshot()).0;
|
||||
let range = if direction == Direction::Prev {
|
||||
0..offset
|
||||
} else {
|
||||
@@ -2869,7 +2876,7 @@ fn method_motion(
|
||||
} else {
|
||||
possibilities.min().unwrap_or(offset)
|
||||
};
|
||||
let new_point = map.clip_point(dest.to_display_point(map), Bias::Left);
|
||||
let new_point = map.clip_point(MultiBufferOffset(dest).to_display_point(map), Bias::Left);
|
||||
if new_point == display_point {
|
||||
break;
|
||||
}
|
||||
@@ -2890,7 +2897,7 @@ fn comment_motion(
|
||||
|
||||
for _ in 0..times {
|
||||
let point = map.display_point_to_point(display_point, Bias::Left);
|
||||
let offset = point.to_offset(&map.buffer_snapshot());
|
||||
let offset = point.to_offset(&map.buffer_snapshot()).0;
|
||||
let range = if direction == Direction::Prev {
|
||||
0..offset
|
||||
} else {
|
||||
@@ -2923,7 +2930,7 @@ fn comment_motion(
|
||||
} else {
|
||||
possibilities.min().unwrap_or(offset)
|
||||
};
|
||||
let new_point = map.clip_point(dest.to_display_point(map), Bias::Left);
|
||||
let new_point = map.clip_point(MultiBufferOffset(dest).to_display_point(map), Bias::Left);
|
||||
if new_point == display_point {
|
||||
break;
|
||||
}
|
||||
@@ -2946,7 +2953,7 @@ fn section_motion(
|
||||
.display_point_to_point(display_point, Bias::Left)
|
||||
.to_offset(&map.buffer_snapshot());
|
||||
let range = if direction == Direction::Prev {
|
||||
0..offset
|
||||
MultiBufferOffset(0)..offset
|
||||
} else {
|
||||
offset..map.buffer_snapshot().len()
|
||||
};
|
||||
@@ -2977,7 +2984,7 @@ fn section_motion(
|
||||
let relevant = if is_start { range.start } else { range.end };
|
||||
if direction == Direction::Prev && relevant < offset {
|
||||
Some(relevant)
|
||||
} else if direction == Direction::Next && relevant > offset + 1 {
|
||||
} else if direction == Direction::Next && relevant > offset + 1usize {
|
||||
Some(relevant)
|
||||
} else {
|
||||
None
|
||||
@@ -2985,7 +2992,7 @@ fn section_motion(
|
||||
});
|
||||
|
||||
let offset = if direction == Direction::Prev {
|
||||
possibilities.max().unwrap_or(0)
|
||||
possibilities.max().unwrap_or(MultiBufferOffset(0))
|
||||
} else {
|
||||
possibilities.min().unwrap_or(map.buffer_snapshot().len())
|
||||
};
|
||||
|
||||
@@ -211,9 +211,14 @@ fn find_target(
|
||||
let mut pre_char = String::new();
|
||||
|
||||
// Backward scan to find the start of the number, but stop at start_offset
|
||||
for ch in snapshot.reversed_chars_at(offset + if offset < snapshot.len() { 1 } else { 0 }) {
|
||||
let next_offset = if offset < snapshot.len() {
|
||||
offset + 1usize
|
||||
} else {
|
||||
offset
|
||||
};
|
||||
for ch in snapshot.reversed_chars_at(next_offset) {
|
||||
// Search boundaries
|
||||
if offset == 0 || ch.is_whitespace() || (need_range && offset <= start_offset) {
|
||||
if offset.0 == 0 || ch.is_whitespace() || (need_range && offset <= start_offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use editor::{DisplayPoint, RowExt, SelectionEffects, display_map::ToDisplayPoint, movement};
|
||||
use editor::{
|
||||
DisplayPoint, MultiBufferOffset, RowExt, SelectionEffects, display_map::ToDisplayPoint,
|
||||
movement,
|
||||
};
|
||||
use gpui::{Action, Context, Window};
|
||||
use language::{Bias, SelectionGoal};
|
||||
use schemars::JsonSchema;
|
||||
@@ -174,7 +177,10 @@ impl Vim {
|
||||
original_indent_columns.push(original_indent_column);
|
||||
}
|
||||
|
||||
let cursor_offset = editor.selections.last::<usize>(&display_map).head();
|
||||
let cursor_offset = editor
|
||||
.selections
|
||||
.last::<MultiBufferOffset>(&display_map)
|
||||
.head();
|
||||
if editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
|
||||
+40
-26
@@ -6,7 +6,7 @@ use crate::{
|
||||
state::{Mode, Operator},
|
||||
};
|
||||
use editor::{
|
||||
Bias, DisplayPoint, Editor, ToOffset,
|
||||
Bias, BufferOffset, DisplayPoint, Editor, MultiBufferOffset, ToOffset,
|
||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||
movement::{self, FindRange},
|
||||
};
|
||||
@@ -81,8 +81,8 @@ pub struct CandidateRange {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CandidateWithRanges {
|
||||
candidate: CandidateRange,
|
||||
open_range: Range<usize>,
|
||||
close_range: Range<usize>,
|
||||
open_range: Range<MultiBufferOffset>,
|
||||
close_range: Range<MultiBufferOffset>,
|
||||
}
|
||||
|
||||
/// Selects text at the same indentation level.
|
||||
@@ -120,7 +120,7 @@ struct CurlyBrackets {
|
||||
opening: bool,
|
||||
}
|
||||
|
||||
fn cover_or_next<I: Iterator<Item = (Range<usize>, Range<usize>)>>(
|
||||
fn cover_or_next<I: Iterator<Item = (Range<MultiBufferOffset>, Range<MultiBufferOffset>)>>(
|
||||
candidates: Option<I>,
|
||||
caret: DisplayPoint,
|
||||
map: &DisplaySnapshot,
|
||||
@@ -128,7 +128,7 @@ fn cover_or_next<I: Iterator<Item = (Range<usize>, Range<usize>)>>(
|
||||
let caret_offset = caret.to_offset(map, Bias::Left);
|
||||
let mut covering = vec![];
|
||||
let mut next_ones = vec![];
|
||||
let snapshot = &map.buffer_snapshot();
|
||||
let snapshot = map.buffer_snapshot();
|
||||
|
||||
if let Some(ranges) = candidates {
|
||||
for (open_range, close_range) in ranges {
|
||||
@@ -171,7 +171,7 @@ fn cover_or_next<I: Iterator<Item = (Range<usize>, Range<usize>)>>(
|
||||
if !next_ones.is_empty() {
|
||||
return next_ones.into_iter().min_by_key(|r| {
|
||||
let start = r.candidate.start.to_offset(map, Bias::Left);
|
||||
(start as isize - caret_offset as isize).abs()
|
||||
(start.0 as isize - caret_offset.0 as isize).abs()
|
||||
});
|
||||
}
|
||||
|
||||
@@ -181,8 +181,8 @@ fn cover_or_next<I: Iterator<Item = (Range<usize>, Range<usize>)>>(
|
||||
type DelimiterPredicate = dyn Fn(&BufferSnapshot, usize, usize) -> bool;
|
||||
|
||||
struct DelimiterRange {
|
||||
open: Range<usize>,
|
||||
close: Range<usize>,
|
||||
open: Range<MultiBufferOffset>,
|
||||
close: Range<MultiBufferOffset>,
|
||||
}
|
||||
|
||||
impl DelimiterRange {
|
||||
@@ -221,14 +221,14 @@ fn find_mini_delimiters(
|
||||
.buffer_snapshot()
|
||||
.bracket_ranges(visible_line_range)
|
||||
.map(|ranges| {
|
||||
ranges.filter_map(move |(open, close)| {
|
||||
ranges.filter_map(|(open, close)| {
|
||||
// Convert the ranges from multibuffer space to buffer space as
|
||||
// that is what `is_valid_delimiter` expects, otherwise it might
|
||||
// panic as the values might be out of bounds.
|
||||
let buffer_open = excerpt.map_range_to_buffer(open.clone());
|
||||
let buffer_close = excerpt.map_range_to_buffer(close.clone());
|
||||
|
||||
if is_valid_delimiter(buffer, buffer_open.start, buffer_close.start) {
|
||||
if is_valid_delimiter(buffer, buffer_open.start.0, buffer_close.start.0) {
|
||||
Some((open, close))
|
||||
} else {
|
||||
None
|
||||
@@ -252,8 +252,12 @@ fn find_mini_delimiters(
|
||||
|
||||
Some(
|
||||
DelimiterRange {
|
||||
open: open_bracket,
|
||||
close: close_bracket,
|
||||
open: excerpt.map_range_from_buffer(
|
||||
BufferOffset(open_bracket.start)..BufferOffset(open_bracket.end),
|
||||
),
|
||||
close: excerpt.map_range_from_buffer(
|
||||
BufferOffset(close_bracket.start)..BufferOffset(close_bracket.end),
|
||||
),
|
||||
}
|
||||
.to_display_range(map, around),
|
||||
)
|
||||
@@ -899,7 +903,7 @@ pub fn surrounding_html_tag(
|
||||
// Find the most closest to current offset
|
||||
let mut cursor = buffer.syntax_layer_at(offset)?.node().walk();
|
||||
let mut last_child_node = cursor.node();
|
||||
while cursor.goto_first_child_for_byte(offset).is_some() {
|
||||
while cursor.goto_first_child_for_byte(offset.0).is_some() {
|
||||
last_child_node = cursor.node();
|
||||
}
|
||||
|
||||
@@ -916,10 +920,16 @@ pub fn surrounding_html_tag(
|
||||
- range.start.to_offset(map, Bias::Left)
|
||||
<= 1
|
||||
{
|
||||
offset <= last_child.end_byte()
|
||||
offset.0 <= last_child.end_byte()
|
||||
} else {
|
||||
range.start.to_offset(map, Bias::Left) >= first_child.start_byte()
|
||||
&& range.end.to_offset(map, Bias::Left) <= last_child.start_byte() + 1
|
||||
excerpt
|
||||
.map_offset_to_buffer(range.start.to_offset(map, Bias::Left))
|
||||
.0
|
||||
>= first_child.start_byte()
|
||||
&& excerpt
|
||||
.map_offset_to_buffer(range.end.to_offset(map, Bias::Left))
|
||||
.0
|
||||
<= last_child.start_byte() + 1
|
||||
};
|
||||
if open_tag.is_some() && open_tag == close_tag && is_valid {
|
||||
let range = if around {
|
||||
@@ -927,6 +937,7 @@ pub fn surrounding_html_tag(
|
||||
} else {
|
||||
first_child.byte_range().end..last_child.byte_range().start
|
||||
};
|
||||
let range = BufferOffset(range.start)..BufferOffset(range.end);
|
||||
if excerpt.contains_buffer_range(range.clone()) {
|
||||
let result = excerpt.map_range_from_buffer(range);
|
||||
return Some(
|
||||
@@ -1093,7 +1104,8 @@ fn text_object(
|
||||
.collect();
|
||||
matches.sort_by_key(|r| r.end - r.start);
|
||||
if let Some(buffer_range) = matches.first() {
|
||||
let range = excerpt.map_range_from_buffer(buffer_range.clone());
|
||||
let buffer_range = BufferOffset(buffer_range.start)..BufferOffset(buffer_range.end);
|
||||
let range = excerpt.map_range_from_buffer(buffer_range);
|
||||
return Some(range.start.to_display_point(map)..range.end.to_display_point(map));
|
||||
}
|
||||
|
||||
@@ -1113,10 +1125,12 @@ fn text_object(
|
||||
if let Some(buffer_range) = matches.first()
|
||||
&& !buffer_range.is_empty()
|
||||
{
|
||||
let range = excerpt.map_range_from_buffer(buffer_range.clone());
|
||||
let buffer_range = BufferOffset(buffer_range.start)..BufferOffset(buffer_range.end);
|
||||
let range = excerpt.map_range_from_buffer(buffer_range);
|
||||
return Some(range.start.to_display_point(map)..range.end.to_display_point(map));
|
||||
}
|
||||
let buffer_range = excerpt.map_range_from_buffer(around_range.clone());
|
||||
let around_range = BufferOffset(around_range.start)..BufferOffset(around_range.end);
|
||||
let buffer_range = excerpt.map_range_from_buffer(around_range);
|
||||
return Some(buffer_range.start.to_display_point(map)..buffer_range.end.to_display_point(map));
|
||||
}
|
||||
|
||||
@@ -1134,9 +1148,9 @@ fn argument(
|
||||
|
||||
fn comma_delimited_range_at(
|
||||
buffer: &BufferSnapshot,
|
||||
mut offset: usize,
|
||||
mut offset: BufferOffset,
|
||||
include_comma: bool,
|
||||
) -> Option<Range<usize>> {
|
||||
) -> Option<Range<BufferOffset>> {
|
||||
// Seek to the first non-whitespace character
|
||||
offset += buffer
|
||||
.chars_at(offset)
|
||||
@@ -1151,7 +1165,7 @@ fn argument(
|
||||
}
|
||||
|
||||
// If the cursor is outside the brackets, ignore them
|
||||
if open.start == offset || close.end == offset {
|
||||
if open.start == offset.0 || close.end == offset.0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1167,7 +1181,7 @@ fn argument(
|
||||
let (open_bracket, close_bracket) =
|
||||
buffer.innermost_enclosing_bracket_ranges(offset..offset, Some(&bracket_filter))?;
|
||||
|
||||
let inner_bracket_range = open_bracket.end..close_bracket.start;
|
||||
let inner_bracket_range = BufferOffset(open_bracket.end)..BufferOffset(close_bracket.start);
|
||||
|
||||
let layer = buffer.syntax_layer_at(offset)?;
|
||||
let node = layer.node();
|
||||
@@ -1186,7 +1200,7 @@ fn argument(
|
||||
parent_covers_bracket_range = covers_bracket_range;
|
||||
|
||||
// Unable to find a child node with a parent that covers the bracket range, so no argument to select
|
||||
cursor.goto_first_child_for_byte(offset)?;
|
||||
cursor.goto_first_child_for_byte(offset.0)?;
|
||||
}
|
||||
|
||||
let mut argument_node = cursor.node();
|
||||
@@ -1256,7 +1270,7 @@ fn argument(
|
||||
}
|
||||
}
|
||||
|
||||
Some(start..end)
|
||||
Some(BufferOffset(start)..BufferOffset(end))
|
||||
}
|
||||
|
||||
let result = comma_delimited_range_at(buffer, excerpt.map_offset_to_buffer(offset), around)?;
|
||||
@@ -1387,7 +1401,7 @@ fn is_possible_sentence_start(character: char) -> bool {
|
||||
const SENTENCE_END_PUNCTUATION: &[char] = &['.', '!', '?'];
|
||||
const SENTENCE_END_FILLERS: &[char] = &[')', ']', '"', '\''];
|
||||
const SENTENCE_END_WHITESPACE: &[char] = &[' ', '\t', '\n'];
|
||||
fn is_sentence_end(map: &DisplaySnapshot, offset: usize) -> bool {
|
||||
fn is_sentence_end(map: &DisplaySnapshot, offset: MultiBufferOffset) -> bool {
|
||||
let mut next_chars = map.buffer_chars_at(offset).peekable();
|
||||
if let Some((char, _)) = next_chars.next() {
|
||||
// We are at a double newline. This position is a sentence end.
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
object::{Object, surrounding_markers},
|
||||
state::Mode,
|
||||
};
|
||||
use editor::{Bias, movement};
|
||||
use editor::{Bias, MultiBufferOffset, movement};
|
||||
use gpui::{Context, Window};
|
||||
use language::BracketPair;
|
||||
|
||||
@@ -175,7 +175,7 @@ impl Vim {
|
||||
while let Some((ch, offset)) = chars_and_offset.next() {
|
||||
if ch.to_string() == pair.start {
|
||||
let start = offset;
|
||||
let mut end = start + 1;
|
||||
let mut end = start + 1usize;
|
||||
if surround
|
||||
&& let Some((next_ch, _)) = chars_and_offset.peek()
|
||||
&& next_ch.eq(&' ')
|
||||
@@ -193,7 +193,7 @@ impl Vim {
|
||||
while let Some((ch, offset)) = reverse_chars_and_offsets.next() {
|
||||
if ch.to_string() == pair.end {
|
||||
let mut start = offset;
|
||||
let end = start + 1;
|
||||
let end = start + 1usize;
|
||||
if surround
|
||||
&& let Some((next_ch, _)) = reverse_chars_and_offsets.peek()
|
||||
&& next_ch.eq(&' ')
|
||||
@@ -282,7 +282,7 @@ impl Vim {
|
||||
// that the end replacement string does not exceed
|
||||
// this value. Helpful when dealing with newlines.
|
||||
let mut edit_len = 0;
|
||||
let mut open_range_end = 0;
|
||||
let mut open_range_end = MultiBufferOffset(0);
|
||||
let mut chars_and_offset = display_map
|
||||
.buffer_chars_at(range.start.to_offset(&display_map, Bias::Left))
|
||||
.peekable();
|
||||
@@ -291,7 +291,7 @@ impl Vim {
|
||||
if ch.to_string() == will_replace_pair.start {
|
||||
let mut open_str = pair.start.clone();
|
||||
let start = offset;
|
||||
open_range_end = start + 1;
|
||||
open_range_end = start + 1usize;
|
||||
while let Some((next_ch, _)) = chars_and_offset.next()
|
||||
&& next_ch == ' '
|
||||
{
|
||||
@@ -322,7 +322,7 @@ impl Vim {
|
||||
if ch.to_string() == will_replace_pair.end {
|
||||
let mut close_str = String::new();
|
||||
let mut start = offset;
|
||||
let end = start + 1;
|
||||
let end = start + 1usize;
|
||||
while let Some((next_ch, _)) = reverse_chars_and_offsets.next()
|
||||
&& next_ch == ' '
|
||||
&& close_str.len() < edit_len - 1
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{sync::Arc, time::Duration};
|
||||
use collections::HashMap;
|
||||
use command_palette::CommandPalette;
|
||||
use editor::{
|
||||
AnchorRangeExt, DisplayPoint, Editor, EditorMode, MultiBuffer,
|
||||
AnchorRangeExt, DisplayPoint, Editor, EditorMode, MultiBuffer, MultiBufferOffset,
|
||||
actions::{DeleteLine, WrapSelectionsInTag},
|
||||
code_context_menus::CodeContextMenu,
|
||||
display_map::DisplayRow,
|
||||
@@ -908,6 +908,9 @@ fn assert_pending_input(cx: &mut VimTestContext, expected: &str) {
|
||||
.map(|highlight| highlight.to_offset(&snapshot.buffer_snapshot()))
|
||||
.collect::<Vec<_>>(),
|
||||
ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
});
|
||||
}
|
||||
@@ -967,7 +970,7 @@ async fn test_jk_delay(cx: &mut gpui::TestAppContext) {
|
||||
.iter()
|
||||
.map(|highlight| highlight.to_offset(&snapshot.buffer_snapshot()))
|
||||
.collect::<Vec<_>>(),
|
||||
vec![0..1]
|
||||
vec![MultiBufferOffset(0)..MultiBufferOffset(1)]
|
||||
)
|
||||
});
|
||||
cx.executor().advance_clock(Duration::from_millis(500));
|
||||
|
||||
@@ -21,8 +21,8 @@ mod visual;
|
||||
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
Anchor, Bias, Editor, EditorEvent, EditorSettings, HideMouseCursorOrigin, SelectionEffects,
|
||||
ToPoint,
|
||||
Anchor, Bias, Editor, EditorEvent, EditorSettings, HideMouseCursorOrigin, MultiBufferOffset,
|
||||
SelectionEffects, ToPoint,
|
||||
actions::Paste,
|
||||
movement::{self, FindRange},
|
||||
};
|
||||
@@ -1388,7 +1388,7 @@ impl Vim {
|
||||
let newest_selection_empty = editor.update(cx, |editor, cx| {
|
||||
editor
|
||||
.selections
|
||||
.newest::<usize>(&editor.display_snapshot(cx))
|
||||
.newest::<MultiBufferOffset>(&editor.display_snapshot(cx))
|
||||
.is_empty()
|
||||
});
|
||||
let editor = editor.read(cx);
|
||||
@@ -1488,7 +1488,7 @@ impl Vim {
|
||||
let snapshot = &editor.snapshot(window, cx);
|
||||
let selection = editor
|
||||
.selections
|
||||
.newest::<usize>(&snapshot.display_snapshot);
|
||||
.newest::<MultiBufferOffset>(&snapshot.display_snapshot);
|
||||
|
||||
let snapshot = snapshot.buffer_snapshot();
|
||||
let (range, kind) =
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
Bias, DisplayPoint, Editor, SelectionEffects,
|
||||
Bias, DisplayPoint, Editor, MultiBufferOffset, SelectionEffects,
|
||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||
movement,
|
||||
};
|
||||
@@ -778,7 +778,7 @@ impl Vim {
|
||||
{
|
||||
let range = row_range.start.to_offset(&display_map, Bias::Right)
|
||||
..row_range.end.to_offset(&display_map, Bias::Right);
|
||||
let text = text.repeat(range.len());
|
||||
let text = text.repeat(range.end - range.start);
|
||||
edits.push((range, text));
|
||||
}
|
||||
}
|
||||
@@ -844,8 +844,8 @@ impl Vim {
|
||||
return;
|
||||
};
|
||||
let vim_is_normal = self.mode == Mode::Normal;
|
||||
let mut start_selection = 0usize;
|
||||
let mut end_selection = 0usize;
|
||||
let mut start_selection = MultiBufferOffset(0);
|
||||
let mut end_selection = MultiBufferOffset(0);
|
||||
|
||||
self.update_editor(cx, |_, editor, _| {
|
||||
editor.set_collapse_matches(false);
|
||||
@@ -868,7 +868,7 @@ impl Vim {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
let latest = editor
|
||||
.selections
|
||||
.newest::<usize>(&editor.display_snapshot(cx));
|
||||
.newest::<MultiBufferOffset>(&editor.display_snapshot(cx));
|
||||
start_selection = latest.start;
|
||||
end_selection = latest.end;
|
||||
});
|
||||
@@ -891,7 +891,7 @@ impl Vim {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
let latest = editor
|
||||
.selections
|
||||
.newest::<usize>(&editor.display_snapshot(cx));
|
||||
.newest::<MultiBufferOffset>(&editor.display_snapshot(cx));
|
||||
if vim_is_normal {
|
||||
start_selection = latest.start;
|
||||
end_selection = latest.end;
|
||||
|
||||
Reference in New Issue
Block a user