emacs-lsp / lsp-mode

Emacs client/library for the Language Server Protocol
https://emacs-lsp.github.io/lsp-mode
GNU General Public License v3.0
4.76k stars 876 forks source link

cursor issue about variable and rust inlay hints #3263

Open c02y opened 2 years ago

c02y commented 2 years ago

Thank you for the bug report

Bug description

When I enable inlay hints for rust code, the cursor of the last character of the variable is at the wrong place.

Steps to reproduce

  1. Use rust-analyzer
  2. use lsp-mode for rust code
  3. open a rust file
  4. enable inlat hints for rust file by enabling lsp-rust-analyzer-inlay-hints-mode and lsp-rust-analyzer-server-display-inlay-hints
  5. move cursor, check out the gif

Peek 2021-12-16 05-00

BTW: I'm using Spacemacs(Spacemacs, rust-analyzer, all packages are all update to date), I'm not sure whether other people can reproduce it or not.

Expected behavior

Moving the cursor to the last character of the variable should not move over to the inlay hints

Which Language Server did you use?

rust-analyzer db2a7087b 2021-12-13 stable

OS

Linux

Error callstack

No response

Anything else?

No response

deifactor commented 1 year ago

I'm not sure if this is possible to easily fix. For a given block of propertized text and overlays, I think emacs will always display the cursor at the same point. If so, then there's no way to make it so you can have the cursor both immediately before and immediately after the overlay and insert text at the location you're expecting without hooking into post-command-hook to

as well as do the opposite for moving backwards. Basically, instead of moving the cursor around the overlay, you move the overlay around the cursor.

This would potentially be a good candidate for emacs to support at the C level by adding a new property to overlays.

deifactor commented 1 year ago

I just wrote this snippet to propertize the overlay based on whether it makes more sense for the cursor to be at the start or the end (type overlays come after the thing they describe, param overlays come before):

(defun lsp-rust-analyzer-properties-for-inlay (kind)
  "Returns the text properties to be used for the inlay's after-string."
  (cond
   ((eql kind lsp/rust-analyzer-inlay-hint-kind-type-hint)
    ; Setting the cursor to 1 lets us put the cursor at the start of the
    ; overlay; not setting it/setting it to nil means we can put it at the
    ; end. See https://github.com/emacs-lsp/lsp-mode/issues/3263
    '(font-lock-face lsp-rust-analyzer-inlay-type-face cursor 1))
   ((eql kind lsp/rust-analyzer-inlay-hint-kind-param-hint)
    '(font-lock-face lsp-rust-analyzer-inlay-param-face))
   (t
    '(font-lock-face lsp-rust-analyzer-inlay-face))))

and then replace the call to propertize in lsp-rust-analyzer-update-inlay-hints with

(apply 'propertize (lsp-rust-analyzer-format-inlay concat-label kind)
       (lsp-rust-analyzer-properties-for-inlay kind))

If this doesn't somehow blow up in my face, I'll send a PR.