Add helix match surround operations#44317
Conversation
8d15b23 to
3ee714f
Compare
83b0da3 to
9bb99c1
Compare
kubkon
left a comment
There was a problem hiding this comment.
Thanks for the PR and all in all it looks great! I do have two suggestions I would like to fix before landing this PR. Lemme know what you think!
crates/vim/src/helix/surround.rs
Outdated
| let start_anchor = display_map.buffer_snapshot().anchor_before(start); | ||
| edits.push((end..end, pair.end.clone())); | ||
| edits.push((start..start, pair.start.clone())); | ||
| anchors.push(start_anchor..start_anchor); |
There was a problem hiding this comment.
This will force the cursor position to the beginning of the surrounded text whereas I believe that the Helix editor does the opposite - it will place the cursor at the end of the selection:
#[gpui::test]
async fn test_helix_surround_add_cursor_at_closing_bracket(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.enable_helix();
cx.set_state("hello ˇworld", Mode::HelixNormal);
cx.simulate_keystrokes("m s (");
cx.assert_state("hello (wˇ)orld", Mode::HelixNormal);
cx.set_state("hello «worlˇ»d", Mode::HelixNormal);
cx.simulate_keystrokes("m s [");
cx.assert_state("hello [worlˇ]d", Mode::HelixNormal);
}| let open_start = range.start.to_offset(display_map, Bias::Left); | ||
| let open_end = open_start + open_marker.len_utf8(); | ||
| let close_end = range.end.to_offset(display_map, Bias::Left); | ||
| let close_start = close_end - close_marker.len_utf8(); | ||
|
|
||
| edits.push((close_start..close_end, String::new())); | ||
| edits.push((open_start..open_end, String::new())); | ||
|
|
||
| let anchor = display_map.buffer_snapshot().anchor_before(open_start); | ||
| anchors.push(anchor..anchor); |
There was a problem hiding this comment.
For surround delete/replace, Helix leaves the cursor where it was (minus the deleted surrounding pair), whereas here we also force it to the beginning of modified matched selection:
#[gpui::test]
async fn test_helix_surround_delete_replace_cursor_stays_in_place(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.enable_helix();
cx.set_state("hello (woˇrld) test", Mode::HelixNormal);
cx.simulate_keystrokes("m d (");
cx.assert_state("hello woˇrld test", Mode::HelixNormal);
cx.set_state("hello [woˇrld] test", Mode::HelixNormal);
cx.simulate_keystrokes("m d m");
cx.assert_state("hello woˇrld test", Mode::HelixNormal);
cx.set_state("hello (woˇrld) test", Mode::HelixNormal);
cx.simulate_keystrokes("m r ( [");
cx.assert_state("hello [woˇrld] test", Mode::HelixNormal);
cx.set_state("hello {woˇrld} test", Mode::HelixNormal);
cx.simulate_keystrokes("m r m (");
cx.assert_state("hello (woˇrld) test", Mode::HelixNormal);
}9bb99c1 to
7a440ea
Compare
# Conflicts: # assets/keymaps/vim.json
7a440ea to
d2df8a0
Compare
|
Correct - should be addressed, thank you! |
kubkon
left a comment
There was a problem hiding this comment.
Looks great! Thanks for following up with fixes!
Partially addresses #38151 Release Notes: - Added Helix match surround operations
Partially addresses zed-industries#38151 Release Notes: - Added Helix match surround operations
Partially addresses zed-industries#38151 Release Notes: - Added Helix match surround operations
Partially addresses zed-industries#38151 Release Notes: - Added Helix match surround operations
Partially addresses #38151
Release Notes:
Implements Helix-style surround operations under the
m(match) menu:ms<char>- Add surrounding characters around selectionmr<from><to>- Replace surrounding charactersmd<char>- Delete surrounding charactersIt supports Helix'
mas a special target character meaning "match nearest surrounding pair", allowing operations likemdm(delete nearest surround) andmrm<char>(replace nearest surround).It also adds the concept of a
SurroundPairas a single source of truth for all supported surround characters (brackets and quotes), used by both Vim and Helix flows.surround_pair_for_char_vim,bracket_pair_for_str_vim) keep aliasing (b/B/r/a) while rejecting unknown characters.surround_pair_for_char_helix,bracket_pair_for_str_helix) avoid aliases and treat unknown characters as symmetric pairs.Note
helix/surround.rsassurround.rsexists already.SurroundPairabstraction seemed like a good idea but is definitely not required.