emacs/lisp/+setup.el

106 lines
3.3 KiB
EmacsLisp

;;; +setup.el -- my `setup' commands -*- lexical-binding: t -*-
;; Author: Case Duckworth <acdw@acdw.net>
;; This file is NOT part of GNU Emacs.
;;; License:
;; Everyone is permitted to do whatever with this software, without
;; limitation. This software comes without any warranty whatsoever,
;; but with two pieces of advice:
;; - Don't hurt yourself.
;; - Make good choices.
;;; Commentary:
;; `setup', by Philip Kaludercic, is a wonderful package that works
;; sort of like `use-package', but to my mind it's cleaner and easier
;; to extend. These are my additions to the local macros provided by
;; the package.
;;; Code:
(require 'el-patch)
(require 'setup)
(require 'straight)
;; I don't like the "magic" `setup' performs to ensure a symbol is a
;; function in `:global', `:bind', `:hook', `:hook-into', and others.
;; So here, I'll just make it return the symbol unmodified.
(el-patch-feature setup)
(with-eval-after-load 'setup
(el-patch-defvar
(el-patch-add setup-ensure-function-inhibit nil
"Whether to inhibit `setup-ensure-function'."))
(el-patch-defun setup-ensure-function (sexp)
(el-patch-concat
"Attempt to return SEXP as a quoted function name."
(el-patch-add
"\nIf `setup-ensure-function-inhibit' is non-nil, just return SEXP."))
(el-patch-wrap 3 0
(if (and setup-ensure-function-inhibit
(not (eq sexp (setup-get 'mode))))
sexp
(cond ((eq (car-safe sexp) 'function)
sexp)
((eq (car-safe sexp) 'quote)
`#',(cadr sexp))
((symbolp sexp)
`#',sexp)
(sexp))))))
(setup-define :face
(lambda (face spec)
`(custom-set-faces '(,face ,spec 'now "Customized by `setup'.")))
:documentation "Customize FACE with SPEC using `custom-set-faces'."
:repeatable t)
(setup-define :load-after
(lambda (&rest features)
(let ((body `(require ',(setup-get 'feature))))
(dolist (feature (nreverse features))
(setq body `(with-eval-after-load ',feature ,body)))
body))
:documentation "Load the current feature after FEATURES.")
(setup-define :also-straight
(lambda (recipe) `(setup (:straight ,recipe)))
:documentation
"Install RECIPE with `straight-use-package', after loading FEATURE."
:repeatable t
:after-loaded t)
(setup-define :straight
(lambda (recipe)
`(unless (straight-use-package ',recipe)
,(setup-quit)))
:documentation
"Install RECIPE with `straight-use-package'.
This macro can be used as HEAD, and will replace itself with the
first RECIPE's package."
:repeatable t
:shorthand (lambda (sexp)
(let ((recipe (cadr sexp)))
(if (consp recipe)
(car recipe)
recipe))))
(setup-define :straight-when
(lambda (recipe condition)
`(unless (and ,condition
(straight-use-package ',recipe))
,(setup-quit)))
:documentation
"Install RECIPE with `straight-use-package' when CONDITION is met.
If CONDITION is false, or if `straight-use-package' fails, stop
evaluating the body. This macro can be used as HEAD, and will
replace itself with the RECIPE's package."
:repeatable 2
:indent 1
:shorthand (lambda (sexp)
(let ((recipe (cadr sexp)))
(if (consp recipe) (car recipe) recipe))))
(provide '+setup)
;;; +setup.el ends here