summary refs log tree commit diff stats
path: root/lisp/acdw-compat.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/acdw-compat.el')
-rw-r--r--lisp/acdw-compat.el555
1 files changed, 0 insertions, 555 deletions
diff --git a/lisp/acdw-compat.el b/lisp/acdw-compat.el deleted file mode 100644 index 3221191..0000000 --- a/lisp/acdw-compat.el +++ /dev/null
@@ -1,555 +0,0 @@
1;;; acdw-compat.el -*- lexical-binding: t; coding: utf-8-unix -*-
2
3;; Author: Case Duckworth <(rot13-string "npqj@npqj.arg")>
4;; Created: 2021-08-11
5;; Keywords: configuration
6;; URL: https://tildegit.org/acdw/emacs
7
8;; This file is NOT part of GNU Emacs.
9
10;;; License:
11;; Everyone is permitted to do whatever with this software, without
12;; limitation. This software comes without any warranty whatsoever,
13;; but with two pieces of advice:
14;; - Don't hurt yourself.
15;; - Make good choices.
16
17;;; Commentary:
18
19;; This file contains functions, variables, and other code that might not be in
20;; every version of Emacs I use.
21
22;;; Code:
23
24;; Convenience macro
25(defmacro safely (&rest defines)
26 "Wrap DEFINES in tests to make sure they're not already defined.
27Is it necessary? Who knows!!"
28 (let (output)
29 (dolist (form defines)
30 ;; this is one part where elisp being a lisp-2 bites us...
31 (push (cond ((memq (car form)
32 '(;; makes functions
33 define-global-minor-mode
34 define-globalized-minor-mode
35 define-minor-mode
36 defmacro
37 defsubst
38 defun))
39 `(unless (fboundp ',(cadr form))
40 ,form))
41 ((memq (car form)
42 '(;; makes variables
43 defcustom
44 defvar
45 defvar
46 defvar-local
47 defvar-mode-local
48 defvaralias))
49 `(unless (boundp ',(cadr form))
50 ,form))
51 (t form))
52 output))
53 `(progn ,@(nreverse output))))
54
55
56;;; Functions for changing capitalization that Do What I Mean
57;; Defined in EMACS/lisp/simple.el
58(safely
59 (defun upcase-dwim (arg)
60 "Upcase words in the region, if active; if not, upcase word at point.
61If the region is active, this function calls `upcase-region'.
62Otherwise, it calls `upcase-word', with prefix argument passed to it
63to upcase ARG words."
64 (interactive "*p")
65 (if (use-region-p)
66 (upcase-region (region-beginning) (region-end) (region-noncontiguous-p))
67 (upcase-word arg)))
68
69 (defun downcase-dwim (arg)
70 "Downcase words in the region, if active; if not, downcase word at point.
71If the region is active, this function calls `downcase-region'.
72Otherwise, it calls `downcase-word', with prefix argument passed to it
73to downcase ARG words."
74 (interactive "*p")
75 (if (use-region-p)
76 (downcase-region (region-beginning) (region-end) (region-noncontiguous-p))
77 (downcase-word arg)))
78
79 (defun capitalize-dwim (arg)
80 "Capitalize words in the region, if active; if not, capitalize word at point.
81If the region is active, this function calls `capitalize-region'.
82Otherwise, it calls `capitalize-word', with prefix argument passed to it
83to capitalize ARG words."
84 (interactive "*p")
85 (if (use-region-p)
86 (capitalize-region (region-beginning) (region-end) (region-noncontiguous-p))
87 (capitalize-word arg))))
88
89
90;;; Repeat.el
91;; Defined in EMACS/lisp/repeat.el
92
93(safely
94 (defcustom repeat-too-dangerous '(kill-this-buffer)
95 "Commands too dangerous to repeat with \\[repeat]."
96 :group 'convenience
97 :type '(repeat function))
98
99 (defvar repeat-message-function nil
100 "If non-nil, function used by `repeat' command to say what it's doing.
101Message is something like \"Repeating command glorp\".
102A value of `ignore' will disable such messages. To customize
103display, assign a function that takes one string as an arg and
104displays it however you want.
105If this variable is nil, the normal `message' function will be
106used to display the messages.")
107
108 (defcustom repeat-on-final-keystroke t
109 "Allow `repeat' to re-execute for repeating lastchar of a key sequence.
110If this variable is t, `repeat' determines what key sequence
111it was invoked by, extracts the final character of that sequence, and
112re-executes as many times as that final character is hit; so for example
113if `repeat' is bound to C-x z, typing C-x z z z repeats the previous command
1143 times. If this variable is a sequence of characters, then re-execution
115only occurs if the final character by which `repeat' was invoked is a
116member of that sequence. If this variable is nil, no re-execution occurs."
117 :group 'convenience
118 :type '(choice (const :tag "Repeat for all keys" t)
119 (const :tag "Don't repeat" nil)
120 (sexp :tag "Repeat for specific keys")))
121
122 (defvar repeat-num-input-keys-at-repeat -1
123 "# key sequences read in Emacs session when `repeat' last invoked.")
124
125 (defsubst repeat-is-really-this-command ()
126 "Return t if this command is happening because user invoked `repeat'.
127Usually, when a command is executing, the Emacs builtin variable
128`this-command' identifies the command the user invoked. Some commands modify
129that variable on the theory they're doing more good than harm; `repeat' does
130that, and usually does do more good than harm. However, like all do-gooders,
131sometimes `repeat' gets surprising results from its altruism. The value of
132this function is always whether the value of `this-command' would've been
133'repeat if `repeat' hadn't modified it."
134 (= repeat-num-input-keys-at-repeat num-input-keys))
135
136 (defvar repeat-previous-repeated-command nil
137 "The previous repeated command.")
138
139 (defun repeat (repeat-arg)
140 "Repeat most recently executed command.
141If REPEAT-ARG is non-nil (interactively, with a prefix argument),
142supply a prefix argument to that command. Otherwise, give the
143command the same prefix argument it was given before, if any.
144
145If this command is invoked by a multi-character key sequence, it
146can then be repeated by repeating the final character of that
147sequence. This behavior can be modified by the global variable
148`repeat-on-final-keystroke'.
149
150`repeat' ignores commands bound to input events. Hence the term
151\"most recently executed command\" shall be read as \"most
152recently executed command not bound to an input event\"."
153 ;; The most recently executed command could be anything, so surprises could
154 ;; result if it were re-executed in a context where new dynamically
155 ;; localized variables were shadowing global variables in a `let' clause in
156 ;; here. (Remember that GNU Emacs 19 is dynamically localized.)
157 ;; To avoid that, I tried the `lexical-let' of the Common Lisp extensions,
158 ;; but that entails a very noticeable performance hit, so instead I use the
159 ;; "repeat-" prefix, reserved by this package, for *local* variables that
160 ;; might be visible to re-executed commands, including this function's arg.
161 (interactive "P")
162 (when (eq last-repeatable-command 'repeat)
163 (setq last-repeatable-command repeat-previous-repeated-command))
164 (cond
165 ((null last-repeatable-command)
166 (error "There is nothing to repeat"))
167 ((eq last-repeatable-command 'mode-exit)
168 (error "last-repeatable-command is mode-exit & can't be repeated"))
169 ((memq last-repeatable-command repeat-too-dangerous)
170 (error "Command %S too dangerous to repeat automatically"
171 last-repeatable-command)))
172 (setq this-command last-repeatable-command
173 repeat-previous-repeated-command last-repeatable-command
174 repeat-num-input-keys-at-repeat num-input-keys)
175 (when (null repeat-arg)
176 (setq repeat-arg last-prefix-arg))
177 ;; Now determine whether to loop on repeated taps of the final character
178 ;; of the key sequence that invoked repeat. The Emacs global
179 ;; last-command-event contains the final character now, but may not still
180 ;; contain it after the previous command is repeated, so the character
181 ;; needs to be saved.
182 (let ((repeat-repeat-char
183 (if (eq repeat-on-final-keystroke t)
184 last-command-event
185 ;; Allow only specified final keystrokes.
186 (car (memq last-command-event
187 (listify-key-sequence
188 repeat-on-final-keystroke))))))
189 (if (eq last-repeatable-command (caar command-history))
190 (let ((repeat-command (car command-history)))
191 (repeat-message "Repeating %S" repeat-command)
192 (eval repeat-command))
193 (if (null repeat-arg)
194 (repeat-message "Repeating command %S" last-repeatable-command)
195 (setq current-prefix-arg repeat-arg)
196 (repeat-message
197 "Repeating command %S %S" repeat-arg last-repeatable-command))
198 (when (eq last-repeatable-command 'self-insert-command)
199 ;; We used to use a much more complex code to try and figure out
200 ;; what key was used to run that self-insert-command:
201 ;; (if (<= (- num-input-keys
202 ;; repeat-num-input-keys-at-self-insert)
203 ;; 1)
204 ;; repeat-last-self-insert
205 ;; (let ((range (nth 1 buffer-undo-list)))
206 ;; (condition-case nil
207 ;; (setq repeat-last-self-insert
208 ;; (buffer-substring (car range)
209 ;; (cdr range)))
210 ;; (error (error "%s %s %s" ;Danger, Will Robinson!
211 ;; "repeat can't intuit what you"
212 ;; "inserted before auto-fill"
213 ;; "clobbered it, sorry")))))
214 (setq last-command-event (char-before)))
215 (let ((indirect (indirect-function last-repeatable-command)))
216 (if (or (stringp indirect)
217 (vectorp indirect))
218 ;; Bind last-repeatable-command so that executing the macro does
219 ;; not alter it.
220 (let ((last-repeatable-command last-repeatable-command))
221 (execute-kbd-macro last-repeatable-command))
222 (call-interactively last-repeatable-command))))
223 (when repeat-repeat-char
224 (set-transient-map
225 (let ((map (make-sparse-keymap)))
226 (define-key map (vector repeat-repeat-char)
227 (if (null repeat-message-function) 'repeat
228 ;; If repeat-message-function is let-bound, preserve it for the
229 ;; next "iterations of the loop".
230 (let ((fun repeat-message-function))
231 (lambda ()
232 (interactive)
233 (let ((repeat-message-function fun))
234 (setq this-command 'repeat)
235 ;; Beware: messing with `real-this-command' is *bad*, but we
236 ;; need it so `last-repeatable-command' can be recognized
237 ;; later (bug#12232).
238 (setq real-this-command 'repeat)
239 (call-interactively 'repeat))))))
240 map)))))
241
242 (defun repeat-message (format &rest args)
243 "Like `message' but displays with `repeat-message-function' if non-nil."
244 (let ((message (apply 'format format args)))
245 (if repeat-message-function
246 (funcall repeat-message-function message)
247 (message "%s" message))))
248
249 (defcustom repeat-exit-key nil
250 "Key that stops the modal repeating of keys in sequence.
251For example, you can set it to <return> like `isearch-exit'."
252 :type '(choice (const :tag "No special key to exit repeating sequence" nil)
253 (key-sequence :tag "Key that exits repeating sequence"))
254 :group 'convenience
255 :version "28.1")
256
257 (defcustom repeat-exit-timeout nil
258 "Break the repetition chain of keys after specified timeout.
259When a number, exit the repeat mode after idle time of the specified
260number of seconds."
261 :type '(choice (const :tag "No timeout to exit repeating sequence" nil)
262 (number :tag "Timeout in seconds to exit repeating"))
263 :group 'convenience
264 :version "28.1")
265
266 (defvar repeat-exit-timer nil
267 "Timer activated after the last key typed in the repeating key sequence.")
268
269 (defcustom repeat-keep-prefix t
270 "Keep the prefix arg of the previous command."
271 :type 'boolean
272 :group 'convenience
273 :version "28.1")
274
275 (defcustom repeat-echo-function #'repeat-echo-message
276 "Function to display a hint about available keys.
277Function is called after every repeatable command with one argument:
278a repeating map, or nil after deactivating the repeat mode."
279 :type '(choice (const :tag "Show hints in the echo area"
280 repeat-echo-message)
281 (const :tag "Show indicator in the mode line"
282 repeat-echo-mode-line)
283 (const :tag "No visual feedback" ignore)
284 (function :tag "Function"))
285 :group 'convenience
286 :version "28.1")
287
288 (defvar repeat-in-progress nil
289 "Non-nil when the repeating map is active.")
290
291 (defvar repeat-map nil
292 "The value of the repeating map for the next command.
293A command called from the map can set it again to the same map when
294the map can't be set on the command symbol property `repeat-map'.")
295
296 (define-minor-mode repeat-mode
297 "Toggle Repeat mode.
298When Repeat mode is enabled, and the command symbol has the property named
299`repeat-map', this map is activated temporarily for the next command."
300 :global t :group 'convenience
301 (if (not repeat-mode)
302 (remove-hook 'post-command-hook 'repeat-post-hook)
303 (add-hook 'post-command-hook 'repeat-post-hook)
304 (let* ((keymaps nil)
305 (commands (all-completions
306 "" obarray (lambda (s)
307 (and (commandp s)
308 (get s 'repeat-map)
309 (push (get s 'repeat-map) keymaps))))))
310 (message "Repeat mode is enabled for %d commands and %d keymaps; see `describe-repeat-maps'."
311 (length commands)
312 (length (delete-dups keymaps))))))
313
314 (defun repeat-post-hook ()
315 "Function run after commands to set transient keymap for repeatable keys."
316 (let ((was-in-progress repeat-in-progress))
317 (setq repeat-in-progress nil)
318 (when repeat-mode
319 (let ((rep-map (or repeat-map
320 (and (symbolp real-this-command)
321 (get real-this-command 'repeat-map)))))
322 (when rep-map
323 (when (boundp rep-map)
324 (setq rep-map (symbol-value rep-map)))
325 (let ((map (copy-keymap rep-map)))
326
327 ;; Exit when the last char is not among repeatable keys,
328 ;; so e.g. `C-x u u' repeats undo, whereas `C-/ u' doesn't.
329 (when (and (zerop (minibuffer-depth)) ; avoid remapping in prompts
330 (or (lookup-key map (this-command-keys-vector))
331 prefix-arg))
332
333 ;; Messaging
334 (unless prefix-arg
335 (funcall repeat-echo-function map))
336
337 ;; Adding an exit key
338 (when repeat-exit-key
339 (define-key map repeat-exit-key 'ignore))
340
341 (when (and repeat-keep-prefix (not prefix-arg))
342 (setq prefix-arg current-prefix-arg))
343
344 (setq repeat-in-progress t)
345 (let ((exitfun (set-transient-map map)))
346
347 (when repeat-exit-timer
348 (cancel-timer repeat-exit-timer)
349 (setq repeat-exit-timer nil))
350
351 (when repeat-exit-timeout
352 (setq repeat-exit-timer
353 (run-with-idle-timer
354 repeat-exit-timeout nil
355 (lambda ()
356 (setq repeat-in-progress nil)
357 (funcall exitfun)
358 (funcall repeat-echo-function nil)))))))))))
359
360 (setq repeat-map nil)
361 (when (and was-in-progress (not repeat-in-progress))
362 (when repeat-exit-timer
363 (cancel-timer repeat-exit-timer)
364 (setq repeat-exit-timer nil))
365 (funcall repeat-echo-function nil))))
366
367 (defun repeat-echo-message-string (keymap)
368 "Return a string with a list of repeating keys."
369 (let (keys)
370 (map-keymap (lambda (key _) (push key keys)) keymap)
371 (format-message "Repeat with %s%s"
372 (mapconcat (lambda (key)
373 (key-description (vector key)))
374 keys ", ")
375 (if repeat-exit-key
376 (format ", or exit with %s"
377 (key-description repeat-exit-key))
378 ""))))
379
380 (defun repeat-echo-message (keymap)
381 "Display available repeating keys in the echo area."
382 (if keymap
383 (let ((mess (repeat-echo-message-string keymap)))
384 (if (current-message)
385 (message "%s [%s]" (current-message) mess)
386 (message mess)))
387 (and (current-message)
388 (string-search "Repeat with " (current-message))
389 (message nil))))
390
391 (defvar repeat-echo-mode-line-string
392 (propertize "[Repeating...] " 'face 'mode-line-emphasis)
393 "String displayed in the mode line in repeating mode.")
394
395 (defun repeat-echo-mode-line (keymap)
396 "Display the repeat indicator in the mode line."
397 (if keymap
398 (unless (assq 'repeat-in-progress mode-line-modes)
399 (add-to-list 'mode-line-modes (list 'repeat-in-progress
400 repeat-echo-mode-line-string)))
401 (force-mode-line-update t)))
402
403 (defun describe-repeat-maps ()
404 "Describe mappings of commands repeatable by symbol property `repeat-map'."
405 (interactive)
406 (help-setup-xref (list #'describe-repeat-maps)
407 (called-interactively-p 'interactive))
408 (let ((keymaps nil))
409 (all-completions
410 "" obarray (lambda (s)
411 (and (commandp s)
412 (get s 'repeat-map)
413 (push s (alist-get (get s 'repeat-map) keymaps)))))
414 (with-help-window (help-buffer)
415 (with-current-buffer standard-output
416 (princ "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n")
417
418 (dolist (keymap (sort keymaps (lambda (a b) (string-lessp (car a) (car b)))))
419 (princ (format-message "`%s' keymap is repeatable by these commands:\n"
420 (car keymap)))
421 (dolist (command (sort (cdr keymap) 'string-lessp))
422 (princ (format-message " `%s'\n" command)))
423 (princ "\n"))))))
424
425;;; Bindings!
426 (defvar undo-repeat-map
427 (let ((map (make-sparse-keymap)))
428 (define-key map "u" 'undo)
429 map)
430 "Keymap to repeat undo key sequences `C-x u u'. Used in `repeat-mode'.")
431 (put 'undo 'repeat-map 'undo-repeat-map)
432
433 (defvar next-error-repeat-map
434 (let ((map (make-sparse-keymap)))
435 (define-key map "n" 'next-error)
436 (define-key map "\M-n" 'next-error)
437 (define-key map "p" 'previous-error)
438 (define-key map "\M-p" 'previous-error)
439 map)
440 "Keymap to repeat next-error key sequences. Used in `repeat-mode'.")
441 (put 'next-error 'repeat-map 'next-error-repeat-map)
442 (put 'previous-error 'repeat-map 'next-error-repeat-map)
443
444 (defvar page-navigation-repeat-map
445 (let ((map (make-sparse-keymap)))
446 (define-key map "]" #'forward-page)
447 (define-key map "[" #'backward-page)
448 map)
449 "Keymap to repeat page navigation key sequences. Used in `repeat-mode'.")
450 (put 'forward-page 'repeat-map 'page-navigation-repeat-map)
451 (put 'backward-page 'repeat-map 'page-navigation-repeat-map)
452
453 (defvar tab-bar-switch-repeat-map
454 (let ((map (make-sparse-keymap)))
455 (define-key map "o" 'tab-next)
456 (define-key map "O" 'tab-previous)
457 map)
458 "Keymap to repeat tab switch key sequences `C-x t o o O'.
459Used in `repeat-mode'.")
460 (put 'tab-next 'repeat-map 'tab-bar-switch-repeat-map)
461 (put 'tab-previous 'repeat-map 'tab-bar-switch-repeat-map)
462
463 (defvar tab-bar-move-repeat-map
464 (let ((map (make-sparse-keymap)))
465 (define-key map "m" 'tab-move)
466 (define-key map "M" (lambda ()
467 (interactive)
468 (setq repeat-map 'tab-bar-move-repeat-map)
469 (tab-move -1)))
470 map)
471 "Keymap to repeat tab move key sequences `C-x t m m M'.
472Used in `repeat-mode'.")
473 (put 'tab-move 'repeat-map 'tab-bar-move-repeat-map)
474
475 (defvar other-window-repeat-map
476 (let ((map (make-sparse-keymap)))
477 (define-key map "o" 'other-window)
478 (define-key map "O" (lambda ()
479 (interactive)
480 (setq repeat-map 'other-window-repeat-map)
481 (other-window -1)))
482 map)
483 "Keymap to repeat other-window key sequences. Used in `repeat-mode'.")
484 (put 'other-window 'repeat-map 'other-window-repeat-map)
485
486 (defvar resize-window-repeat-map
487 (let ((map (make-sparse-keymap)))
488 ;; Standard keys:
489 (define-key map "^" 'enlarge-window)
490 (define-key map "}" 'enlarge-window-horizontally)
491 (define-key map "{" 'shrink-window-horizontally)
492 ;; Additional keys:
493 (define-key map "v" 'shrink-window)
494 map)
495 "Keymap to repeat window resizing commands. Used in `repeat-mode'.")
496 (put 'enlarge-window 'repeat-map 'resize-window-repeat-map)
497 (put 'enlarge-window-horizontally 'repeat-map 'resize-window-repeat-map)
498 (put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map)
499 (put 'shrink-window 'repeat-map 'resize-window-repeat-map)
500
501 (defvar outline-navigation-repeat-map
502 (let ((map (make-sparse-keymap)))
503 (define-key map (kbd "C-b") #'outline-backward-same-level)
504 (define-key map (kbd "b") #'outline-backward-same-level)
505 (define-key map (kbd "C-f") #'outline-forward-same-level)
506 (define-key map (kbd "f") #'outline-forward-same-level)
507 (define-key map (kbd "C-n") #'outline-next-visible-heading)
508 (define-key map (kbd "n") #'outline-next-visible-heading)
509 (define-key map (kbd "C-p") #'outline-previous-visible-heading)
510 (define-key map (kbd "p") #'outline-previous-visible-heading)
511 (define-key map (kbd "C-u") #'outline-up-heading)
512 (define-key map (kbd "u") #'outline-up-heading)
513 map))
514
515 (defvar outline-editing-repeat-map
516 (let ((map (make-sparse-keymap)))
517 (define-key map (kbd "C-v") #'outline-move-subtree-down)
518 (define-key map (kbd "v") #'outline-move-subtree-down)
519 (define-key map (kbd "C-^") #'outline-move-subtree-up)
520 (define-key map (kbd "^") #'outline-move-subtree-up)
521 (define-key map (kbd "C->") #'outline-demote)
522 (define-key map (kbd ">") #'outline-demote)
523 (define-key map (kbd "C-<") #'outline-promote)
524 (define-key map (kbd "<") #'outline-promote)
525 map))
526
527 (with-eval-after-load 'outline
528 (dolist (command '(outline-backward-same-level
529 outline-forward-same-level
530 outline-next-visible-heading
531 outline-previous-visible-heading
532 outline-up-heading))
533 (put command 'repeat-map 'outline-navigation-repeat-map))
534
535 (dolist (command '(outline-move-subtree-down
536 outline-move-subtree-up
537 outline-demote
538 outline-promote))
539 (put command 'repeat-map 'outline-editing-repeat-map))))
540
541
542;;; goto-address-mode
543(safely
544 (defvar global-address-mode nil)
545
546 (define-globalized-minor-mode global-goto-address-mode
547 goto-address-mode goto-addr-mode--turn-on
548 :version "28.1")
549
550 (defun goto-addr-mode--turn-on ()
551 (when (not goto-address-mode)
552 (goto-address-mode 1))))
553
554(provide 'acdw-compat)
555;;; acdw-compat.el ends here