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
Fix possible misplaced cursor after :map expr (Issue #12707) #12837
Conversation
|
f8fe5d4
to
d742251
Compare
Yh I agree, calling
The way the tests are failing is not good. The cursor is updated but the screen is not. So, for example, the screen is not unscrolled after displaying messages. The way to fix it would be to do something like:
Which is obviously a heavy handed approach. There already exists logic in Lines 2235 to 2246 in 1e14dac
The screen update is skipped when I don't know the best way to tackle this, two options I came up with:
In the first case we pay for a |
The tests are still failing, but now the results really are better. |
In case this might give you an idea for a test, I can describe what led to this issue ("X" in the "XY problem"). For that it At some point I tried to compile On a side note, can you possibly comment on this |
I'm not an expert, but I think you have it right. I think having just a |
I uncovered a few more drawing bugs related to expression mappings, they're documented in the original issue (#12707). This PR addresses those too. After commit e30e054 I believe them all to be fixed. I went digging around the Vim code base to see how they're dealing with this. It turns out Vim does something analogous to Just to further put everyone's mind at ease, I did some profiling:
The timings really start to explode with any moderately complex expression. I refactored the screen updating changes into a function for testing purposes:
The function executed within |
Ah nice, thanks for investigating. So we can mark Vim patch 8.1.2336 vim/vim@4ebe0e6 as merged after this PR.
Perfect, thank you! |
src/nvim/getchar.c
Outdated
update_screen(0); | ||
} | ||
|
||
setcursor(); |
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.
any reason not to use the same approach as in vim/vim@4ebe0e6 ? I.e.
int was_screen_col = screen_cur_col;
int was_screen_row = screen_cur_row;
...
ui_cursor_goto(was_screen_row, was_screen_col);
ui_flush();
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 update_screen
is needed to clear messages. Super contrived example:
function! F1()
echoerr "test"
echoerr "test"
echoerr "test"
call input("> ")
return ""
endfunction
map <expr> a F1()
Without a screen_update, the cursor is restored, but the screen isn't. We could maybe test for msg_did_scroll
rather than must_redraw
, but there could some other obscure corner case that requires a screen update. The ui is flushed the next time we block, or when a something has changed, figured it was fine to wait for that flush.
The cursor strategy does seem better. One thing though, I'm not sure how ui_cursor_goto
and multigrid interact, I did notice that ui_cursor_goto
always uses the default grid, would that produce the correct result when multigrid is active? Maybe it takes something like:
ui_grid_cursor_goto(curwin->w_grid.handle, was_screen_row, was_screen_col);
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.
ui_grid_cursor_goto
is low-level, ui_cursor_goto
will (must) do the right thing.
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.
Great, thanks. I'll make the changes.
I forgot to mention, the redrawcmdline
call is their to address the bugs I added to the original issue.
Switched to
|
note: the linter is complaining about the length of
We obviously can't rewrite vgetorpeek() here, so let's add a NOLINT line to the end of it like this : Line 4221 in d8e6a03
only changes from the given patch. Otherwise it's confusing when merging the other patches. Usually we try to merge in-order though, to avoid confusion.
👍
small patch is fine to put here, thanks! |
Fixed the linter errors and merged the vim patches. I think that should do it. The CI build failure seems unrelated. |
Hmm, seems as though my lua also has linting issues. I will take a look, but I'm not a lua expert. A quick note on the GC patch, the Vim version addresses a bug in Vim's timer code. We use a different timer implementation, and as far as I can tell, our version is not susceptible to the same flaw. Specifically, the GC is correctly handled in |
Yes, correct.
Since we are just trying to merge now (review is done), it's a good time to rebase and fixup commits. We don't want meaningless commits like "fix single lint error" in the history. |
87527c0
to
80eda20
Compare
I'm not sure about your workflow, but shouldn't this PR be added to the 0.6 milestone? Considering there's already a pre-release. It'd be nice to have this fixed in the next release. |
Don't pay too much attention to milestones; they don't mean much unless close to a release. If/when it's merged, it will be automatically included in the next (non-bugfix) release, which is 0.6. (And "pre-release" is just another name for nightlies, it doesn't imply anything about the imminence of a release.) For this to be merged, it first has to be rebased on master and the conflicts fixed. @JaySandhu are you still available for that? |
Fix issue (neovim#12707) where cursor is not restored after an expression mapping. Save the cursor position before evaluating the mapped expression, restore it after. Also, redraw command line after expression mappings. Evaluating an expression can wreak all sorts of havoc on the command line, to avoid drawing glitches such as those in neovim#12707, it's best to redraw it. Add tests for: - Cursor position restored after :map expr - Cursor position restored after :imap expr - Command line restored after :cmap expr - Error in :cmap expr handled correctly
…estored Problem: When an expr mapping moves the cursor it is not restored. Solution: Position the cursor after an expr mapping. (closes vim/vim#5256) vim/vim@4ebe0e6
I've rebased the changes: Restore cursor position after expr mapping onto Restore cursor position after expr mapping
The first commit had a conflict in The second commit had a conflict in the same file, and in It's worth noting that they put the cursor back before restoring Other than that, it resolves the issue, and the tests pass. @JaySandhu, can you update the PR? Or should I create a new one? |
80eda20
to
b3df432
Compare
I updated the PR. Thank you @x-yuri for resolving the conflicts. |
Bram's comment about the redrawing problem: vim/vim@74a0a5b#commitcomment-66443154:
I think it makes sense. |
Interesting. That language wasn't in the help when this PR was originally authored. I believe it was added later: b16c7c5. In my opinion, there's not a lot of harm done by the In any case, if we were to remove it, we would have to add something similar to that vim patch to handle accidental error messages. At the moment, the call to |
Add tests for: - Cursor position restored after :map expr - Cursor position restored after :imap expr - Error in :cmap expr handled correctly Cherry-picked from neovim#12837
Add tests for: - Cursor position restored after :map expr - Cursor position restored after :imap expr - Error in :cmap expr handled correctly Cherry-picked from neovim#12837
My attempt at tackling issue: #12707.
Fix corner case that occurs when both:
When a mapping does not result in a character, the UI is flushed, and we go back to waiting for user input. When the cursor has moved, the UI is flushed in an incorrect state, this can be resolved with a simple call to setcursor().