Skip to content

Commit

Permalink
Make textobject select last paragraph (#1992)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

Co-authored-by: Michael Davis <[email protected]>
  • Loading branch information
pickfire and the-mikedavis authored Apr 13, 2022
1 parent a0c6c45 commit 62283fd
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions helix-core/src/textobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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!(),
}

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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|]#",
Expand Down

0 comments on commit 62283fd

Please sign in to comment.