mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 11:29:25 +00:00
Add a new movement::surrounding_word
function
This commit is contained in:
parent
005a7076af
commit
a0ea5b38a0
2 changed files with 125 additions and 25 deletions
|
@ -169,7 +169,7 @@ impl DisplayMap {
|
|||
}
|
||||
|
||||
pub struct DisplayMapSnapshot {
|
||||
buffer_snapshot: language::Snapshot,
|
||||
pub buffer_snapshot: language::Snapshot,
|
||||
folds_snapshot: fold_map::Snapshot,
|
||||
tabs_snapshot: tab_map::Snapshot,
|
||||
wraps_snapshot: wrap_map::Snapshot,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use super::{Bias, DisplayMapSnapshot, DisplayPoint, SelectionGoal};
|
||||
use super::{Bias, DisplayMapSnapshot, DisplayPoint, SelectionGoal, ToDisplayPoint};
|
||||
use anyhow::Result;
|
||||
use buffer::ToPoint;
|
||||
use std::{cmp, ops::Range};
|
||||
|
||||
pub fn left(map: &DisplayMapSnapshot, mut point: DisplayPoint) -> Result<DisplayPoint> {
|
||||
if point.column() > 0 {
|
||||
|
@ -113,10 +115,7 @@ pub fn line_end(map: &DisplayMapSnapshot, point: DisplayPoint) -> Result<Display
|
|||
Ok(map.clip_point(line_end, Bias::Left))
|
||||
}
|
||||
|
||||
pub fn prev_word_boundary(
|
||||
map: &DisplayMapSnapshot,
|
||||
mut point: DisplayPoint,
|
||||
) -> Result<DisplayPoint> {
|
||||
pub fn prev_word_boundary(map: &DisplayMapSnapshot, mut point: DisplayPoint) -> DisplayPoint {
|
||||
let mut line_start = 0;
|
||||
if point.row() > 0 {
|
||||
if let Some(indent) = map.soft_wrap_indent(point.row() - 1) {
|
||||
|
@ -126,7 +125,7 @@ pub fn prev_word_boundary(
|
|||
|
||||
if point.column() == line_start {
|
||||
if point.row() == 0 {
|
||||
return Ok(DisplayPoint::new(0, 0));
|
||||
return DisplayPoint::new(0, 0);
|
||||
} else {
|
||||
let row = point.row() - 1;
|
||||
point = map.clip_point(DisplayPoint::new(row, map.line_len(row)), Bias::Left);
|
||||
|
@ -152,13 +151,10 @@ pub fn prev_word_boundary(
|
|||
prev_char_kind = char_kind;
|
||||
column += c.len_utf8() as u32;
|
||||
}
|
||||
Ok(boundary)
|
||||
boundary
|
||||
}
|
||||
|
||||
pub fn next_word_boundary(
|
||||
map: &DisplayMapSnapshot,
|
||||
mut point: DisplayPoint,
|
||||
) -> Result<DisplayPoint> {
|
||||
pub fn next_word_boundary(map: &DisplayMapSnapshot, mut point: DisplayPoint) -> DisplayPoint {
|
||||
let mut prev_char_kind = None;
|
||||
for c in map.chars_at(point) {
|
||||
let char_kind = char_kind(c);
|
||||
|
@ -182,14 +178,46 @@ pub fn next_word_boundary(
|
|||
}
|
||||
prev_char_kind = Some(char_kind);
|
||||
}
|
||||
Ok(point)
|
||||
point
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub fn surrounding_word(map: &DisplayMapSnapshot, point: DisplayPoint) -> Range<DisplayPoint> {
|
||||
let mut start = map.clip_point(point, Bias::Left).to_offset(map, Bias::Left);
|
||||
let mut end = start;
|
||||
|
||||
let text = map.buffer_snapshot.text();
|
||||
let mut next_chars = text.chars_at(start).peekable();
|
||||
let mut prev_chars = text.reversed_chars_at(start).peekable();
|
||||
let word_kind = cmp::max(
|
||||
prev_chars.peek().copied().map(char_kind),
|
||||
next_chars.peek().copied().map(char_kind),
|
||||
);
|
||||
|
||||
for ch in prev_chars {
|
||||
if Some(char_kind(ch)) == word_kind {
|
||||
start -= ch.len_utf8();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ch in next_chars {
|
||||
if Some(char_kind(ch)) == word_kind {
|
||||
end += ch.len_utf8();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start.to_point(&map.buffer_snapshot).to_display_point(map)
|
||||
..end.to_point(&map.buffer_snapshot).to_display_point(map)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||
enum CharKind {
|
||||
Newline,
|
||||
Whitespace,
|
||||
Punctuation,
|
||||
Whitespace,
|
||||
Word,
|
||||
}
|
||||
|
||||
|
@ -225,45 +253,117 @@ mod tests {
|
|||
cx.add_model(|cx| DisplayMap::new(buffer, tab_size, font_id, font_size, None, cx));
|
||||
let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
assert_eq!(
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 12)).unwrap(),
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 12)),
|
||||
DisplayPoint::new(0, 7)
|
||||
);
|
||||
assert_eq!(
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 7)).unwrap(),
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 7)),
|
||||
DisplayPoint::new(0, 2)
|
||||
);
|
||||
assert_eq!(
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 6)).unwrap(),
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 6)),
|
||||
DisplayPoint::new(0, 2)
|
||||
);
|
||||
assert_eq!(
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 2)).unwrap(),
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 2)),
|
||||
DisplayPoint::new(0, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 1)).unwrap(),
|
||||
prev_word_boundary(&snapshot, DisplayPoint::new(0, 1)),
|
||||
DisplayPoint::new(0, 0)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 0)).unwrap(),
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 0)),
|
||||
DisplayPoint::new(0, 1)
|
||||
);
|
||||
assert_eq!(
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 1)).unwrap(),
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 1)),
|
||||
DisplayPoint::new(0, 6)
|
||||
);
|
||||
assert_eq!(
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 2)).unwrap(),
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 2)),
|
||||
DisplayPoint::new(0, 6)
|
||||
);
|
||||
assert_eq!(
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 6)).unwrap(),
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 6)),
|
||||
DisplayPoint::new(0, 12)
|
||||
);
|
||||
assert_eq!(
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 7)).unwrap(),
|
||||
next_word_boundary(&snapshot, DisplayPoint::new(0, 7)),
|
||||
DisplayPoint::new(0, 12)
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_surrounding_word(cx: &mut gpui::MutableAppContext) {
|
||||
let tab_size = 4;
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
let font_size = 14.0;
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, "lorem ipsum dolor\n sit", cx));
|
||||
let display_map =
|
||||
cx.add_model(|cx| DisplayMap::new(buffer, tab_size, font_id, font_size, None, cx));
|
||||
let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 0)),
|
||||
DisplayPoint::new(0, 0)..DisplayPoint::new(0, 5)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 2)),
|
||||
DisplayPoint::new(0, 0)..DisplayPoint::new(0, 5)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 5)),
|
||||
DisplayPoint::new(0, 0)..DisplayPoint::new(0, 5)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 6)),
|
||||
DisplayPoint::new(0, 6)..DisplayPoint::new(0, 11)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 7)),
|
||||
DisplayPoint::new(0, 6)..DisplayPoint::new(0, 11)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 11)),
|
||||
DisplayPoint::new(0, 6)..DisplayPoint::new(0, 11)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 13)),
|
||||
DisplayPoint::new(0, 11)..DisplayPoint::new(0, 14)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 14)),
|
||||
DisplayPoint::new(0, 14)..DisplayPoint::new(0, 19)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 17)),
|
||||
DisplayPoint::new(0, 14)..DisplayPoint::new(0, 19)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(0, 19)),
|
||||
DisplayPoint::new(0, 14)..DisplayPoint::new(0, 19)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(1, 0)),
|
||||
DisplayPoint::new(1, 0)..DisplayPoint::new(1, 4)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(1, 1)),
|
||||
DisplayPoint::new(1, 0)..DisplayPoint::new(1, 4)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(1, 6)),
|
||||
DisplayPoint::new(1, 4)..DisplayPoint::new(1, 7)
|
||||
);
|
||||
assert_eq!(
|
||||
surrounding_word(&snapshot, DisplayPoint::new(1, 7)),
|
||||
DisplayPoint::new(1, 4)..DisplayPoint::new(1, 7)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue