diff --git a/docs/user/README.md b/docs/user/README.md index d5633019281..8a576784928 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -86,7 +86,7 @@ Installation: [ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer -* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys +* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints ## Vim and NeoVim diff --git a/editors/emacs/ra-emacs-lsp.el b/editors/emacs/ra-emacs-lsp.el index 21a90c86b46..d7656476ef7 100644 --- a/editors/emacs/ra-emacs-lsp.el +++ b/editors/emacs/ra-emacs-lsp.el @@ -15,6 +15,7 @@ ;; - implements source changes (for code actions etc.), except for file system changes ;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key) ;; - implements extendSelection (either bind rust-analyzer-extend-selection to a key, or use expand-region) +;; - provides rust-analyzer-inlay-hints-mode for inline type hints ;; What's missing: ;; - file system changes in apply-source-change @@ -22,7 +23,6 @@ ;; - onEnter, parentModule, findMatchingBrace ;; - runnables ;; - the debugging commands (syntaxTree and analyzerStatus) -;; - lsp-ui doesn't interpret the markdown we return currently and instead displays it raw (https://github.com/emacs-lsp/lsp-ui/issues/220 ) ;; - more ;; Also, there's a problem with company-lsp's caching being too eager, sometimes @@ -225,10 +225,46 @@ (with-current-buffer buf (let ((inhibit-read-only t)) (erase-buffer) - (insert parse-result)) - ) + (insert parse-result))) (pop-to-buffer buf)))))) +;; inlay hints +(defun rust-analyzer--update-inlay-hints () + (lsp-send-request-async + (lsp-make-request "rust-analyzer/inlayHints" + (list :textDocument (lsp--text-document-identifier))) + (lambda (res) + (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) + (dolist (hint res) + (-let* (((&hash "range" "label" "kind") hint) + ((beg . end) (lsp--range-to-region range)) + (overlay (make-overlay beg end))) + (overlay-put overlay 'rust-analyzer--inlay-hint t) + (overlay-put overlay 'evaporate t) + (overlay-put overlay 'after-string (propertize (concat ": " label) + 'font-lock-face 'font-lock-comment-face))))) + 'tick) + nil) + +(defvar-local rust-analyzer--inlay-hints-timer nil) + +(defun rust-analyzer--inlay-hints-change-handler (&rest rest) + (when rust-analyzer--inlay-hints-timer + (cancel-timer rust-analyzer--inlay-hints-timer)) + (setq rust-analyzer--inlay-hints-timer + (run-with-idle-timer 0.1 nil #'rust-analyzer--update-inlay-hints))) + +(define-minor-mode rust-analyzer-inlay-hints-mode + "Mode for showing inlay hints." + nil nil nil + (cond + (rust-analyzer-inlay-hints-mode + (rust-analyzer--update-inlay-hints) + (add-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler nil t)) + (t + (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) + (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t)))) + (provide 'ra-emacs-lsp) ;;; ra-emacs-lsp.el ends here