diff options
author | Ivan Tham | 2022-04-13 01:02:53 +0000 |
---|---|---|
committer | GitHub | 2022-04-13 01:02:53 +0000 |
commit | 62283fdadb762d77deaba7ff820fbdac0b2d3a3b (patch) | |
tree | bed99274678beba6d73a48939f90a0536d4829b5 | |
parent | a0c6c45c1b5dc36f3c5151363d3f360bea388a99 (diff) |
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>
-rw-r--r-- | helix-core/src/textobject.rs | 39 |
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|]#", |