7

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.

2
  • Please clarify your question. What have you tried, and what is not working?
    – Dan
    Commented Dec 16, 2015 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. Commented Dec 16, 2015 at 14:28

2 Answers 2

6

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)))
5
  • What does it do ? Commented Dec 16, 2015 at 17:02
  • It does what you asked in the question :) I will update the answer for clarity. Commented Dec 16, 2015 at 17:03
  • @NicolasScottoDiPerto Let me know if the added explanation helps. Commented Dec 16, 2015 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 ! Commented Dec 17, 2015 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. Commented Dec 17, 2015 at 11:43
11

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.

5
  • 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. Commented Dec 16, 2015 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
    Commented Dec 16, 2015 at 15:07
  • Are you saying that :mode is more appropriate for major mode requirement ? Commented Dec 16, 2015 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
    Commented Dec 16, 2015 at 18:20
  • Also see yasnippet's README about this
    – npostavs
    Commented Dec 16, 2015 at 19:23

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.