5

Windows 10, Emacs 25.1

In my init.el

(define-key shell-mode-map (kbd "C-c C-l") 'helm-comint-input-ring)

But when I start emacs I get error:

Symbol's value as variable is void: shell-mode-map
user8542613
  • 643
  • 6
  • 16
  • 5
    You need to load the library that defines `shell-mode-map` before you try to use it. – Drew Sep 06 '17 at 13:35
  • 3
    Possible duplicate of [Defining key-bindings within \`helm-map\`: getting a \`void-variable helm-map\` error](https://emacs.stackexchange.com/questions/2539/defining-key-bindings-within-helm-map-getting-a-void-variable-helm-map-erro) – Drew Sep 23 '18 at 18:06

2 Answers2

4

Drew is right you need to load the package, which defines shell-mode-map

(require 'shell)
;; your code based on functions and variables defined in shell.el

Explanation

At the end of your Emacs's shell.el file you should find a line:

(provide 'shell)

This line holds the trick, because Emacs elisp and Common Lisp have their own unusual import solution, every package provides a FEATURE which can be used to load a package into memory, which is uncanny at first because the file must be read even if it won't be loaded.

My educated guess is it happens because lisp code can be read without evaluation, which maybe used to achieve some optimization and security solutions. Imagine you can write lisp code to reprogram your lisp code before loading the package, which is a way of meta programming.

So require uses the provided FEATURE as quoted argument to load a package.

Hint: If you don't know the feature name, check Emacs feature list variable, by hitting C-h v and typing features, or seek the provide function in the source file.

Update:

phils pointed out that provide tells Emacs that the library is loaded, so a next require call will not load it again. So my guess (stroke out text) was wrong.

atevm
  • 928
  • 7
  • 16
  • 1
    `provide` simply tells Emacs that the library is now loaded, so any that additional `require` calls for that library can bail out without actually (re)loading the library. If it is not already loaded, `(require 'shell)` will `load` the library `"shell"` (simply using the symbol name as the library name). – phils Sep 14 '17 at 09:09
0

you can also use with-eval-after-load. In particular:

(with-eval-after-load 'shell
  (define-key shell-mode-map (kbd "C-c C-l")
                             'helm-comint-input-ring))
xdavidliu
  • 143
  • 8