Make textobject select last paragraph (#1992)

* Make textobject select last paragraph

Last paragraph shoud be selected if the cursor was placed on the
whitespace paragraph part and `map` is done, otherwise it would do
nothing useful, but now we select backwards for the last paragraph
which behaves similarly to kakoune, making `map` useful for the last
paragraph with whitespace. Example usecase is to copy and paste last
ledger cli paragraph quickly by `mapyp` to duplicate last entry.

* Fix typo in core textobject

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
pull/2094/head
Ivan Tham 3 years ago committed by GitHub
parent a0c6c45c1b
commit 62283fdadb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -132,9 +132,9 @@ pub fn textobject_paragraph(
if prev_empty_to_line || curr_empty_to_line { if prev_empty_to_line || curr_empty_to_line {
line_back += 1; line_back += 1;
} }
let mut lines = slice.lines_at(line_back);
// do not include current paragraph on paragraph end (include next) // do not include current paragraph on paragraph end (include next)
if !(curr_empty_to_line && last_char) { if !(curr_empty_to_line && last_char) {
let mut lines = slice.lines_at(line_back);
lines.reverse(); lines.reverse();
let mut lines = lines.map(rope_is_line_ending).peekable(); let mut lines = lines.map(rope_is_line_ending).peekable();
while lines.next_if(|&e| e).is_some() { while lines.next_if(|&e| e).is_some() {
@ -150,25 +150,46 @@ pub fn textobject_paragraph(
line += 1; line += 1;
} }
let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable(); 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() { while lines.next_if(|&e| !e).is_some() {
line += 1; line += 1;
done = true;
} }
while lines.next_if(|&e| e).is_some() { while lines.next_if(|&e| e).is_some() {
line += 1; line += 1;
} }
count_done += done as usize;
}
// 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() { while lines.next_if(|&e| !e).is_some() {
line += 1; line_back -= 1;
} }
}
// handle last whitespaces part separately depending on textobject // handle last whitespaces part separately depending on textobject
match 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() { while lines.next_if(|&e| e).is_some() {
line += 1; line -= 1;
} }
} }
TextObject::Inside => {}
TextObject::Movement => unreachable!(), TextObject::Movement => unreachable!(),
} }
@ -364,7 +385,7 @@ mod test {
"second\n\n#[paragraph\n|]#\n", "second\n\n#[paragraph\n|]#\n",
), ),
("#[f|]#irst char\n\n", "#[first char\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",
"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|]#", "second\n\n#[paragraph\n\n|]#",
), ),
("#[f|]#irst char\n\n", "#[first char\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",
"empty to line\n\n#[paragraph boundary\n\n|]#", "empty to line\n\n#[paragraph boundary\n\n|]#",

Loading…
Cancel
Save