     (f-expand (concat module-name "/" submodule-name "/" file)
               doom-modules-dir)))
 
-(defun doom-module-pairs ()
-  "TODO"
+(defun doom-module-loaded-p (module submodule)
+  "Returns t if SUBMODULE (in MODULE) is present in `doom-modules'."
+  (memq submodule (cdr (assq module doom-modules))))
+
+(defun doom--module-pairs ()
+  "Returns `doom-modules' as a list of (MODULE . SUBMODULE) cons cells."
   (let (pairs module)
     (dolist (modules doom-modules)
       (setq module (car modules))

        (error "Autoloads file couldn't be generated")))))

(defun doom-initialize-packages (&optional force-p)
  "Parses your Emacs config to keep track of packages declared with `@package'
in `doom-packages' and enabled modules in `doom-modules'."
  (doom-initialize force-p)
  (when (or force-p (not doom-modules) (not doom-packages))
    (setq doom-modules nil)
    (let ((noninteractive t))
      (mapc (lambda (file) (load file nil :nomessage))
            (list (f-expand "packages.el" doom-core-dir)
                  (f-expand "init.el" doom-emacs-dir)))
      ;; Look up packages.el for enabled modules
      (mapc (lambda (file) (load file :noerror :nomessage))
            (--map (doom-module-path (car it) (cdr it) "packages.el")
                   (doom-module-pairs))))))

(defun doom-module-path (module submodule &optional file)
  "Get the full path to a module: e.g. :lang emacs-lisp maps to

;;; core-packages.el
;;
;; Emacs package management is opinionated. Unfortunately, so am I. So with the
;; help of `use-package', `quelpa' and package.el, DOOM Emacs manages my
;; plugins and internal module dependency chains.
;;
;; So I've divided my config into two parts: configuration and
;; packages/dependency control. You'll find packages.el files in each DOOM
;; module (in `doom-modules-dir') and one in `doom-core-dir'. When executed,
;; they fill `doom-packages' and `doom-modules', which are necessary for DOOM to
;; extrapolate all kinds of information about plugins.
;;
;; Why all the trouble? Because:
;; 1. Scriptability: I want my plugins managable from the command line. This
;;    means a `doom/packages-update' command I can call to programmatically
;;    update my plugins, rather than through package.el's interface.
;; 2. Flexibility: I want to install packages from sources other than ELPA. Like
;;    github or the Emacs wiki. Some plugins are out-of-date through official
;;    channels, have changed hands unofficially, or simply haven't been
;;    submitted to an ELPA repo yet.
;; 3. Stability: I don't want to worry that each time I use my package
;;    manager something might inexplicably go wrong. Cask, which I used
;;    previously, was horribly unstable. package.el and quelpa, however, appear
;;    very stable (and much faster).
;; 4. Performance: A minor point, but it helps startup performance not to do
;;    package.el initialization and package installation checks at startup.
;; 5. Simplicity: Without Cask, I have no external dependencies to worry about
;;    (unless make counts). DOOM handles itself. Arguably, my emacs.d is
;;    overcomplicated, but configuring is simpler as a result (well, for me
;;    anyway :P).
;;
;; It should be safe to use package.el functionality, however, avoid
;; `package-autoremove' as it may not reliably select the right packages to
;; delete.
;;
;; For complete certainty, I've provided DOOM alternatives of package commands,
;; like `doom/install-package', `doom/delete-package' and
;; `doom/update-packages'. As well as: `doom/packages-install',
;; `doom/packages-update' and `doom/packages-autoremove', which are called from
;; the Makefile tasks.
;;
;; See core/autoload/packages.el for more functions.

(defvar doom-init-p nil
  "Non-nil if doom's package system has been initialized or not. It may not be
if you have byte-compiled your configuration (as intended). Running
`doom-initialize' sets this.")

(defvar doom-modules nil
  "Alist of enabled modules; each element is a list, whose CAR is a module
keyword, and whose CDR is a list of submodule symbols.")

(defvar doom-packages nil
  "A list of enabled packages. Each element is a sublist, whose CAR is the
package's name as a symbol, and whose CDR is the plist supplied to its
`@package' declaration.")

(defvar doom-protected-packages
  '(quelpa use-package dash f s)
  "A list of packages that must be installed (and will be auto-installed if
missing) and shouldn't be deleted.")

(defvar doom--base-load-path
  (append (list doom-core-dir doom-modules-dir)
          load-path)
  "A backup of `load-path' before it was altered by `doom-initialize'. Used as a
base when running `doom/reload', or by `@doom', for calculating how many
packages exist.")

(setq load-prefer-newer nil
      package--init-file-ensured t
