Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add auto pairs for same-char pairs #1219

Merged
merged 6 commits into from
Dec 13, 2021
Merged

Conversation

dead10ck
Copy link
Member

@dead10ck dead10ck commented Dec 2, 2021

Changes

  • Add unit tests for all existing functionality
  • Add auto pairs for same-char pairs (quotes, etc). Account for apostrophe in prose by requiring both sides of the cursor to be non-pair chars or whitespace
  • Slight factor of moving the cursor transform of the selection to inside the hooks. This will enable doing auto pairing with selections, and fixing the bug where auto pairs destroy the selection.

I will still be working on other things, but I thought it would be a good idea to make an incremental smaller PR for the sake of ease of review, and for providing opportunity for feedback with the approach to testing and implementation details before I build further on them.

Fixes #1014

Things I'd still like to do:

  • delete implementation where it erases the whole bracket (|) -> |
  • do not reduce to cursors; use whole selections, and surround with pair
  • change to multi character pairs to handle cases like placing the cursor in the middle of triple quotes, and more exotic pairs like Jinja's {% %}
  • add more granular config for particular pairs and behaviors as discussed in Enable config for auto-pairs #992

In particular about the auto pairing with selections, I think when we have a case like (where [] is the selection)

[wor]d

and we enter insert mode and type ", we could either unconditionally surround the selection and make

"[wor]"d

so it behaves exactly like surround, or we could choose only to surround when both sides of the selection are non-pair chars or whitespace, extending the current behavior to selections, so

"[wor]d

I'm on the fence about it, so any guidance there would be helpful.

)
}

// [TODO] broken until it works with selections
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort of addressed bybmsa"(match surrounding add ()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just to be clear, are you saying we shouldn't worry about adding surround functionality with selections? Or just that this particular case should just be inserting a ( before the word, but if the whole word was selected, do the surround?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've fixed this test, although it's still broken until I add the changes for selections.

@archseer
Copy link
Member

archseer commented Dec 2, 2021

Great work! I need to give this a full read later but it's especially great to see test coverage being added :)

@dead10ck dead10ck force-pushed the auto_pairs branch 7 times, most recently from 0621b85 to bc4c38d Compare December 8, 2021 03:39
Comment on lines 61 to 66
fn next_char(doc: &Rope, pos: usize) -> Option<char> {
if pos >= doc.len_chars() {
return None;
}
Some(doc.char(pos))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be replaced by doc.get_char(pos) now, ropey added a non-panicking variant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, done.

fn handle_open(
doc: &Rope,
selection: &Selection,
open: char,
close: char,
close_before: &str,
) -> Transaction {
let mut ranges = SmallVec::with_capacity(selection.len());
let mut end_ranges = SmallVec::with_capacity(selection.len());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the rename? It looks like all the variables in _open and _close were renamed but nothing else was changed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, sorry, this was mostly for my own benefit to better understand the code. When building the final range, in the anchor position, it's offset inline, but the head is in a variable that was defined above. And to me pos (i.e. position) and head are kind of synonymous, and it was hard to follow that one is what we started with and the other is what we want it to be after the text transformation. Are you okay with the changes?

start_range.anchor + offs
};

// if selection, retain anchor, if cursor, move over
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment would be better suited above the let end_anchor

Copy link
Member Author

@dead10ck dead10ck Dec 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Also, it's worth noting that the if expression is currently a tautology because the selection is transformed into cursors before this code is hit. I kept it because something like it will be necessary when I get to fixing selections (which I'm pretty close to now).

// return transaction that moves past close
(start_head, start_head, None) // no-op
} else {
let mut pair = Tendril::with_capacity(2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses bytes as the capacity, you probably want 2 * token.len_utf8()

Copy link
Member

@archseer archseer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me but I'd like to get one more reviewer

/cc @sudormrfbin

* Add unit tests for all existing functionality
* Add auto pairs for same-char pairs (quotes, etc). Account for
  apostrophe in prose by requiring both sides of the cursor to be
  non-pair chars or whitespace. This also incidentally will work for
  avoiding a double single quote in lifetime annotations, at least until
  <> is added
* Slight factor of moving the cursor transform of the selection to
  inside the hooks. This will enable doing auto pairing with selections,
  and fixing the bug where auto pairs destroy the selection.

Fixes helix-editor#1014
Copy link
Member

@sudormrfbin sudormrfbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor nitpicks, other than that LGTM :)

helix-core/src/auto_pairs.rs Show resolved Hide resolved
helix-core/src/auto_pairs.rs Show resolved Hide resolved
helix-core/src/auto_pairs.rs Outdated Show resolved Hide resolved
start_range.anchor + offs
};

end_ranges.push(Range::new(end_anchor, end_head));

match next {
Some(ch) if !close_before.contains(ch) => {
offs += 1;
// TODO: else return (use default handler that inserts open)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO still relevant @archseer ? All the handle_ functions would have to return an Option that gets passed through the hook.

helix-core/src/auto_pairs.rs Outdated Show resolved Hide resolved
helix-core/src/auto_pairs.rs Outdated Show resolved Hide resolved
@archseer archseer merged commit 94535fa into helix-editor:master Dec 13, 2021
@dead10ck dead10ck deleted the auto_pairs branch December 21, 2021 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add support for autopairs of certain keys
3 participants