-
-
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
Add lsp signature help #1755
Add lsp signature help #1755
Conversation
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.
Obstructs the completion popup
There's a TODO item in Popup or about adding a Bias::Above/Below
that would specify a preference for popup placement around the cursor (This is only a preference because you still want to place it below if there's no space above)
helix/helix-term/src/ui/popup.rs
Lines 63 to 80 in 9bfb0ca
// if there's a orientation preference, use that | |
// if we're on the top part of the screen, do below | |
// if we're on the bottom part, do above | |
// -- make sure frame doesn't stick out of bounds | |
let mut rel_x = position.col as u16; | |
let mut rel_y = position.row as u16; | |
if viewport.width <= rel_x + width { | |
rel_x = rel_x.saturating_sub((rel_x + width).saturating_sub(viewport.width)); | |
} | |
// TODO: be able to specify orientation preference. We want above for most popups, below | |
// for menus/autocomplete. | |
if viewport.height > rel_y + height { | |
rel_y += 1 // position below point | |
} else { | |
rel_y = rel_y.saturating_sub(height) // position above point | |
} |
I'd add this as a builder method similar to margin:
helix/helix-term/src/ui/popup.rs
Lines 46 to 49 in 9bfb0ca
pub fn margin(mut self, margin: Margin) -> Self { | |
self.margin = margin; | |
self | |
} |
Then you can specify the signature help to be displayed above, and completion below.
We also want to add a editor.lsp.signature-help
config item that would allow configuring / disabling this since I can imagine some users find it distracting.
Config values used by |
a09d948
to
4a48370
Compare
a23536e
to
87efd55
Compare
This is mainly done to accomodate the new lsp.signature-help config option that will be introduced in helix-editor#1755 which will have to be accessed by commands. The top level config struct is split and moved to different places, making the relocation necessary
This is mainly done to accomodate the new lsp.signature-help config option that will be introduced in helix-editor#1755 which will have to be accessed by commands. The top level config struct is split and moved to different places, making the relocation necessary
* Move top level lsp config to editor.lsp This is mainly done to accomodate the new lsp.signature-help config option that will be introduced in #1755 which will have to be accessed by commands. The top level config struct is split and moved to different places, making the relocation necessary * Revert rebase slipup
87efd55
to
3000bf4
Compare
I added |
It might be easier to remember something like CtrlShiftx but OTOH that's a lot of keystrokes. I think Ctrls is ok. Ctrlh could be another good option but we'd have to kill (haha) the readline/emacs binding that's already there. |
|
Even then we probably shouldn't rely on https://sw.kovidgoyal.net/kitty/keyboard-protocol/ by default since not every terminal supports it. |
|
That's a bad reason to avoid a key. I think it's even a weak reason to prefer a key (e.g. Ctrl-Space could be interesting though as long as the terminal accepts the inputs (iirc it gives a keycode of |
I noticed testing this that Backspace in insert mode will pop up the "Language server not active for current buffer" status message for buffers like scratch or text. Probably not a big deal but it does grab the eye a bit. |
match ¶m.label { | ||
lsp::ParameterLabel::Simple(string) => { | ||
let start = signature.label.find(string.as_str())?; | ||
Some((start, start + string.len())) |
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.
I didn't look closely on this. Does this also work with double width characters like CJK? This seemed to be characters length after looking at the code (wasn't mentioned in the comment whether it is character length or terminal width length) and we don't seemed to be checking the width of required_size
.
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.
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.
I think it should if the intent is to use byte length, or do we need to use string.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.
(This actually turned out to be a bug, see #3154.)
Syntax highlighting uses char byte offsets so that is what we need as the final (start, end)
value. Now, LSP sends the label offsets in utf-16 according to the configured , so we would have to convert this to OffsetEncoding
(but we have it hardcoded to utf8) and the same is used by the LSP for ParameterLabel::LabelOffsets
char byte offsets:
lsp::ParameterLabel::LabelOffsets([start, end]) => {
Some((*start as usize, *end as usize))
}
str.find()
reports the byte index of the start of the pattern, so that would have to be changed too.
But strangely, with a naive test on a bit of CJK and non ASCII text, the parameter highlighting seems to work okay:
Details
fn main() {}
/// Documentation with doc tests:
///
/// ```
/// test
/// ```
fn func(_par老am0: char, _lö老虎wy̆: usize, _paröam1: &str) {
return;
}
Found one issue: We need to check for the signature help capability before sending the request. If the language server doesn't support it then "Async job failed: Unhandled method textDocument/signatureHelp" is emitted to the statusline. |
@Houkime I'll add a config option to control the display of docs 👍🏾 |
Escape now closes the popup and exits insert mode, similar to the completion popup. Closing the popup only can be done with |
Hi and thanks for this feature ! Been playing with it a little bit, found something that looks like an issue: when writing a closure and hitting Also, a keybinding suggestion: how about mapping |
Backspace triggers the LSP call - showing the signature for the function in that case is up to rust-analyzer. It can be a bit odd to show the signature of the outer call when you're in a closure - maybe we should open an issue in rust-analyzer? |
I am not sure about that, it is not doing it in neovim with the lsp signature plugin. When specifically asking for the signature help when inside the closure, this plugin returns "No signature help available". I'll try to see how this is handled by that plugin. Maybe a treesitter scope check ? Edit: Welp, I am on a different setup right now and the issue seems to be gone, maybe it was a bug in RA and I'm using a different version at the moment, I'll check when I get back home. |
|
/// Enable automatic pop up of signature help (parameter hints) | ||
pub auto_signature_help: bool, |
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.
Is there a way to manually trigger signature help if this is disabled? We can manually trigger completion with ctrl-x
, maybe once we trigger that it automatically triggers signature help as well?
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.
I added a keybind earlier but removed it due to a conflict. Adding a keybind is as easy as binding it to signature_help
command, and we definitely need a built-in insert mode keybind too. Any suggestions?
We can manually trigger completion with
ctrl-x
, maybe once we trigger that it automatically triggers signature help as well?
I'd rather have a separate key that can toggle just the signature help popup since that allows exclusive control.
I was trying this branch out and noticed that the |
I can't reproduce this; I tried both |
The language server sends a char offset range within the signature help label text to highlight as the current parameter, but helix uses byte offset ranges for rendering highlights. This was brought up in the [review of the original signature help PR][1], but the ranges were being highlighted correctly, and there were no out of bound or indexing panics. Turns out rust-analyzer was [incorrectly sending byte offsets] instead of char offsets and this made it seem like all was well and good with offsets in helix during initial testing. [1]: helix-editor#1755 (comment) [2]: rust-lang/rust-analyzer#12272
The language server sends a char offset range within the signature help label text to highlight as the current parameter, but helix uses byte offset ranges for rendering highlights. This was brought up in the [review of the original signature help PR][1], but the ranges were being highlighted correctly, and there were no out of bound or indexing panics. Turns out rust-analyzer was [incorrectly sending byte offsets][2] instead of char offsets and this made it seem like all was well and good with offsets in helix during initial testing. [1]: helix-editor#1755 (comment) [2]: rust-lang/rust-analyzer#12272
The language server sends a char offset range within the signature help label text to highlight as the current parameter, but helix uses byte offset ranges for rendering highlights. This was brought up in the [review of the original signature help PR][1], but the ranges were being highlighted correctly, and there were no out of bound or indexing panics. Turns out rust-analyzer was [incorrectly sending byte offsets] instead of char offsets and this made it seem like all was well and good with offsets in helix during initial testing. [1]: #1755 (comment) [2]: rust-lang/rust-analyzer#12272
The language server sends a char offset range within the signature help label text to highlight as the current parameter, but helix uses byte offset ranges for rendering highlights. This was brought up in the [review of the original signature help PR][1], but the ranges were being highlighted correctly, and there were no out of bound or indexing panics. Turns out rust-analyzer was [incorrectly sending byte offsets] instead of char offsets and this made it seem like all was well and good with offsets in helix during initial testing. [1]: helix-editor#1755 (comment) [2]: rust-lang/rust-analyzer#12272
* Add lsp signature help * Do not move signature help popup on multiple triggers * Highlight current parameter in signature help * Auto close signature help * Position signature help above to not block completion * Update signature help on backspace/insert mode delete * Add lsp.auto-signature-help config option * Add serde default annotation for LspConfig * Show LSP inactive message only if signature help is invoked manually * Do not assume valid signature help response from LSP Malformed LSP responses are common, and these should not crash the editor. * Check signature help capability before sending request * Reuse Open enum for PositionBias in popup * Close signature popup and exit insert mode on escape * Add config to control signature help docs display * Use new Margin api in signature help * Invoke signature help on changing to insert mode
The language server sends a char offset range within the signature help label text to highlight as the current parameter, but helix uses byte offset ranges for rendering highlights. This was brought up in the [review of the original signature help PR][1], but the ranges were being highlighted correctly, and there were no out of bound or indexing panics. Turns out rust-analyzer was [incorrectly sending byte offsets] instead of char offsets and this made it seem like all was well and good with offsets in helix during initial testing. [1]: helix-editor#1755 (comment) [2]: rust-lang/rust-analyzer#12272
Implements signature help, aka parameter hints:
TODO
editor.lsp.signature-help
configCtrl-S
in insert mode)Future Work