I use elpy as Python IDE. I want M-<left> and M-<right> (M = alt) not to be overridden by elpy with elpy-nav-indent-shift-left and elpy-nav-indent-shift-left but insted bind these to something else.

Here's what I tried in my .emacs:

(eval-after-load "elpy"
     (define-key elpy-mode-map (kbd "M-<left>") nil)
     (define-key elpy-mode-map (kbd "M-<right>") nil)
     (define-key elpy-mode-map (kbd "M-s-<left>") (elpy-nav-indent-shift-left))
     (define-key elpy-mode-map (kbd "M-s-<right>") (elpy-nav-indent-shift-right))

M-<left> and M-<right> now do left-word and right-word as intended. The other bindings however just yield

<M-s-left> is undefined
<M-s-right> is undefined

Why is it not working?

2 Answers 2



 (define-key elpy-mode-map (kbd "M-s-<left>") 'elpy-nav-indent-shift-left)
 (define-key elpy-mode-map (kbd "M-s-<right>") 'elpy-nav-indent-shift-right)

EDIT: using use-package and bind-keys one can do the following to get what you are after (might be an overkill if you are not using it yet)

(use-package elpy
  :ensure t
  (unbind-key "M-<left>" elpy-mode-map)
  (unbind-key "M-<right>" elpy-mode-map)
  (bind-keys :map elpy-mode-map
           ("M-s-<left>" . elpy-nav-indent-shift-left)
           ("M-s-<right>" . elpy-nav-indent-shift-right)))
  • 2
    This solved it. I guess in the long run learning some elisp would pay off, even only from a user perspective... Commented Nov 27, 2018 at 12:09
  • Learning elisp would certainly pay off. I'm also only a user and would in this case use use-package and bind-keys which I hope will produce the right thing which was pointed out by @nickd I will update the post, to show what I mean.
    – andrej
    Commented Nov 27, 2018 at 16:52

(elpy-nav-indent-shift-left) is a function call in lisp. You want to bind the key to the function, but instead you've bound it to whatever the function call returns. The best way IMO (but see @Drew's comment below) to do that is to say (function <name>), so e.g.

 (define-key elpy-mode-map (kbd "M-s-<left>") (function elpy-nav-indent-shift-left))

There is a reader macro that is equivalent:

(define-key elpy-mode-map (kbd "M-s-<left>") #'elpy-nav-indent-shift-left) 

but most people write the quoted form as in the accepted answer:

(define-key elpy-mode-map (kbd "M-s-<left>") 'elpy-nav-indent-shift-left) 

although the first two forms are (again IMO) preferable. The Elisp manual says this:

-- Special Form: function function-object

This special form returns FUNCTION-OBJECT without evaluating it.
 In this, it is similar to ‘quote’ (*note Quoting).  But unlike
 ‘quote’, it also serves as a note to the Emacs evaluator and
 byte-compiler that FUNCTION-OBJECT is intended to be used as a
 function.  Assuming FUNCTION-OBJECT is a valid lambda expression,
 this has two effects:

   • When the code is byte-compiled, FUNCTION-OBJECT is compiled
      into a byte-code function object (*note Byte Compilation::).

   • When lexical binding is enabled, FUNCTION-OBJECT is converted
      into a closure.  *Note Closures::.

The read syntax ‘#'’ is a short-hand for using ‘function’. The following forms are all equivalent:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))
  • FWIW, I disagree with your characterization of The "real" way to bind a key to a function (a command, actually). There's nothing wrong with using a command symbol in a key-binding function (e.g. define-key, global-set-key). The byte compiler and the interpreter follow a function symbol to its function. And the Emacs doc itself uses just function symbols - see, e.g., node Init Rebinding. But there are other contexts than key binding where it makes sense to prefer #', to tell the compiler about a function.
    – Drew
    Commented Nov 27, 2018 at 17:46
  • (That said, your first two sentences are a good answer.)
    – Drew
    Commented Nov 27, 2018 at 17:51
  • OK - I softened it a bit, but I still think that #'foo is "better" than 'foo even in this case.
    – NickD
    Commented Nov 27, 2018 at 18:09
  • Yes, it certainly doesn't hurt in this case.
    – Drew
    Commented Nov 27, 2018 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.