From 767497ece4b06f12ad04b40131aeee57bcbc6bd4 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Mon, 8 Mar 2021 18:00:13 -0600 Subject: Almost finished with `acdw/pkg' Still some bugs to squash. --- lisp/acdw.el | 135 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 40 deletions(-) (limited to 'lisp') diff --git a/lisp/acdw.el b/lisp/acdw.el index 7f0145c..927b083 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el @@ -22,6 +22,14 @@ ;; ;;; Code: +;;; Utilities +(defun acdw/when-unfocused (func &rest args) + "Call FUNC, with ARGS, iff all Emacs frames are out of focus. + +Ready for use with `after-focus-change-function'." + (when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) + (apply func args))) + ;;; Directories (think `no-littering') (defvar acdw/dir (expand-file-name @@ -71,26 +79,6 @@ SPEC is as for `defface'." ;;; Hooks -;; XXX NOT WORKING -(defmacro acdw/defun-hook (hook docstring &optional depth local &rest forms) - "Add FORMS to a function described by DOCSTRING, then add that - function to HOOK. DOCSTRING is converted to a function name by - calling `docstring-to-symbol', if it's a string, or used as-is - otherwise. The optional DEPTH and LOCAL are passed to - `add-hook', if they're present (i.e., not a list). - -This macro aims to split the difference between the syntax of -lambdas in hooks and the ability to easily disable hooks." - (declare (indent 2)) - (let ((name (if (stringp docstring) - (docstring-to-symbol docstring "hook-") - docstring))) - (when (listp local) (push local forms) (setq local nil)) - (when (listp depth) (push depth forms) (setq depth 0)) - `(progn - (defun ,name () ,@forms) - (add-hook ,hook #',name ,depth ,local)))) - (defmacro acdw/hooks (hooks funcs &optional depth local) "Add FUNCS to HOOKS. @@ -110,15 +98,15 @@ more fine-grained control, just use `add-hook'." `(progn ,@hook-list))) -;; Utilities -(defun docstring-to-symbol (docstring &optional prefix) - "Convert a DOCSTRING to a symbol by lowercasing the string, -converting non-symbol-safe characters to '-', and calling - `intern'. Returns the created symbol." - (let ((str (split-string (downcase docstring) "[ \f\t\n\r\v'\"`,]+" - :omit-nulls))) - (when prefix (push prefix str)) - (intern (mapconcat #'identity str "-")))) +(defmacro acdw/hooks-after (file hooks funcs &optional depth local) + "Add FUNCS, from FILE, to HOOKS." + (let ((funcs (if (listp funcs) funcs (list funcs))) + (autoload-list)) + (dolist (func funcs) + (add-to-list 'autoload-list `(autoload #',func ,file))) + `(progn + ,@autoload-list + (acdw/hooks ,hooks ,funcs ,depth ,local)))) ;;; Keybindings @@ -134,12 +122,12 @@ otherwise it's wrapped in `read-kbd-macro'. The following keywords are recognized: -:autoload ARGS .. call `autoload' on COMMAND using ARGS before - binding the key. ARGS can be just the filename to load; in - that case it's wrapped in a list. +:after ARGS .. call `autoload' on COMMAND using ARGS before + binding the key. ARGS can be just the filename to + load; in that case it's wrapped in a list. :map KEYMAP .. define KEY in KEYMAP instead of the default `acdw/bind-default-map'." - (let ((autoload (when-let (sym (plist-get args :autoload)) + (let ((after (when-let (sym (plist-get args :after)) (if (not (listp sym)) (list sym) sym))) @@ -147,24 +135,59 @@ The following keywords are recognized: (keycode (if (vectorp key) key (kbd key))) (command-list)) (push `(define-key ,keymap ,keycode ,command) command-list) - (when autoload - (push `(autoload ,command ,@autoload) command-list)) + (when after + (push `(autoload ,command ,@after) command-list)) `(progn ,@command-list))) ;; convenience -(defmacro acdw/bind-after-map (file keymap &rest bindings) +(defmacro acdw/bind-after-map (file keymap bindings) "Wrap multiple calls of `acdw/bind' after FILE and with KEYMAP. KEYMAP can be nil." (declare (indent 2)) - (let (bind-list) + (let ((bind-list) + (extra-args (if keymap + `(:after ,file :map ,keymap) + `(:after ,file)))) (dolist (binding bindings) - (if keymap - (push `(acdw/bind ,@binding :after ,file :map ,keymap) bind-list) - (push `(acdw/bind ,@binding :after ,file) bind-list))) + (push `(acdw/bind ,@binding ,@extra-args) bind-list)) `(progn ,@bind-list))) +;;; Packages + +(defmacro acdw/pkg (package &rest args) + "Set up a package using `straight.el'. + +ARGS can include the following keywords: + +:now FORMS .. run forms immediately. + Good for settings and auxiliary functions. +:then FORMS .. run forms after loading PACKAGE, using `with-eval-after-load'. +:binds BINDS .. run `acdw/bind-after-map' on BINDS. +:hooks HOOKS .. run `acdw/hooks-after' on HOOKS." + (declare (indent 1)) + (let ((now-forms (plist-get args :now)) + (binds (plist-get args :binds)) + (hooks (plist-get args :hooks)) + (then-forms (plist-get args :then)) + (requirement (if (listp package) + (car package) + package)) + (final-form)) + (when then-forms + (push `(with-eval-after-load ',requirement ,@then-forms) final-form)) + (when hooks + (push `(acdw/hooks-after ,(symbol-name requirement) ,hooks) final-form)) + (when binds + (push `(acdw/bind-after-map ,(symbol-name requirement) nil ,binds) + final-form)) + (when now-forms + (push `(progn ,@now-forms) final-form)) + (push `(straight-use-package ',package) final-form) + `(progn + ,@final-form))) + ;;; Keymap & Mode (defvar acdw/map (make-sparse-keymap) @@ -193,3 +216,35 @@ KEYMAP can be nil." (provide 'acdw) ;;; acdw.el ends here + +;;; Elephant graveyard + +;; XXX NOT WORKING -- And is this even necessary? +;; (defmacro acdw/defun-hook (hook docstring &optional depth local &rest forms) +;; "Add FORMS to a function described by DOCSTRING, then add that +;; function to HOOK. DOCSTRING is converted to a function name by +;; calling `docstring-to-symbol', if it's a string, or used as-is +;; otherwise. The optional DEPTH and LOCAL are passed to +;; `add-hook', if they're present (i.e., not a list). + +;; This macro aims to split the difference between the syntax of +;; lambdas in hooks and the ability to easily disable hooks." +;; (declare (indent 2)) +;; (let ((name (if (stringp docstring) +;; (docstring-to-symbol docstring "hook-") +;; docstring))) +;; (when (listp local) (push local forms) (setq local nil)) +;; (when (listp depth) (push depth forms) (setq depth 0)) +;; `(progn +;; (defun ,name () ,@forms) +;; (add-hook ,hook #',name ,depth ,local)))) + +;; Utilities XXX related to `acdw/defun-hook' +;; (defun docstring-to-symbol (docstring &optional prefix) +;; "Convert a DOCSTRING to a symbol by lowercasing the string, +;; converting non-symbol-safe characters to '-', and calling +;; `intern'. Returns the created symbol." +;; (let ((str (split-string (downcase docstring) "[ \f\t\n\r\v'\"`,]+" +;; :omit-nulls))) +;; (when prefix (push prefix str)) +;; (intern (mapconcat #'identity str "-")))) -- cgit 1.4.1-21-gabe81