-
Notifications
You must be signed in to change notification settings - Fork 0
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 multiline snippets for completions without offsets #7
Fix multiline snippets for completions without offsets #7
Conversation
This is definitely out of my expertise. cc @pascalkuthe |
You have indentified the right bugs but there are open PRs to fix this on the main repo for the first two (maybe also for the third not sure right now). The fxes are more involved and we shouldn't bunch them in with the snippet PR. |
Given |
// TODO: We can't use range.cursor() here because the text hasn't been updated yet | ||
let cursor = std::cmp::min(range.anchor, range.head); | ||
Range::new( | ||
(range.anchor as i128 + *from) as usize, | ||
(range.anchor as i128 + *to) as usize, | ||
(cursor as i128 + *from) as usize, | ||
(cursor as i128 + *to) as usize, |
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.
cc @pascalkuthe. This is the fix for issue 3.
@pascalkuthe I don't think we can just skip this. Both issue 1 and issue 3 are actually introduced by the snippet code. I've seen issue 3 happen for Rust but it only shows up for the very first completion since after that the direction of the cursor is inversed and anchor matches the cursor position fixing the math. I'm happy to look into a different way to fix it that doesn't involve fixing issue 2. But I don't think we should be merging the snippet code without these fixes. If you really want to minimize the amount of changes to the main PR at this point, we should at the very least include fix for 3, since it's only changing the newly added code and it just updates the math for selection computation. |
Actually looking at helix-editor#5728 - moving away from replace to insert will introduce the same issue for multi-line snippets as issue 1 flagged here. If we are going in that direction, an alternative fix for 1 that doesn't also depend on fixing issue 2, would be to pass the length of the prefix (in case the snippet was trimmed) to generate_transaction_from_snippet so that it can be accounted for when computing newline_with_offset. |
No removing the prefix was always incorrect and not compliant with the lsp spec helix-editor#5728 contains multiple fixes, including completely removing any prefix stripping |
The insert/replace config is comepltly orthogonal and only abkut which transaction is selected for servers that send multiple |
The problem with insert is that we are currently assuming that every new line has to be offset by the same number of characters as the first position in the completion. Insert potentially hides what that first character was. @pascalkuthe what's your opinion on fixing issue 3? It's just fixing a clear bug in the snippet logic. Would you prefer me to create a new PR just for that? |
Yeah the third fix seems reasonable to fix inside the snippet PR. You can just post that as a suggestion on the main PR tough since that's just a couple of lines. Not sure what you mean about insert/replace transactions. Both transactions are sent by the server, it's up to the server yo make sure they are valid |
I tried applying just fix 3 and it's somehow dependent on fix for 2 :( So it's not safe to be merging fix 3 alone. I'll look into it more later today. |
For multi-line completions the LS is currently not offsetting the completion and we are doing this in the snippet code. Let's assume I typed
|
Or is it a LS bug in the first place that mutli-line completions don't have the right offset? |
I am not sure why that would be the case? It seems like the problem is just that the range is used the wrong way around. Fixing that shouldn't cause additional problems AFAIK. That being said we might just merge helix-editor#6173 before the snippet PR and then you can rebase on that. There are a bunch more issues around savepoints that become a lot more apparent with snippets since it's not just a bit of text being lost. That PR is a bit more tricky to understand so it will take a bit more time to review tough. |
You are missunderstanding what that PR does. The PR is a bit of a kitchen sink. Firstly it removes the prefix stripping and instead just always replaces all the way to the word boundary if the LSP sends no custom edits. The option to insert instead of replace text is about something different. I explained it here: helix-editor#5728 (comment). It's not about the start of the replacement (that must always be sent). It's about whether we want to replace the rest of the current identifier after the cursor or keep it. |
Thanks a lot for the detailed explanation it makes sense now! I should have spent more time reading through that PR before making conclusions based on naming :) |
So I understand what's happening here better now. The current logic works correctly in 2 cases: (c) is easy to observe for the very first completion after switching from normal mode to insert mode. But after we jump to the second completion (or even just select the first completion) - the savepoint logic inverses the selection and we end hitting (b) so things seem to be working fine. My fix to savepoint, prevented us from hitting (b) and so I was now seeing (c) all the time. So my fix for issue 3 above only works when savepoint is fixed since it depends on selection being of length 1 after applying the transform. |
@pascalkuthe, I think I actually managed to come up with a pretty elegant fix (at least that's what I'm telling to myself 🤡 before you reviewed it) that both keeps the code simple, but also handles all these cases nicely - helix-editor#6224 |
This fixes an issue reported by @leonqadirie on the main PR ... as well as some more subtle bugs.
I think that fixes for issues 1 and 2 are reasonable.
I'm not sure about the fix for issue 3. This investigation also exposed the fact that generate_transaction_from_snippet currently depends on cursor ending up at the end of the completion after the completion transaction is applied (which seems like a reasonable expectation given that completion is triggered at a cursor position, but it also makes the code more fragile). If we don't want to have this dependency generate_transaction_from_snippet should be updated to not rely on selection.clone().map(transaction.changes()).