summaryrefslogtreecommitdiff
path: root/helix-core/src/textobject.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/textobject.rs')
-rw-r--r--helix-core/src/textobject.rs39
1 files changed, 30 insertions, 9 deletions
diff --git a/helix-core/src/textobject.rs b/helix-core/src/textobject.rs
index e7bbfc43..ab418792 100644
--- a/helix-core/src/textobject.rs
+++ b/helix-core/src/textobject.rs
@@ -132,9 +132,9 @@ pub fn textobject_paragraph(
if prev_empty_to_line || curr_empty_to_line {
line_back += 1;
}
- let mut lines = slice.lines_at(line_back);
// do not include current paragraph on paragraph end (include next)
if !(curr_empty_to_line && last_char) {
+ let mut lines = slice.lines_at(line_back);
lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() {
@@ -150,25 +150,46 @@ pub fn textobject_paragraph(
line += 1;
}
let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
- for _ in 0..count - 1 {
+ let mut count_done = 0; // count how many non-whitespace paragraphs done
+ for _ in 0..count {
+ let mut done = false;
while lines.next_if(|&e| !e).is_some() {
line += 1;
+ done = true;
}
while lines.next_if(|&e| e).is_some() {
line += 1;
}
+ count_done += done as usize;
}
- while lines.next_if(|&e| !e).is_some() {
- line += 1;
+
+ // search one paragraph backwards for last paragraph
+ // makes `map` at the end of the paragraph with trailing newlines useful
+ let last_paragraph = count_done != count && lines.peek().is_none();
+ if last_paragraph {
+ let mut lines = slice.lines_at(line_back);
+ lines.reverse();
+ let mut lines = lines.map(rope_is_line_ending).peekable();
+ while lines.next_if(|&e| e).is_some() {
+ line_back -= 1;
+ }
+ while lines.next_if(|&e| !e).is_some() {
+ line_back -= 1;
+ }
}
+
// handle last whitespaces part separately depending on textobject
match textobject {
- TextObject::Around => {
+ TextObject::Around => {}
+ TextObject::Inside => {
+ // remove last whitespace paragraph
+ let mut lines = slice.lines_at(line);
+ lines.reverse();
+ let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() {
- line += 1;
+ line -= 1;
}
}
- TextObject::Inside => {}
TextObject::Movement => unreachable!(),
}
@@ -364,7 +385,7 @@ mod test {
"second\n\n#[paragraph\n|]#\n",
),
("#[f|]#irst char\n\n", "#[first char\n|]#\n"),
- ("last char\n#[\n|]#", "last char\n\n#[|]#"),
+ ("last char\n#[\n|]#", "#[last char\n|]#\n"),
(
"empty to line\n#[\n|]#paragraph boundary\n\n",
"empty to line\n\n#[paragraph boundary\n|]#\n",
@@ -418,7 +439,7 @@ mod test {
"second\n\n#[paragraph\n\n|]#",
),
("#[f|]#irst char\n\n", "#[first char\n\n|]#"),
- ("last char\n#[\n|]#", "last char\n\n#[|]#"),
+ ("last char\n#[\n|]#", "#[last char\n\n|]#"),
(
"empty to line\n#[\n|]#paragraph boundary\n\n",
"empty to line\n\n#[paragraph boundary\n\n|]#",