-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
feat: make move_vertically
aware of tabs and wide characters
#2620
feat: make move_vertically
aware of tabs and wide characters
#2620
Conversation
@@ -109,10 +109,12 @@ pub fn visual_coords_at_pos(text: RopeSlice, pos: usize, tab_width: usize) -> Po | |||
/// with left-side block-cursor positions, as this prevents the the block cursor | |||
/// from jumping to the next line. Otherwise you typically want it to be `false`, | |||
/// such as when dealing with raw anchor/head positions. | |||
/// |
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.
This TODO seems wrong, pos_at_coords is intended for line, col calculation, and we already have pos_at_visual_coords for functions that need to deal with tab width and grapheme widths. The method should be kept unchanged, instead commands should use visual_ versions where necessary.
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.
Ok, I've refactored things in 33e8fa7 so pos_at_visual_coords
is a separate function. I removed the limit_before_line_ending
parameter because I figure when we're dealing with visual coords we'll always want the behaviour corresponding to a true value for that parameter, right?
Also, I noticed this comment that mentions pos_at_visual_coords
; is it fine if I update the code there to use that function now that it exists? It looks like the code there does the same thing as my implementation (at least, it does now, I found a bug in my code with the handling of tabs that don't start at a multiple of tab_width
from looking at it).
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.
Yeah good catch! It should use that function, similar to how the inverse does: https://github.com/helix-editor/helix/blob/eba82250bb4403fcb2e3ade74ba7301a680bc561/helix-view/src/view.rs#L226-L232=
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.
Thanks, updated in 324a76b.
if grapheme_width > cols_remaining { | ||
break; | ||
} |
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 you include the original comment here: https://github.com/helix-editor/helix/blob/eba82250bb4403fcb2e3ade74ba7301a680bc561/helix-view/src/view.rs#L280-L281=
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.
Sure, added in 3c17265.
let mut cols_remaining = col; | ||
for grapheme in RopeGraphemes::new(text.slice(line_start..line_end)) { | ||
let grapheme_width = if grapheme == "\t" { | ||
tab_width - ((col - cols_remaining) % tab_width) |
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.
The logic here and in the conditional looks slightly different though
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.
Ah true, it is still slightly different. The other implementation keeps track of the current column, while mine keeps track of the columns remaining before we reach the target column, but I think the behaviour is still the same.
I just realized that Are there any other commands that I've missed that should also be modified? |
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.
Sorry for the delay, this looks correct to me and I couldn't find any more spots that need fixing. Great work! 🎉
As the
TODO
inmove_vertically
previously noted, the current behaviour leads to jerky vertical movement on lines with wide characters and tabs. This pull request refactors a few of the related functions (and resolves some of theirTODO
s in the process) so that vertical movement is always smooth.Since the parameters to
pos_at_coords
had to be modified to accepttab_width
, quite a few tests had to be updated. Some of these tests also needed their expected values changed sincepos_at_coords
now operates based on visual row/column instead of graphemes, as theTODO
called for. I'm not 100% sure if I updated a few of the tests correctly though, in particular, this assertion, and this block. If someone could offer a second opinion on those, I'd appreciate it!