diff options
author | Case Duckworth | 2023-01-20 13:14:55 -0600 |
---|---|---|
committer | Case Duckworth | 2023-01-20 13:14:55 -0600 |
commit | d7824cacb2bb9d0b9c15fa24e15ac367effec9a5 (patch) | |
tree | 78d5a09594dc682595e9450217445d21fe83b87e /lisp/acdw.el | |
parent | Add link-hint (diff) | |
download | emacs-d7824cacb2bb9d0b9c15fa24e15ac367effec9a5.tar.gz emacs-d7824cacb2bb9d0b9c15fa24e15ac367effec9a5.zip |
meh
Diffstat (limited to 'lisp/acdw.el')
-rw-r--r-- | lisp/acdw.el | 119 |
1 files changed, 116 insertions, 3 deletions
diff --git a/lisp/acdw.el b/lisp/acdw.el index a05295c..3b178db 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el | |||
@@ -2,6 +2,9 @@ | |||
2 | 2 | ||
3 | ;;; Code: | 3 | ;;; Code: |
4 | 4 | ||
5 | (require 'cl-lib) | ||
6 | (require 'seq) | ||
7 | |||
5 | (defmacro defdir (name directory &optional docstring makedir) | 8 | (defmacro defdir (name directory &optional docstring makedir) |
6 | "Define a variable and a function NAME expanding to DIRECTORY. | 9 | "Define a variable and a function NAME expanding to DIRECTORY. |
7 | DOCSTRING is applied to the variable; its default is DIRECTORY's | 10 | DOCSTRING is applied to the variable; its default is DIRECTORY's |
@@ -22,9 +25,9 @@ be created." | |||
22 | (make-directory (file-name-directory file-name) :parents)) | 25 | (make-directory (file-name-directory file-name) :parents)) |
23 | file-name)) | 26 | file-name)) |
24 | ,(if makedir | 27 | ,(if makedir |
25 | `(make-directory ,directory :parents) | 28 | `(make-directory ,directory :parents) |
26 | `(unless (file-exists-p ,directory) | 29 | `(unless (file-exists-p ,directory) |
27 | (warn "Directory `%s' doesn't exist." ,directory))))) | 30 | (warn "Directory `%s' doesn't exist." ,directory))))) |
28 | 31 | ||
29 | (defun choose-executable (&rest programs) | 32 | (defun choose-executable (&rest programs) |
30 | "Return the first of PROGRAMS that exists in the system's $PATH. | 33 | "Return the first of PROGRAMS that exists in the system's $PATH. |
@@ -85,6 +88,17 @@ If `:separator' is the first of STRINGS, the next string will be | |||
85 | used as a separator." | 88 | used as a separator." |
86 | (++concat #'format strings)) | 89 | (++concat #'format strings)) |
87 | 90 | ||
91 | (defun list-append-removing-duplicates (&rest lists) | ||
92 | "Append LISTS, removing duplicates from the result. | ||
93 | Any keyword arguments to `cl-remove-duplicates' should come | ||
94 | before the LISTS." | ||
95 | (let (cl-remove-duplicates-args) | ||
96 | (while (keywordp (car lists)) | ||
97 | (push (pop lists) cl-remove-duplicates-args) | ||
98 | (push (pop lists) cl-remove-duplicates-args)) | ||
99 | (apply #'cl-remove-duplicates (apply #'append lists) | ||
100 | (nreverse cl-remove-duplicates-args)))) | ||
101 | |||
88 | (defun mapc-buffers (func &optional predicate) | 102 | (defun mapc-buffers (func &optional predicate) |
89 | "Map FUNC over buffers matching PREDICATE. | 103 | "Map FUNC over buffers matching PREDICATE. |
90 | Both FUNC and PREDICATE will be executed with no arguments and in | 104 | Both FUNC and PREDICATE will be executed with no arguments and in |
@@ -125,6 +139,83 @@ each buffer." | |||
125 | (progress-reporter-done ,prog))))) | 139 | (progress-reporter-done ,prog))))) |
126 | 140 | ||
127 | 141 | ||
142 | |||
143 | ;;; Ispell in .dir-locals | ||
144 | |||
145 | ;; Let Emacs know a list of strings is safe | ||
146 | (defun +ispell-safe-local-p (list) | ||
147 | (and (listp list) | ||
148 | (seq-every-p #'stringp list))) | ||
149 | |||
150 | ;; Can I instruct ispell to insert LocalWords in a different file? | ||
151 | ;; https://emacs.stackexchange.com/q/31396/2264 | ||
152 | |||
153 | ;; How can I move all my file-local LocalWords to .dir-locals.el? | ||
154 | ;; https://emacs.stackexchange.com/q/31419 | ||
155 | |||
156 | ;; Adapted from ispell.el:ispell-buffer-local-words | ||
157 | (defun +ispell-buffer-local-words-list () | ||
158 | (let (words) | ||
159 | (or ispell-buffer-local-name | ||
160 | (setf ispell-buffer-local-name (buffer-name))) | ||
161 | (save-excursion | ||
162 | (goto-char (point-min)) | ||
163 | (while (search-forward ispell-words-keyword nil t) | ||
164 | (let ((end (point-at-eol)) | ||
165 | (ispell-casechars (ispell-get-casechars)) | ||
166 | string) | ||
167 | (while (re-search-forward " *\\([^ ]+\\)" end t) | ||
168 | (setf string (match-string-no-properties 1)) | ||
169 | (if (and (< 1 (length string)) | ||
170 | (equal 0 (string-match ispell-casechars string))) | ||
171 | (push string words)))))) | ||
172 | words)) | ||
173 | |||
174 | ;;;###autoload | ||
175 | (defun +ispell-move-buffer-words-to-dir-locals (&optional arg) | ||
176 | "Move the current buffer-local words to .dir-locals.el. | ||
177 | This function prompts the user to save .dir-locals.el, unless | ||
178 | prefix ARG is non-nil; then it just saves them." | ||
179 | (interactive "P") | ||
180 | (unless (buffer-file-name) | ||
181 | (user-error "Buffer not attached to file")) | ||
182 | (hack-dir-local-variables) | ||
183 | (let ((print-level nil) | ||
184 | (print-length nil)) | ||
185 | (when-let ((new-words (cl-remove-if | ||
186 | (lambda (el) (eq el '\.\.\.)) ; XXX: NO IDEA | ||
187 | ; where this came from | ||
188 | (list-append-removing-duplicates | ||
189 | :test #'string= | ||
190 | ispell-buffer-session-localwords | ||
191 | (alist-get 'ispell-buffer-session-localwords | ||
192 | dir-local-variables-alist) | ||
193 | (alist-get 'ispell-buffer-session-localwords | ||
194 | file-local-variables-alist) | ||
195 | (+ispell-buffer-local-words-list))))) | ||
196 | (save-excursion | ||
197 | (add-dir-local-variable | ||
198 | major-mode | ||
199 | 'ispell-buffer-session-localwords | ||
200 | (setf ispell-buffer-session-localwords | ||
201 | new-words)) | ||
202 | (when (or arg | ||
203 | (y-or-n-p "Save .dir-locals.el?")) | ||
204 | (save-buffer)) | ||
205 | (bury-buffer)) | ||
206 | (or ispell-buffer-local-name | ||
207 | (setf ispell-buffer-local-name (buffer-name))) | ||
208 | (save-excursion | ||
209 | (goto-char (point-min)) | ||
210 | (while (search-forward ispell-words-keyword nil t) | ||
211 | (delete-region (point-at-bol) (1+ (point-at-eol)))))))) | ||
212 | |||
213 | ;;;###autoload | ||
214 | (defun +ispell-move-buffer-words-to-dir-locals-hook () | ||
215 | "Convenience function for binding to a hook." | ||
216 | (+ispell-move-buffer-words-to-dir-locals t)) | ||
217 | |||
218 | |||
128 | ;;; Comment-or-uncomment-sexp | 219 | ;;; Comment-or-uncomment-sexp |
129 | ;; from https://endlessparentheses.com/a-comment-or-uncomment-sexp-command.html | 220 | ;; from https://endlessparentheses.com/a-comment-or-uncomment-sexp-command.html |
130 | 221 | ||
@@ -214,5 +305,27 @@ With a prefix argument N, (un)comment that many sexps." | |||
214 | (dotimes (_ (or n 1)) | 305 | (dotimes (_ (or n 1)) |
215 | (+lisp-comment-sexp--raw)))) | 306 | (+lisp-comment-sexp--raw)))) |
216 | 307 | ||
308 | |||
309 | ;;; Random shit | ||
310 | |||
311 | (defun insert-iso-date (&optional arg) | ||
312 | "Insert current date formatted ISO-8601 style. | ||
313 | When called with \\[universal-argument] \\[insert-iso-date], | ||
314 | include the time. When called with \\[universal-argument] | ||
315 | \\[universal-argument] \\[insert-iso-date], prompt the user for the | ||
316 | `format-time-string' format to use." | ||
317 | (interactive "P") | ||
318 | (insert (format-time-string (pcase arg | ||
319 | ('nil "%F") | ||
320 | ('(4) "%FT%T%z") | ||
321 | (_ (read-string "Time format: ")))))) | ||
322 | |||
323 | (defun unfill-paragraph () | ||
324 | "Unfill the current paragraph." | ||
325 | (interactive) | ||
326 | (let ((fill-column most-positive-fixnum) | ||
327 | (fill-paragraph-function nil)) | ||
328 | (fill-paragraph))) | ||
329 | |||
217 | (provide 'acdw) | 330 | (provide 'acdw) |
218 | ;;; acdw.el ends here | 331 | ;;; acdw.el ends here |