Add new argument
vim text object (#7791)
This PR adds a new `argument` vim text object, inspired by [targets.vim](https://github.com/wellle/targets.vim). As it's the first vim text object to use the syntax tree, it needed to operate on the `Buffer` level, not the `MultiBuffer` level, then map the buffer coordinates to `DisplayPoint` as necessary. This required two main changes: 1. `innermost_enclosing_bracket_ranges` and `enclosing_bracket_ranges` were moved into `Buffer`. The `MultiBuffer` implementations were updated to map to/from these. 2. `MultiBuffer::excerpt_containing` was made public, returning a new `MultiBufferExcerpt` type that contains a reference to the excerpt and methods for mapping to/from `Buffer` and `MultiBuffer` offsets and ranges. Release Notes: - Added new `argument` vim text object, inspired by [targets.vim](https://github.com/wellle/targets.vim).
This commit is contained in:
parent
dc7e14f888
commit
2e616f8388
5 changed files with 392 additions and 93 deletions
|
@ -2492,7 +2492,7 @@ impl BufferSnapshot {
|
|||
self.syntax.layers_for_range(0..self.len(), &self.text)
|
||||
}
|
||||
|
||||
fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer> {
|
||||
pub fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer> {
|
||||
let offset = position.to_offset(self);
|
||||
self.syntax
|
||||
.layers_for_range(offset..offset, &self.text)
|
||||
|
@ -2886,6 +2886,52 @@ impl BufferSnapshot {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns enclosing bracket ranges containing the given range
|
||||
pub fn enclosing_bracket_ranges<T: ToOffset>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + '_ {
|
||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||
|
||||
self.bracket_ranges(range.clone())
|
||||
.filter(move |(open, close)| open.start <= range.start && close.end >= range.end)
|
||||
}
|
||||
|
||||
/// Returns the smallest enclosing bracket ranges containing the given range or None if no brackets contain range
|
||||
///
|
||||
/// Can optionally pass a range_filter to filter the ranges of brackets to consider
|
||||
pub fn innermost_enclosing_bracket_ranges<T: ToOffset>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
range_filter: Option<&dyn Fn(Range<usize>, Range<usize>) -> bool>,
|
||||
) -> Option<(Range<usize>, Range<usize>)> {
|
||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||
|
||||
// Get the ranges of the innermost pair of brackets.
|
||||
let mut result: Option<(Range<usize>, Range<usize>)> = None;
|
||||
|
||||
for (open, close) in self.enclosing_bracket_ranges(range.clone()) {
|
||||
if let Some(range_filter) = range_filter {
|
||||
if !range_filter(open.clone(), close.clone()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let len = close.end - open.start;
|
||||
|
||||
if let Some((existing_open, existing_close)) = &result {
|
||||
let existing_len = existing_close.end - existing_open.start;
|
||||
if len > existing_len {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result = Some((open, close));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns anchor ranges for any matches of the redaction query.
|
||||
/// The buffer can be associated with multiple languages, and the redaction query associated with each
|
||||
/// will be run on the relevant section of the buffer.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue