diff options
Diffstat (limited to 'lisp/acdw-funs.el')
-rw-r--r-- | lisp/acdw-funs.el | 262 |
1 files changed, 0 insertions, 262 deletions
diff --git a/lisp/acdw-funs.el b/lisp/acdw-funs.el deleted file mode 100644 index ed41a61..0000000 --- a/lisp/acdw-funs.el +++ /dev/null | |||
@@ -1,262 +0,0 @@ | |||
1 | ;;; acdw-funs.el --- extra functions -*- lexical-binding: t -*- | ||
2 | |||
3 | |||
4 | ;;; Cribs from CRUX --- Advice | ||
5 | ;; https://github.com/bbatsov/crux | ||
6 | |||
7 | ;; All of these should go `:before' the function they're advising | ||
8 | (defun advise-region-or-buffer (&rest _) | ||
9 | "`:before' advice to work on the active region or whole buffer. | ||
10 | See also `with-region-or-buffer'." | ||
11 | (interactive (if mark-active | ||
12 | (list (region-beginning) (region-end)) | ||
13 | (list (point-min) (point-max))))) | ||
14 | |||
15 | (defun advise-region-or-line (&rest _) | ||
16 | "`:before' advice to work on the active region or whole line. | ||
17 | See also `with-region-or-line'." | ||
18 | (interactive (if mark-active | ||
19 | (list (region-beginning) (region-end)) | ||
20 | (list (line-beginning-position) (line-end-position))))) | ||
21 | |||
22 | (defun advise-region-or-to-eol (&rest _) | ||
23 | "`:before' advice to work on the active region or to end of line. | ||
24 | See also `with-region-or-to-eol'." | ||
25 | (INTERACTIVE (if mark-active | ||
26 | (list (region-beginning) (region-end)) | ||
27 | (list (point) (line-end-position))))) | ||
28 | |||
29 | |||
30 | ;;; Other functions and whatnot | ||
31 | |||
32 | (defun delete2 (list &rest elems) | ||
33 | "Delete each element of ELEMS, and the next item, from LIST." | ||
34 | (let ((r nil)) | ||
35 | (while (consp list) | ||
36 | (if (member (car list) elems) | ||
37 | (setf list (cdr list)) | ||
38 | (setf r (cons (car list) r))) | ||
39 | (setf list (cdr list))) | ||
40 | (reverse r))) | ||
41 | |||
42 | (unless (fboundp 'ensure-list) | ||
43 | (defun ensure-list (object) | ||
44 | "Return OBJECT as a list. | ||
45 | If OBJECT is already a list, return OBJECT itself. If it's | ||
46 | not a list, return a one-element list containing OBJECT." | ||
47 | (if (listp object) | ||
48 | object | ||
49 | (list object)))) | ||
50 | |||
51 | (defun +require (&rest features) | ||
52 | "Require FEATURES, plus my extras. | ||
53 | Each feature can be an atom (the feature name) or a list of the form | ||
54 | (FEATURE &optional FILENAME NOERROR), which is passed directly to | ||
55 | `require'. My extras are in lisp/ and named +FEATURE, so this | ||
56 | function will `require' them too---but not error if they don't | ||
57 | exist." | ||
58 | (dolist (feat features) | ||
59 | (apply #'require (ensure-list feat)) | ||
60 | (require (intern (format "+%s" feat)) nil :noerror))) | ||
61 | |||
62 | ;;; Improvements to default functions | ||
63 | |||
64 | (defun +save-buffers-kill-terminal (arg) | ||
65 | "Delete the current frame, or quit Emacs. | ||
66 | This function is my customization of `save-buffers-kill-terminal'." | ||
67 | (interactive "P") | ||
68 | (cond (arg (delete-frame nil :force)) | ||
69 | ((= 1 (length (frame-list))) | ||
70 | (and (yes-or-no-p "Kill emacs? ") | ||
71 | (save-buffers-kill-emacs t))) | ||
72 | (:else (delete-frame)))) | ||
73 | |||
74 | (defun really-quit-emacs (arg) | ||
75 | "Really, actually quit Emacs." | ||
76 | (interactive "P") | ||
77 | (cond (arg (save-buffers-kill-emacs t)) | ||
78 | (:else (save-buffers-kill-terminal t)))) | ||
79 | |||
80 | (defun +cycle-spacing (&optional n) | ||
81 | ;; `cycle-spacing' is wildly different in 29.1 over 28. | ||
82 | "Negate N argument on `cycle-spacing'. | ||
83 | That is, with a positive N, deletes newlines as well, leaving -N | ||
84 | spaces. If N is negative, it will not delete newlines and leave | ||
85 | N spaces." | ||
86 | (interactive "*p") | ||
87 | (cycle-spacing (- n))) | ||
88 | |||
89 | (defun delete-window|bury-buffer () | ||
90 | "Delete the current window, or bury the current buffer. | ||
91 | If the current window is the only window, bury the buffer." | ||
92 | (interactive) | ||
93 | (condition-case e | ||
94 | (delete-window) | ||
95 | (t (bury-buffer)))) | ||
96 | |||
97 | (defun other-window|switch-buffer (arg) | ||
98 | "Call `other-window' or `switch-buffer' depending on windows. | ||
99 | When called with prefix ARG, unconditionally switch buffer." | ||
100 | (interactive "P") | ||
101 | (if (or arg (one-window-p)) | ||
102 | (switch-to-buffer (other-buffer) nil t) | ||
103 | (other-window 1))) | ||
104 | |||
105 | (defun open-paragraph (&optional arg) | ||
106 | "Open a paragraph after paragraph at point. | ||
107 | A paragraph is defined as continguous non-empty lines of text | ||
108 | surrounded by empty lines, so opening a paragraph means to make | ||
109 | three blank lines, then place the point on the second one. | ||
110 | |||
111 | Called with prefix ARG, open a paragraph before point." | ||
112 | ;; TODO: Take an integer as ARG, allowing for skipping paragraphs up and down. | ||
113 | (interactive "*P") | ||
114 | ;; Go to next blank line. This /isn't/ `end-of-paragraph-text' because | ||
115 | ;; that's weird with org, and I'm guessing other modes too. | ||
116 | (unless (looking-at "^$") (forward-line (if arg -1 +1))) | ||
117 | (while (and (not (looking-at "^$")) | ||
118 | (= 0 (forward-line (if arg -1 +1))))) | ||
119 | (newline) | ||
120 | (when arg (newline) (forward-line -2)) | ||
121 | (delete-blank-lines) | ||
122 | (newline 2) | ||
123 | (previous-line)) | ||
124 | |||
125 | (defun +initial-buffer () | ||
126 | (if (equal (get-buffer "*Messages*") | ||
127 | (other-buffer)) | ||
128 | (get-buffer "*scratch*") | ||
129 | (other-buffer))) | ||
130 | |||
131 | (defun open-paragraph (&optional arg) | ||
132 | "Open a paragraph after paragraph at point. | ||
133 | A paragraph is defined as continguous non-empty lines of text | ||
134 | surrounded by empty lines, so opening a paragraph means to make | ||
135 | three blank lines, then place the point on the second one. | ||
136 | |||
137 | Called with prefix ARG, open a paragraph before point." | ||
138 | ;; TODO: Take an integer as ARG, allowing for skipping paragraphs up and down. | ||
139 | (interactive "*P") | ||
140 | ;; Go to next blank line. This /isn't/ `end-of-paragraph-text' because | ||
141 | ;; that's weird with org, and I'm guessing other modes too. | ||
142 | (unless (looking-at "^$") (forward-line (if arg -1 +1))) | ||
143 | (while (and (not (looking-at "^$")) | ||
144 | (= 0 (forward-line (if arg -1 +1))))) | ||
145 | (newline) | ||
146 | (when arg (newline) (forward-line -2)) | ||
147 | (delete-blank-lines) | ||
148 | (newline 2) | ||
149 | (previous-line)) | ||
150 | |||
151 | (defun create-missing-directories () | ||
152 | "Automatically create missing directories when finding a file." | ||
153 | ;; https://emacsredux.com/blog/2022/06/12/auto-create-missing-directories/ | ||
154 | (let ((target-dir (file-name-directory buffer-file-name))) | ||
155 | (unless (file-exists-p target-dir) | ||
156 | (make-directory target-dir t)))) | ||
157 | |||
158 | (defun +vc-off@remote () | ||
159 | (when (file-remote-p (buffer-file-name)) | ||
160 | (setq-local vc-handled-backends nil))) | ||
161 | |||
162 | (defun +auto-save-some-buffers (&rest _) | ||
163 | "Quietly run `save-some-buffers'." | ||
164 | (let ((inhibit-message t)) | ||
165 | (with-temp-message "" | ||
166 | (save-some-buffers t)))) | ||
167 | |||
168 | (defun comment-lines (str &optional comment-char) | ||
169 | "Comment each line of STR. | ||
170 | Returns the new, commented, string. | ||
171 | |||
172 | If COMMENT-CHAR is missing or nil, use `comment-start'." | ||
173 | (mapconcat (lambda (ln) | ||
174 | (concat (or comment-char comment-start) | ||
175 | ln)) | ||
176 | (string-lines str) | ||
177 | "\n")) | ||
178 | |||
179 | (defun clamp (value min max) | ||
180 | "Clamp VALUE between MIN and MAX." | ||
181 | (min max (max min value))) | ||
182 | |||
183 | (define-minor-mode truncate-lines-local-mode | ||
184 | "Truncate lines locally in a buffer." | ||
185 | :lighter " ..." | ||
186 | :group 'display | ||
187 | (setq-local truncate-lines truncate-lines-local-mode)) | ||
188 | |||
189 | (defun mapc-buffers (func &optional predicate) | ||
190 | "Map FUNC over buffers matching PREDICATE. | ||
191 | Both FUNC and PREDICATE will be executed with no arguments and in | ||
192 | the context of each buffer. | ||
193 | |||
194 | If PREDICATE is nil or not given, map FUNC over all buffers." | ||
195 | (cl-loop for buf being the buffers | ||
196 | do (with-current-buffer buf | ||
197 | (when (and predicate | ||
198 | (funcall predicate)) | ||
199 | (funcall func))))) | ||
200 | |||
201 | (defun mapc-buffers-modes (func &rest modes) | ||
202 | "Map FUNC over buffers derived from MODES. | ||
203 | FUNC will be executed with no arguments and in the context of | ||
204 | each buffer." | ||
205 | (mapc-buffers func | ||
206 | (lambda () | ||
207 | (apply #'derived-mode-p modes)))) | ||
208 | |||
209 | (defun ++concat (func strings) | ||
210 | "Concat STRINGS processed by FUNC. | ||
211 | Each of STRINGS can be a bare string or a list. Strings are | ||
212 | passed through as-is, but lists are passed to FUNC first as | ||
213 | arguments. Finally, all the resulting strings are `mapconcat'-ed | ||
214 | together. | ||
215 | |||
216 | As a special case, if `:separator' is the first of STRINGS, the | ||
217 | string following will be used as a separator. Otherwise, a | ||
218 | newline will be used." | ||
219 | (let (separator) | ||
220 | (when (eq (car strings) :separator) | ||
221 | (setq separator (cadr strings) | ||
222 | strings (cddr strings))) | ||
223 | (mapconcat (lambda (s) | ||
224 | (cond | ||
225 | ((listp s) (apply func s)) | ||
226 | ((stringp s) s) | ||
227 | (t (user-error "Bad argument: %S" s)))) | ||
228 | strings | ||
229 | (or separator "\n")))) | ||
230 | |||
231 | (defun nconcat (&rest strings) | ||
232 | "Concat STRINGS separated by SEPARATOR. | ||
233 | If `:separator' is the first of STRINGS, the next string will be used to | ||
234 | separate the rest of STRINGS." | ||
235 | (++concat #'concat strings)) | ||
236 | |||
237 | (defun format-concat (&rest strings) | ||
238 | "Concatenate formatted STRINGS. | ||
239 | Each of STRINGS can be a bare string or a list. Bare strings are passed as-is | ||
240 | to `mapconcat' for concatenation and separation. Lists, however, are passed to | ||
241 | `format' first. | ||
242 | |||
243 | If `:separator' is the first of STRINGS, the next string will be | ||
244 | used as a separator." | ||
245 | (++concat #'format strings)) | ||
246 | |||
247 | (defun choose-executable (&rest programs) | ||
248 | "Return the first of PROGRAMS that exists in the system's $PATH." | ||
249 | (seq-some #'executable-find programs)) | ||
250 | |||
251 | ;;; Update packages more better-er | ||
252 | |||
253 | (defun +package-update-all () | ||
254 | "Update all packages and vc packages." | ||
255 | (interactive) | ||
256 | (package-update-all) | ||
257 | ;; WTF! | ||
258 | (let ((package-archives-nil)) | ||
259 | (package-vc-update-all))) | ||
260 | |||
261 | (provide 'acdw-funs) | ||
262 | ;;; acdw-funs.el ends here | ||