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.73k stars 864 forks source link

Documentation should describe how to actually bind lsp-command-map to a different key #3256

Open TauPan opened 2 years ago

TauPan commented 2 years ago

So in https://emacs-lsp.github.io/lsp-mode/page/installation/#vanilla-emacs it's explained to do the following

;; if you want to change prefix for lsp-mode keybindings.
(setq lsp-keymap-prefix "s-l")

if you want to change the prefix. However as https://github.com/emacs-lsp/lsp-mode/issues/1532#issuecomment-602384182 points out this is merely for which-key-integration and does not actually change the keybinding.

In order to do that I came up with the following (not by myself, but I didn't document where I learned that):

(defun lsp-config ()
  (define-key lsp-mode-map (kbd "C-c e") lsp-command-map)
  (define-key lsp-mode-map (kbd "C-c C-e") #'lsp-rename))

(use-package lsp-pyright
  :ensure t
  :hook ((python-mode . (lambda ()
                          (require 'lsp-pyright)
                          (lsp-deferred ; or lsp
                           )
                          (lsp-config)))))

Not sure if that's the best way to do it but it's the only one I figured out that actually has an effect.

I could not find documentation on how to do it anywhere, so I'd appreciate if it could be added.

cstby commented 2 years ago

I ran into this same problem and ended up with the following config. I bind the lsp-command-map to C-c l elsewhere using general.el. This results in everything working as expected.

(use-package lsp-mode
  :hook ((clojure-mode . lsp)
         (clojurec-mode . lsp)
         (clojurescript-mode . lsp)
     (lsp-mode . lsp-enable-which-key-integration))
  :config
  (setq lsp-keymap-prefix "C-c l")
  (fset 'lsp-command-map lsp-command-map)
  (dolist (m '(clojure-mode
               clojurec-mode
               clojurescript-mode
               clojurex-mode))
    (add-to-list 'lsp-language-id-configuration `(,m . "clojure"))))
richcarl commented 2 years ago

Seems to me that the only thing needed is to set lsp-keymap-prefix before loading lsp-mode instead of the other way around.

(setq lsp-keymap-prefix "C-c l")
(use-package lsp-mode)

Works for me, and is backed up by this page: https://githubhelp.com/ofrank123/lsp-mode

TauPan commented 2 years ago

Seems to me that the only thing needed is to set lsp-keymap-prefix before loading lsp-mode instead of the other way around.

(setq lsp-keymap-prefix "C-c l")
(use-package lsp-mode)

Works for me, and is backed up by this page: https://githubhelp.com/ofrank123/lsp-mode

This does not work for me, specifically:

(setq lsp-keymap-prefix (kbd "C-c e"))
(use-package lsp-mode
  :bind-keymap ("C-c e" . lsp-command-map)
  :hook ((lsp-mode . lsp-enable-which-key-integration)))

If I comment out the :bind-keymap and press "C-c e" I get "C-c e is undefined", otherwise it works. I think this may be a good proposal for the documentation

The documentation you linked appears to be from a fork but the regular lsp-mode documentation that I linked makes the same claim.

CadeMichael commented 2 years ago

I'm trying to bind it with space (SPC-l), and have been unsuccessful using general. I tried a similar approach to setting projectile to SPC-p but keep getting the error

Wrong type argument: commandp, lsp-command-map

I tried making a function and adding it as a hook but it still threw the error

  (defun set-command-map-lsp () (general-define-key
                                 :states '(normal)
                                 :prefix "SPC"
                                 :keymaps 'lsp-mode-map
                                 "l" '(lsp-command-map :which-key "lsp command map")))

is it possible to bind with space?

d1egoaz commented 2 years ago

Thanks @richcarl, setting the variable before the package is loaded did the trick for me.

@TauPan have you tried adding the setq on the use-package :init section?

this works for me:

(use-package lsp-mode
  :init
  (setq lsp-keymap-prefix "C-l")
  :config
  (lsp-enable-which-key-integration t))
TauPan commented 2 years ago

Thanks @richcarl, setting the variable before the package is loaded did the trick for me.

@TauPan have you tried adding the setq on the use-package :init section?

this works for me:

(use-package lsp-mode
  :init
  (setq lsp-keymap-prefix "C-l")
  :config
  (lsp-enable-which-key-integration t))

I just tried that, no effect.

eyeinsky commented 1 year ago

@TauPan That code seems to work when it's run before lsp itself is started, maybe you had lsp already running?

TauPan commented 1 year ago

Hm, I recently updated my distribution from openSUSE 15.2 to 15.3 and I have a more recent emacs now (28.1 instead of, I think, 27.x) and this inded works now:

(use-package lsp-mode
  :bind (:map lsp-mode-map
              ("C-c C-e" . lsp-rename))
  :bind-keymap ("C-c e" . lsp-command-map)
  :hook ((lsp-mode . lsp-enable-which-key-integration)))

I swear it didn't, previously, even after restarting emacs, even if I made extra double sure that it was the first instance of code that loading anything to do with lsp and didn't even think about lsp (via M-x partial-mindwipe) before trying that keybinding.

domas-v commented 1 year ago

A related question - tell me if it's not the place to ask -- how do I unbind the default s-l? Even if I manage to bind the prefix to a different key (C-c l for instance), the default s-l is still bound, even though I want to use for a different action.

yyoncho commented 1 year ago

A related question - tell me if it's not the place to ask -- how do I unbind the default s-l? Even if I manage to bind the prefix to a different key (C-c l for instance), the default s-l is still bound, even though I want to use for a different action.

@domas-v (define-key <map> <key> nil)

domas-v commented 1 year ago

Thanks, but it doesn't work, unless I'm doing something wrong:

(define-key lsp-command-map (kbd "s-l") nil)

I tried setting it before any of the lsp configurations and after all of the configs. s-l still brings up the which key panel and has all the keybindings.

EDIT: found what was wrong. It's supposed to be lsp-mode-map and not lsp-command-map:

(define-key lsp-mode-map (kbd "s-l") nil)

arobertn commented 1 year ago

@domas-v @yyoncho Thank you, thank you! None of the suggestions I was finding anywhere was doing anything about the problem I was trying to solve – getting rid of the conflict with the default M-l = "goto-line" binding on the Mac. (It seems incorrect – not just a documentation problem – that even setting the new early and/or in the right way does not remove the default binding, but I assume there are reasons it must be this way.)

SalamandraDevs commented 1 month ago

I just use this removing require('lsp-mode):

(use-package lsp-mode
  :init
  (setq lsp-keymap-prefix "C-c l"))

Remember to install use-package and require it before this line.