`setup.el` ========== The `setup` macro simplifies repetitive configuration patterns, by providing context-sensitive local macros in `setup` bodies. For example, these macros: ~~~elisp (setup shell (let ((key (kbd "C-c s"))) (:global key shell) (:bind key bury-buffer))) (setup dired (:also-load dired-x) (:option (prepend dired-guess-shell-alist-user) '("" "xdg-open") dired-dwim-target t) (:hook auto-revert-mode)) (setup (:package paredit) (:hide-mode) (:hook-into scheme-mode lisp-mode)) ~~~ will be replaced with the functional equivalent of ~~~elisp (global-set-key (kbd "C-c s") #'shell) (with-eval-after-load 'shell (define-key shell-mode-map (kbd "C-c s") #'bury-buffer)) (with-eval-after-load 'dired (require 'dired-x)) (customize-set-variable 'dired-guess-shell-alist-user (cons '("" "xdg-open") dired-guess-shell-alist-user)) (customize-set-variable 'dired-dwim-target t) (add-hook 'dired-mode-hook #'auto-revert-mode) (unless (package-install-p 'paredit) (package-install 'paredit)) (setq minor-mode-alist (delq (assq 'paredit-mode minor-mode-alist) minor-mode-alist)) (add-hook 'scheme-mode-hook #'paredit-mode) (add-hook 'lisp-mode-hook #'paredit-mode) ~~~ Additional "keywords" can be defined using `setup-define`. All known keywords are documented in the docstring for `setup`. Installation ------------ `setup.el` is part of [GNU ELPA][elpa], and can be installed using `package.el`. Usage ----- The `setup` macro is autoloaded, and can be used directly. The code generated by `setup` does not depend on `setup.el`, meaning that your initialization file can be byte-compiled more efficiently. Tips ---- 1. The first element of a `setup` body can but does not have to be a name. That can be exploited to use `setup` in your own macros. I have this macro in my personal configuration, when I'm only interested in modifying user options: ~~~elisp (defmacro setc (&rest args) "Customize user options using ARGS like `setq'." (declare (debug setq)) `(setup (:option ,@args))) ~~~ 2. If you wish to define you own macros, use `setup-define`. In case the syntax is too cumbersome, you can use a macro like this: ~~~elisp (defmacro defsetup (name signature &rest body) "Shorthand for `setup-define'. NAME is the name of the local macro. SIGNATURE is used as the argument list for FN. If BODY starts with a string, use this as the value for :documentation. Any following keywords are passed as OPTS to `setup-define'." (declare (debug defun)) (let (opts) (when (stringp (car body)) (setq opts (nconc (list :documentation (pop body)) opts))) (while (keywordp (car body)) (let* ((prop (pop body)) (val `',(pop body))) (setq opts (nconc (list prop val) opts)))) `(setup-define ,name (cl-function (lambda ,signature ,@body)) ,@opts))) ~~~ To declare local macros more like `defun` or `defmacro`. Here is how the definition for `:package` could be rewritten: ~~~elisp (defsetup :package (package) "Install PACKAGE if it hasn't been installed yet." :repeatable t :shorthand #'cadr `(unless (package-installed-p ',package) (package-install ',package))) ~~~ Bugs ---- Bugs or patches can be submitted to my [public inbox][mail] or via the [GitHub mirror][github]. Note that non-trivial contributions require a [copyright assignment][ca] to the FSF. This package is still young, so wishes, impressions and criticism are very appreciated. If you have anything to say, feel free to send an email to the aforementioned [public inbox][mail]. Copying ------- `setup.el` is distributed under the [GPL v3][gpl3] license. [elpa]: http://elpa.gnu.org/packages/setup.html [mail]: https://lists.sr.ht/~zge/public-inbox [github]: https://github.com/phikal/setup.el [ca]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Copyright-Assignment.html#Copyright-Assignment [gpl3]: https://www.gnu.org/licenses/gpl-3.0.en.html