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
Implement Vim like movement commands #4204
Implement Vim like movement commands #4204
Conversation
This adds new movement commands to allow h/l to be rebound so that they only operate within a single line like Vim does. This however cannot be fully emulated in Helix as Helix will happily place the character on the newline rather than "before" like Vim does. This means that if one moves to the right, "i" is needed to insert rather than "a" what a Vim user would expect. "a" would still put the character into the new line. The "move_from_line_end" command is provided which can optionally be used after all movements to move the character one back if needed. Unfortunately this also means that the cursor is repositioned which causes it to forget the original position it had which makes movements between lines annoying as the cursor has a left drift.
f01e27b
to
205e3a1
Compare
bc36983
to
0af9776
Compare
@the-mikedavis this does not change the behavior about select-ability. They are still selectable as before. The new commands add a way that for horizontal movements you can stay constrained within the line but you still move onto them and for vertical movement it even anchors you onto them if you already are on one. Just to be clear since maybe my comment on the other issue was misleading: i think the visible newlines are a good thing and I wouldn't want to change this. This is also not changing the behavior of helix to bring in vim semantics that do not feel native. The movements here are vim inspired, but they are actually following the helix model. Rather than using hidden internal flags for the newline behavior, this actually takes advantage of the visible and selectable newline instead. |
(Also fixes #768) |
Curious about what the odds are of this merging. I'm happy to incorporate necessary changes if there is something I can do here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at your comment here (#4204 (comment)), Vim whichwrap and the context in #768, I think these motions are ok and don't introduce incompatible Vim-isms 👍. (Sorry for jumping the gun on "no Vim" here; steam preemptively comes out of my ears when I see "Add Vim-like..." 😅)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
An open question I have is how this should be documented best. Is there a place to document unmapped commands that do not have a typable alias? |
Not currently, see: #997 |
Then I suppose this is ready. |
Sorry for the delay, this looks fine to me but needs a rebase now that the soft wrap changes landed! |
The rebase will be slightly more challenging than usual because the vertical movement commands were essentially reimplemented in #5420. It would also be good to have a version that does visual line movement and document line movement like we have for the normal movement command |
I will update this. Unfortunately the changes are a bit more involved so it will take a bit until I find the time for it. |
i was also thinking about this topic the other day - that why don't n/vi/m stop the horizontal movement at line ends and don't wrap it around - is there any benefit to that way while editing etc... |
I think a better way to configure it is to add all of those binding into one option. |
/// If you are not on the newline, then moving up and down will move you to the same | ||
/// column except if that column is further to the left from where you are. In that case | ||
/// it places you on the rightmost column that is not a newline. | ||
pub fn move_vertically_anchored( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have some tests for both of these functions?
I would definitely like to still see this feature. Unfortunately, this branch is quite stale as the refactor in #5420 entirely changed how movement works so somebody would need to start almost from scratch. Thank you for contributing! |
This adds a few new movement commands to allow
hjkl
to be rebound so that they follow more the movement of vim. left/right movement cannot move between lines and up/down either follows newline or does not accidentally move onto the newline character. See #4268 for motivation. This however does not emulate vim, it just has some vim inspired movements. In particular it retains the entire behavior of Helix with regards to how newlines are otherwise handled (they stay selectable, and these alternative movement commands to not interfere with other commands in use or change their assumptions).The following commands are added:
move_line_up_anchored
(bind tok
): implements anchored movement upmove_line_down_anchored
(bind toj
): implements anchored movement downmove_char_left_same_line
(bind toh
): implements same-line movement leftmove_char_right_same_line
(bind tol
): implements same-line movement rightextend_line_up_anchored
(bind tok
): implements anchored selection extension upextend_line_down_anchored
(bind toj
): implements anchored selection extension downextend_char_left_same_line
(bind toh
): implements same-line selection extension leftextend_char_right_same_line
(bind tol
): implements same-line selection extension rightBindings
Same Line Movement
The default movement behavior of helix will happily place you in the next line. Vim users are not used to that and are likely to prefer the cursor not to move into the next line (that is at least my expectation). This is what
move_char_left_same_line
andmove_char_right_same_line
do. They will however let you move to the rightmost character (the newline) which is not what vim does (except ofvirtualedit=oneline
is used). However this pairs up nicely with the anchored movement (see next).Anchored Vertical Movements
The two commands
move_line_up_anchored
andmove_line_down_anchored
implement what I would call anchored movement. If you are on the newline character (eg: one to the right of wheregoto_line_end
would place you) then as you move up and down you end up on the newline of the target line again. This emulates the behavior of vim of what happens if you move to the line end with$
. If however you are placed to the left of the newline, as you move up and down you will not move onto the newline.The main difference is that in vim if you use
$
and go up/down you stay anchored to the line end. In Helix with this change you need to dogll
to stay anchored to the newline. I do however have to say that I prefer this actually because in Vim you do not actually know if you are newline anchored visually. That is as far as I can tell an internal state.I played around with this a bit now and I really like the combination of the two. It stays true to the helix character model, but it also feels very natural for vim users.
Limitation: Movements across empty lines are ambiguous. To help with this I put the horizontal column to the largest possible integer on the range to tell these cases apart. From what I can tell this does not create negative impact and avoids extra complication on the range.
Notes on Mixed Use
I think these move/extend commands are interesting to use independent of each other. For instance I find the anchored newline movement functionality useful even if one does not like restricting the movements within a line. For instance line based selection works really nice as once the visual selection is on the newline, any further moving down will continue to capture entire lines. That means for instance
vx
will continue to move downwards which I think also addresses some points of #1638 as it basically keeps you in line mode for as long as you don't move left.