96 lines
3.4 KiB
EmacsLisp
96 lines
3.4 KiB
EmacsLisp
;;; feature-pkg.el --- Brief description -*- lexical-binding: t; -*-
|
|
;;; Commentary:
|
|
;;;
|
|
;;; This feature provides a simple and predictable package management
|
|
;;; framework building upon built-in Emacs package management
|
|
;;; features. Frameworks like use-package and leaf are nice, but
|
|
;;; become difficult to manage and debug over time . feature-pkg.el
|
|
;;; is the foundation for adding and removing features in this Emacs
|
|
;;; configuration.
|
|
;;;
|
|
;;; Note that feature-pkg does not explicitly need to be required in
|
|
;;; the main Emacs config, as it will be loaded as a dependency by
|
|
;;; each feature.
|
|
|
|
;;; Code:
|
|
|
|
(require 'package)
|
|
(with-eval-after-load 'package
|
|
(add-to-list 'package-archives
|
|
'("melpa" . "https://melpa.org/packages/")
|
|
'("nongnu" . "https://elpa.nongnu.org/nongnu/")))
|
|
(package-initialize)
|
|
|
|
;; install straight.el
|
|
(defvar bootstrap-version)
|
|
(let ((bootstrap-file
|
|
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
|
|
(bootstrap-version 5))
|
|
(unless (file-exists-p bootstrap-file)
|
|
(with-current-buffer
|
|
(url-retrieve-synchronously
|
|
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
|
|
'silent 'inhibit-cookies)
|
|
(goto-char (point-max))
|
|
(eval-print-last-sexp)))
|
|
(load bootstrap-file nil 'nomessage))
|
|
|
|
(defun pkg/ensure-installed (package)
|
|
"Ensure that PACKAGE is installed."
|
|
(unless (package-installed-p package)
|
|
(package-refresh-contents)
|
|
(package-install package)))
|
|
|
|
(defmacro pkg/require (feature &optional filename noerror)
|
|
"Ensure FEATURE is installed, then require it.
|
|
FILENAME and NOERROR are passed to `require'."
|
|
`(progn
|
|
(pkg/ensure-installed ,feature)
|
|
(require ,feature ,filename ,noerror)))
|
|
|
|
(defmacro pkg/require-defer (feature &optional filename noerror)
|
|
"Defer loading of FEATURE until it's actually needed.
|
|
Ensure FEATURE is installed first.
|
|
FILENAME, if non-nil, is the file to load to provide FEATURE.
|
|
If NOERROR is non-nil, don't signal an error if the file is not found."
|
|
(let ((feature-sym (if (and (listp feature) (eq (car feature) 'quote))
|
|
(cadr feature)
|
|
feature)))
|
|
`(progn
|
|
(pkg/ensure-installed ',feature-sym)
|
|
(unless (featurep ',feature-sym)
|
|
(autoload #',(intern (format "%s-autoloaded" feature-sym))
|
|
,(or filename (symbol-name feature-sym))
|
|
nil t)
|
|
(defalias ',feature-sym #',(intern (format "%s-autoloaded" feature-sym))))
|
|
',feature-sym)))
|
|
|
|
(defun pkg/require-defer-load (feature)
|
|
"Check if a deferred FEATURE is already loaded."
|
|
(unless (featurep feature)
|
|
(unload-feature feature t)
|
|
(require feature)
|
|
(fmakunbound (intern (format "%s-autoloaded" feature))))
|
|
feature)
|
|
|
|
(defmacro pkg/require-defer-timer (feature seconds)
|
|
"Ensure FEATURE is installed, then defer its loading by SECONDS idle time."
|
|
`(progn
|
|
(pkg/ensure-installed ,feature)
|
|
(run-with-idle-timer ,seconds nil #'require ',feature)))
|
|
|
|
(defun pkg/packages-loaded-p (&rest packages)
|
|
"Return t if all PACKAGES are loaded."
|
|
(cl-every #'featurep packages))
|
|
|
|
(defmacro pkg/with-eval-after-load (packages &rest body)
|
|
"Run BODY after all PACKAGES are loaded."
|
|
`(if (apply #'pkg/packages-loaded-p ',packages)
|
|
(progn ,@body)
|
|
(eval-after-load (car (last ',packages))
|
|
'(pkg/run-after-packages-load ',packages ,@body))))
|
|
|
|
(provide 'module-pkg)
|
|
|
|
;;; module-pkg.el ends here.
|