it's not clear for me how should I set use-package to load a package when a mode is activated.

I have read different things about :mode, :init :config and I am now confused. Could someone explains it to me ?

A good exemple to me would be to start yasnipped in prog-mode.

  • Please clarify your question. What have you tried, and what is not working? – Dan Dec 16 '15 at 14:14
  • I haven't tried anything yet, it's just that I don't understand how to ask use-package to use yasnippet only for prog modes. I have read the official page and other pages but due to my lack of good english I don't understand how manage this task. So if someone would be kind enough to tell me how to do it I'd be very thankful. – Nicolas Scotto Di Perto Dec 16 '15 at 14:28
up vote 5 down vote accepted

The below snippet does the following:

  • It calls yas-minor-mode when prog-mode-hook is called.
  • The yasnippet package gets loaded/required automatically when yas-minor-mode is called. So if you do not open a buffer with a prog-mode derived major mode, then yas-minor-mode is not called, and so yasnippet is not loaded at all.
  • Once yasnippet is loaded, yas-reload-all is called.

Please see the comments in below snippet for explanation.

(use-package yasnippet
  :commands (yas-minor-mode) ; autoload `yasnippet' when `yas-minor-mode' is called
                                        ; using any means: via a hook or by user
                                        ; Feel free to add more commands to this
                                        ; list to suit your needs.
  :init ; stuff to do before requiring the package
  (progn
    (add-hook 'prog-mode-hook #'yas-minor-mode))
  :config ; stuff to do after requiring the package
  (progn
    (yas-reload-all)))

For macros like use-package, the pp-macroexpand-last-sexp command is very valuable; simply put the cursor after the ending parenthesis of the macro form and call that command. For the above snippet, you will see,

(progn
  (unless
      (fboundp 'yas-minor-mode)
    (autoload #'yas-minor-mode "yasnippet" nil t))
  (condition-case-unless-debug err
      (progn
        (add-hook 'prog-mode-hook #'yas-minor-mode))
    (error
     (ignore
      (display-warning 'use-package
                       (format "%s %s: %s" "yasnippet" ":init"
                               (error-message-string err))
                       :error))))
  (eval-after-load 'yasnippet
    '(progn
       (condition-case-unless-debug err
           (progn
             (yas-reload-all))
         (error
          (ignore
           (display-warning 'use-package
                            (format "%s %s: %s" "yasnippet" ":config"
                                    (error-message-string err))
                            :error))))
       t)))
  • What does it do ? – Nicolas Scotto Di Perto Dec 16 '15 at 17:02
  • It does what you asked in the question :) I will update the answer for clarity. – Kaushal Modi Dec 16 '15 at 17:03
  • @NicolasScottoDiPerto Let me know if the added explanation helps. – Kaushal Modi Dec 16 '15 at 17:12
  • Actually I understood the first code, it's the second that I didn't understand, that's because I haven't tried [code]pp-macroexpand-last-sexp[/code] ! Ok so it's the code used by use-package... I will try to understand properly what it does, I cound't have written it myself ! Thank you that was really helpful ! – Nicolas Scotto Di Perto Dec 17 '15 at 7:40
  • Just to be clear pp-macroexpand-last-sexp command is available in emacs core. It is used to understand what any elisp macro is doing behind the scenes, not just for use-package. The second snippet above is actually what the use-package form in the first snippet expands to. Again, to clarify, I did not write the second snippet by myself. It was generated by pp-macroexpand-last-sexp and pasted it here to help understand what the use-package form is actually doing. If you don't understand it 100% right now, it is OK. Over time, you can learn more elisp to cover stuff like fboundp etc. – Kaushal Modi Dec 17 '15 at 11:43

As the README will tell you, the :mode keyword allows you to define a deferred binding (i.e. on-demand), which will load the package when visiting a buffer which filename matches the expression you provided.

The :init and :config keywords are what you are looking for:
They allow you to respectively execute code before and after the package is loaded.

Keeping this in mind, here's what you could do to only load yasnippet in prog-mode buffers:

(use-package yasnippet
  :ensure t
  :init (add-hook 'prog-mode-hook #'yas-minor-mode)
  :config (yas-reload-all))

Using this snippet, yasnippet will actually be loaded on startup, but will only be enabled in the buffers which major mode derive from prog-mode. The appropriate snippets (if any) will then be loaded just-in-time.

  • Thank you for your answer. If I wanted to enable it only for C-mode whis is equivalent to .c files or .h, I could do it with :mode, am I right ? If yes and if I have truely understand, in that case it would be better to use :mode because it the package would be loaded only when needed, correct me if I'm wrong. In my case it's not what I want, but it's for my comprehension. – Nicolas Scotto Di Perto Dec 16 '15 at 14:45
  • 2
    As I understand it, :mode is not really the appropriate keyword here; It is rather used to load the major-mode provided by the package (say, tuareg-mode) when visiting buffers which match the provided expression (e.g. "\\.ml\\'" for ocaml files). – ngqrl Dec 16 '15 at 15:07
  • Are you saying that :mode is more appropriate for major mode requirement ? – Nicolas Scotto Di Perto Dec 16 '15 at 17:01
  • I believe so. Yasnippet is meant to be used as a minor mode (that may be global), not as a major mode. – ngqrl Dec 16 '15 at 18:20
  • Also see yasnippet's README about this – npostavs Dec 16 '15 at 19:23

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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