6

I found that there's a :requires (source) section, but I'm not quite sure what it does and there doesn't seem to be any documentation on it. Can someone explain what it does?

4

Unfortunately, use-package is not as thoroughly documented as it should be. I remember finding an explanation of this keyword at some point, but can't seem to turn it up now. Looking at the source for use-package-handler/:requires, I think what this does is make the entire use-package block conditional on the presence of the specified feature(s).

Macroexpanding a sample block seems to confirm this interpretation. Take

(use-package foo
  :requires (bar baz)
  :config
  (blah))

and call pp-macroexpand-last-sexp on it. You get this:

(if
    (not
     (member nil
             (mapcar #'featurep
                     '(bar baz))))
    (progn
      (if
          (not
           (require 'foo nil 'noerror))
          (ignore
           (message
            (format "Could not load %s" 'foo)))
        (condition-case-unless-debug err
            (blah)
          (error
           (ignore
            (display-warning 'use-package
                             (format "%s %s: %s" "foo" ":config"
                                     (error-message-string err))
                             :error))))
        t)))

If you remove the :requires line and try again, you get just the contents of the progn form. So if all of the features you listed are present at the time the block is being executed, then everything's the same. If any feature is missing, nothing is loaded whatsoever.

  • Oh wow okay. I was imagining perhaps it expanded to a (require 'feature) for each feature listed and then the rest of the expansion, to ensure that the features were loaded by the time the body ran. This seems like it's more for chaining for example with other packages that use :if or :when. Instead of repeating the conditions in a package that depends on those, you can just do something like :requires (a b). If their :if fail and they never load, then the one that :requires will never load either. At least, that's the only use case I can envision at the moment. – Jorge Israel Peña Jan 20 '16 at 23:34
  • 1
    By the way, I'm happy to learn about that macro expansion tool! – Jorge Israel Peña Jan 20 '16 at 23:35
  • Actually it does call (require, so it will end up loading the specified features as I was saying, but in the event that those features aren't available at the time the require runs, then the condition turns false and so the package is never loaded. Does that sound right? – Jorge Israel Peña Jan 20 '16 at 23:37
  • I think your dependency-chain use case is the most likely one. I could also see using it if you're not sure you'll have a particular package available for some reason (a multi-machine setup where your packages aren't synchronized, for instance). – Aaron Harris Jan 21 '16 at 0:49
  • The only require call I see is requiring foo, the base package, and is already past the conditional that checks for the presence of bar and baz. So that's just the use-package call itself. – Aaron Harris Jan 21 '16 at 0:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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