summary refs log tree commit diff stats
path: root/lisp/user-save.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/user-save.el')
-rw-r--r--lisp/user-save.el137
1 files changed, 0 insertions, 137 deletions
diff --git a/lisp/user-save.el b/lisp/user-save.el deleted file mode 100644 index 674abac..0000000 --- a/lisp/user-save.el +++ /dev/null
@@ -1,137 +0,0 @@
1;;; user-save.el --- Do things when explicitly saving files -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2021--2022 Case Duckworth <acdw@acdw.net>
4;; URL: ...
5;; Version: 0.1.0
6;; Package-Requires: ((emacs "24.3"))
7;; Keywords: files
8
9;;; Commentary:
10
11;; Because `super-save-mode' automatically saves every time we move away from a
12;; buffer, it tends to run a lot of `before-save-hook's that don't need to be
13;; run that often. For that reason, I'm writing a mode where C-x C-s saves
14;; /and/ runs all the "real" before-save-hooks, so that super-save won't
15;; automatically do things like format the buffer all the time.
16
17;;; Code:
18
19(require 'cl-lib)
20
21(defgroup user-save nil
22 "Group for `user-save-mode' customizations."
23 :group 'files
24 :prefix "user-save-")
25
26(defcustom user-save-hook-into-kill-emacs nil
27 "Add a hook to perform `user-save' to `kill-emacs-hook'.
28This option is only useful is `user-save-mode' is active when
29Emacs is killed."
30 :type 'boolean)
31
32(defcustom user-save-inhibit-modes '(special-mode)
33 "List of modes to inhibit `user-save-mode' from activation in."
34 :type '(repeat symbol))
35
36(defcustom user-save-inhibit-predicates '(user-save-non-file-buffer-p)
37 "List of predicates to inhibit `user-save-mode' from activation.
38Each predicate will be called with no arguments, and if it
39returns t, will inhibit `user-save-mode' from activating."
40 :type '(repeat function))
41
42(defcustom user-save-before-save-hook nil
43 "Hook to run before the user, not Emacs, saves the buffer."
44 :type 'hook)
45
46(defcustom user-save-after-save-hook nil
47 "Hook to run after the user, not Emacs, saves the buffer."
48 :type 'hook)
49
50(defvar user-save-mode-map (let ((map (make-sparse-keymap)))
51 (define-key map (kbd "C-x C-s") #'user-save-buffer)
52 (define-key map (kbd "C-x s") #'user-save-some-buffers)
53 map)
54 "Keymap for `user-save-mode'.
55This map shadows the default map for `save-buffer'.")
56
57(defun user-save-run-hooks (which &rest _)
58 "Run the hooks in one of the user-save-hooks.
59If WHICH is `'before', run `user-save-before-save-hook';
60if it's `after', run `user-save-after-save-hook'.
61This does /not/ also save the buffer."
62 (with-demoted-errors "User-save-hook error: %S"
63 (run-hooks (intern (format "user-save-%s-save-hook" which)))))
64
65(defun user-save-non-file-buffer-p (&optional buffer-or-name)
66 "Return whether BUFFER-OR-NAME is a non-file buffer.
67BUFFER-OR-NAME, if omitted, defaults to the current buffer."
68 (with-current-buffer (or buffer-or-name (current-buffer))
69 (not (buffer-file-name))))
70
71(defun user-save-buffer (&optional arg)
72 "Save current buffer in visited file if modified.
73This function is precisely the same as `save-buffer', but with
74one modification: it also runs functions in `user-save-hook'.
75This means that if you have some functionality in Emacs to
76automatically save buffers periodically, but have hooks you want
77to automatically run when the buffer saves that are
78computationally expensive or just aren't something you want to
79run all the time, put them in `user-save-hook'.
80
81ARG is passed directly to `save-buffer'."
82 (interactive '(called-interactively))
83 (message "User-Saving the buffer...")
84 (user-save-run-hooks 'before)
85 (save-buffer arg)
86 (user-save-run-hooks 'after)
87 (message "User-Saving the buffer...Done."))
88
89(defun user-save-some-buffers (&optional pred)
90 "Save some buffers as though the user saved them.
91This function does not ask the user about each buffer, but PRED
92is used in almost the same way as `save-some-buffers': if it's
93nil or t, it will save all file-visiting modified buffers; if
94it's a zero-argument function, that will be called to determine
95whether the buffer needs to be saved."
96 ;; This could maybe be much better.
97 (interactive "P")
98 (unless pred (setq pred save-some-buffers-default-predicate))
99 (dolist (buf (buffer-list))
100 (with-current-buffer buf
101 (when (and (buffer-modified-p)
102 (buffer-file-name)
103 (or (null pred)
104 (if (functionp pred) (funcall pred) pred)))
105 (user-save-buffer)))))
106
107;;;###autoload
108(define-minor-mode user-save-mode
109 "Mode to enable an an extra user-save hook."
110 :lighter " US"
111 :keymap user-save-mode-map)
112
113;;;###autoload
114(defun user-save-mode-disable ()
115 "Turn off `user-save-mode' in the current buffer."
116 (user-save-mode -1))
117
118;;;###autoload
119(defun user-save-mode-in-some-buffers ()
120 "Enable `user-save-mode', but only in some buffers.
121The mode will not be enabled in buffers derived from modes in
122`user-save-inhibit-modes', those for which
123`user-save-inhibit-predicates' return t, or in the minibuffer."
124 (unless (or (minibufferp)
125 (cl-some #'derived-mode-p user-save-inhibit-modes)
126 (run-hook-with-args-until-failure 'user-save-inhibit-predicates))
127 (user-save-mode +1)))
128
129;;;###autoload
130(define-globalized-minor-mode user-save-global-mode user-save-mode user-save-mode-in-some-buffers
131 (if user-save-global-mode
132 (when user-save-hook-into-kill-emacs
133 (add-hook 'kill-emacs-hook #'user-save-some-buffers))
134 (remove-hook 'kill-emacs-hook #'user-save-some-buffers)))
135
136(provide 'user-save)
137;;; user-save.el ends here