Implement iter() and len() directly on Selection.

This commit is contained in:
Blaž Hrastnik 2021-03-19 11:14:13 +09:00
parent e9bd9e72c3
commit f29f01858d
5 changed files with 27 additions and 12 deletions

View file

@ -44,7 +44,7 @@ pub fn toggle_line_comments(doc: &Rope, selection: &Selection) -> Transaction {
let token = "//";
let comment = Tendril::from(format!("{} ", token));
for selection in selection.ranges() {
for selection in selection {
let start = text.char_to_line(selection.from());
let end = text.char_to_line(selection.to());
let lines = start..end + 1;

View file

@ -269,6 +269,25 @@ impl Selection {
pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
self.ranges.iter().map(move |range| range.fragment(text))
}
#[inline(always)]
pub fn iter(&self) -> std::slice::Iter<'_, Range> {
self.ranges.iter()
}
#[inline(always)]
pub fn len(&self) -> usize {
self.ranges.len()
}
}
impl<'a> IntoIterator for &'a Selection {
type Item = &'a Range;
type IntoIter = std::slice::Iter<'a, Range>;
fn into_iter(self) -> std::slice::Iter<'a, Range> {
self.ranges().iter()
}
}
// TODO: checkSelection -> check if valid for doc length
@ -279,7 +298,6 @@ pub fn keep_matches(
regex: &crate::regex::Regex,
) -> Option<Selection> {
let result: SmallVec<_> = selection
.ranges()
.iter()
.filter(|range| regex.is_match(&range.fragment(text)))
.copied()
@ -297,9 +315,9 @@ pub fn select_on_matches(
selection: &Selection,
regex: &crate::regex::Regex,
) -> Option<Selection> {
let mut result = SmallVec::with_capacity(selection.ranges().len());
let mut result = SmallVec::with_capacity(selection.len());
for sel in selection.ranges() {
for sel in selection {
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(text);
@ -331,9 +349,9 @@ pub fn split_on_matches(
selection: &Selection,
regex: &crate::regex::Regex,
) -> Selection {
let mut result = SmallVec::with_capacity(selection.ranges().len());
let mut result = SmallVec::with_capacity(selection.len());
for sel in selection.ranges() {
for sel in selection {
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(text);

View file

@ -494,7 +494,7 @@ impl Transaction {
where
F: FnMut(&Range) -> Change,
{
Self::change(doc, selection.ranges().iter().map(f))
Self::change(doc, selection.iter().map(f))
}
/// Insert text at each selection head.

View file

@ -781,7 +781,6 @@ pub fn buffer_picker(cx: &mut Context) {
// calculate line numbers for each selection range
fn selection_lines(doc: &Rope, selection: &Selection) -> Vec<usize> {
let mut lines = selection
.ranges()
.iter()
.map(|range| doc.char_to_line(range.head))
.collect::<Vec<_>>();
@ -1145,7 +1144,7 @@ fn get_lines(doc: &Document) -> Vec<usize> {
let mut lines = Vec::new();
// Get all line numbers
for range in doc.selection().ranges() {
for range in doc.selection() {
let start = doc.text().char_to_line(range.from());
let end = doc.text().char_to_line(range.to());
@ -1220,7 +1219,6 @@ pub fn format_selections(cx: &mut Context) {
let ranges: Vec<lsp::Range> = doc
.selection()
.ranges()
.iter()
.map(|range| helix_lsp::util::range_to_lsp_range(doc.text(), *range))
.collect();
@ -1257,7 +1255,7 @@ pub fn join_selections(cx: &mut Context) {
let mut changes = Vec::new();
let fragment = Tendril::from(" ");
for selection in doc.selection().ranges() {
for selection in doc.selection() {
let start = text.char_to_line(selection.from());
let mut end = text.char_to_line(selection.to());
if start == end {

View file

@ -211,7 +211,6 @@ impl EditorView {
for selection in view
.doc
.selection()
.ranges()
.iter()
.filter(|range| range.overlaps(&screen))
{