summary refs log tree commit diff stats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/acdw.el135
1 files changed, 95 insertions, 40 deletions
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 @@
22;; 22;;
23;;; Code: 23;;; Code:
24 24
25;;; Utilities
26(defun acdw/when-unfocused (func &rest args)
27 "Call FUNC, with ARGS, iff all Emacs frames are out of focus.
28
29Ready for use with `after-focus-change-function'."
30 (when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))
31 (apply func args)))
32
25;;; Directories (think `no-littering') 33;;; Directories (think `no-littering')
26 34
27(defvar acdw/dir (expand-file-name 35(defvar acdw/dir (expand-file-name
@@ -71,26 +79,6 @@ SPEC is as for `defface'."
71 79
72;;; Hooks 80;;; Hooks
73 81
74;; XXX NOT WORKING
75(defmacro acdw/defun-hook (hook docstring &optional depth local &rest forms)
76 "Add FORMS to a function described by DOCSTRING, then add that
77 function to HOOK. DOCSTRING is converted to a function name by
78 calling `docstring-to-symbol', if it's a string, or used as-is
79 otherwise. The optional DEPTH and LOCAL are passed to
80 `add-hook', if they're present (i.e., not a list).
81
82This macro aims to split the difference between the syntax of
83lambdas in hooks and the ability to easily disable hooks."
84 (declare (indent 2))
85 (let ((name (if (stringp docstring)
86 (docstring-to-symbol docstring "hook-")
87 docstring)))
88 (when (listp local) (push local forms) (setq local nil))
89 (when (listp depth) (push depth forms) (setq depth 0))
90 `(progn
91 (defun ,name () ,@forms)
92 (add-hook ,hook #',name ,depth ,local))))
93
94(defmacro acdw/hooks (hooks funcs &optional depth local) 82(defmacro acdw/hooks (hooks funcs &optional depth local)
95 "Add FUNCS to HOOKS. 83 "Add FUNCS to HOOKS.
96 84
@@ -110,15 +98,15 @@ more fine-grained control, just use `add-hook'."
110 `(progn 98 `(progn
111 ,@hook-list))) 99 ,@hook-list)))
112 100
113;; Utilities 101(defmacro acdw/hooks-after (file hooks funcs &optional depth local)
114(defun docstring-to-symbol (docstring &optional prefix) 102 "Add FUNCS, from FILE, to HOOKS."
115 "Convert a DOCSTRING to a symbol by lowercasing the string, 103 (let ((funcs (if (listp funcs) funcs (list funcs)))
116converting non-symbol-safe characters to '-', and calling 104 (autoload-list))
117 `intern'. Returns the created symbol." 105 (dolist (func funcs)
118 (let ((str (split-string (downcase docstring) "[ \f\t\n\r\v'\"`,]+" 106 (add-to-list 'autoload-list `(autoload #',func ,file)))
119 :omit-nulls))) 107 `(progn
120 (when prefix (push prefix str)) 108 ,@autoload-list
121 (intern (mapconcat #'identity str "-")))) 109 (acdw/hooks ,hooks ,funcs ,depth ,local))))
122 110
123;;; Keybindings 111;;; Keybindings
124 112
@@ -134,12 +122,12 @@ otherwise it's wrapped in `read-kbd-macro'.
134 122
135The following keywords are recognized: 123The following keywords are recognized:
136 124
137:autoload ARGS .. call `autoload' on COMMAND using ARGS before 125:after ARGS .. call `autoload' on COMMAND using ARGS before
138 binding the key. ARGS can be just the filename to load; in 126 binding the key. ARGS can be just the filename to
139 that case it's wrapped in a list. 127 load; in that case it's wrapped in a list.
140:map KEYMAP .. define KEY in KEYMAP instead of the 128:map KEYMAP .. define KEY in KEYMAP instead of the
141 default `acdw/bind-default-map'." 129 default `acdw/bind-default-map'."
142 (let ((autoload (when-let (sym (plist-get args :autoload)) 130 (let ((after (when-let (sym (plist-get args :after))
143 (if (not (listp sym)) 131 (if (not (listp sym))
144 (list sym) 132 (list sym)
145 sym))) 133 sym)))
@@ -147,24 +135,59 @@ The following keywords are recognized:
147 (keycode (if (vectorp key) key (kbd key))) 135 (keycode (if (vectorp key) key (kbd key)))
148 (command-list)) 136 (command-list))
149 (push `(define-key ,keymap ,keycode ,command) command-list) 137 (push `(define-key ,keymap ,keycode ,command) command-list)
150 (when autoload 138 (when after
151 (push `(autoload ,command ,@autoload) command-list)) 139 (push `(autoload ,command ,@after) command-list))
152 `(progn 140 `(progn
153 ,@command-list))) 141 ,@command-list)))
154 142
155;; convenience 143;; convenience
156(defmacro acdw/bind-after-map (file keymap &rest bindings) 144(defmacro acdw/bind-after-map (file keymap bindings)
157 "Wrap multiple calls of `acdw/bind' after FILE and with KEYMAP. 145 "Wrap multiple calls of `acdw/bind' after FILE and with KEYMAP.
158KEYMAP can be nil." 146KEYMAP can be nil."
159 (declare (indent 2)) 147 (declare (indent 2))
160 (let (bind-list) 148 (let ((bind-list)
149 (extra-args (if keymap
150 `(:after ,file :map ,keymap)
151 `(:after ,file))))
161 (dolist (binding bindings) 152 (dolist (binding bindings)
162 (if keymap 153 (push `(acdw/bind ,@binding ,@extra-args) bind-list))
163 (push `(acdw/bind ,@binding :after ,file :map ,keymap) bind-list)
164 (push `(acdw/bind ,@binding :after ,file) bind-list)))
165 `(progn 154 `(progn
166 ,@bind-list))) 155 ,@bind-list)))
167 156
157;;; Packages
158
159(defmacro acdw/pkg (package &rest args)
160 "Set up a package using `straight.el'.
161
162ARGS can include the following keywords:
163
164:now FORMS .. run forms immediately.
165 Good for settings and auxiliary functions.
166:then FORMS .. run forms after loading PACKAGE, using `with-eval-after-load'.
167:binds BINDS .. run `acdw/bind-after-map' on BINDS.
168:hooks HOOKS .. run `acdw/hooks-after' on HOOKS."
169 (declare (indent 1))
170 (let ((now-forms (plist-get args :now))
171 (binds (plist-get args :binds))
172 (hooks (plist-get args :hooks))
173 (then-forms (plist-get args :then))
174 (requirement (if (listp package)
175 (car package)
176 package))
177 (final-form))
178 (when then-forms
179 (push `(with-eval-after-load ',requirement ,@then-forms) final-form))
180 (when hooks
181 (push `(acdw/hooks-after ,(symbol-name requirement) ,hooks) final-form))
182 (when binds
183 (push `(acdw/bind-after-map ,(symbol-name requirement) nil ,binds)
184 final-form))
185 (when now-forms
186 (push `(progn ,@now-forms) final-form))
187 (push `(straight-use-package ',package) final-form)
188 `(progn
189 ,@final-form)))
190
168;;; Keymap & Mode 191;;; Keymap & Mode
169 192
170(defvar acdw/map (make-sparse-keymap) 193(defvar acdw/map (make-sparse-keymap)
@@ -193,3 +216,35 @@ KEYMAP can be nil."
193 216
194(provide 'acdw) 217(provide 'acdw)
195;;; acdw.el ends here 218;;; acdw.el ends here
219
220;;; Elephant graveyard
221
222;; XXX NOT WORKING -- And is this even necessary?
223;; (defmacro acdw/defun-hook (hook docstring &optional depth local &rest forms)
224;; "Add FORMS to a function described by DOCSTRING, then add that
225;; function to HOOK. DOCSTRING is converted to a function name by
226;; calling `docstring-to-symbol', if it's a string, or used as-is
227;; otherwise. The optional DEPTH and LOCAL are passed to
228;; `add-hook', if they're present (i.e., not a list).
229
230;; This macro aims to split the difference between the syntax of
231;; lambdas in hooks and the ability to easily disable hooks."
232;; (declare (indent 2))
233;; (let ((name (if (stringp docstring)
234;; (docstring-to-symbol docstring "hook-")
235;; docstring)))
236;; (when (listp local) (push local forms) (setq local nil))
237;; (when (listp depth) (push depth forms) (setq depth 0))
238;; `(progn
239;; (defun ,name () ,@forms)
240;; (add-hook ,hook #',name ,depth ,local))))
241
242;; Utilities XXX related to `acdw/defun-hook'
243;; (defun docstring-to-symbol (docstring &optional prefix)
244;; "Convert a DOCSTRING to a symbol by lowercasing the string,
245;; converting non-symbol-safe characters to '-', and calling
246;; `intern'. Returns the created symbol."
247;; (let ((str (split-string (downcase docstring) "[ \f\t\n\r\v'\"`,]+"
248;; :omit-nulls)))
249;; (when prefix (push prefix str))
250;; (intern (mapconcat #'identity str "-"))))