Commit | Line | Data |
---|---|---|
216ee1a4 | 1 | ;;; savehist.el --- Save minibuffer history. |
cb23c7c1 | 2 | |
2a2b5b29 | 3 | ;; Copyright (C) 1997,2005 Free Software Foundation |
cb23c7c1 RS |
4 | |
5 | ;; Author: Hrvoje Niksic <hniksic@xemacs.org> | |
6 | ;; Keywords: minibuffer | |
b91f17dc | 7 | ;; Version: 19 |
cb23c7c1 RS |
8 | |
9 | ;; This file is part of GNU Emacs. | |
10 | ||
11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
12 | ;; it under the terms of the GNU General Public License as published by | |
13 | ;; the Free Software Foundation; either version 2, or (at your option) | |
14 | ;; any later version. | |
15 | ||
16 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
23 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
24 | ;; Boston, MA 02110-1301, USA. | |
25 | ||
26 | ;;; Commentary: | |
27 | ||
216ee1a4 SM |
28 | ;; Many editors (e.g. Vim) have the feature of saving minibuffer |
29 | ;; history to an external file after exit. This package provides the | |
2a2b5b29 SM |
30 | ;; same feature in Emacs. When set up, it saves recorded minibuffer |
31 | ;; histories to a file (`~/.emacs-history' by default). Additional | |
32 | ;; variables may be specified by customizing | |
33 | ;; `savehist-additional-variables'. | |
cb23c7c1 | 34 | |
b91f17dc SM |
35 | ;; To use savehist, turn on savehist-mode by putting the following in |
36 | ;; `~/.emacs': | |
cb23c7c1 | 37 | ;; |
b91f17dc SM |
38 | ;; (savehist-mode 1) |
39 | ;; | |
40 | ;; or with customize: `M-x customize-option RET savehist-mode RET'. | |
41 | ;; | |
42 | ;; You can also explicitly save history with `M-x savehist-save' and | |
b13e8fb3 | 43 | ;; load it by loading the `savehist-file' with `M-x load-file'. |
cb23c7c1 | 44 | |
2a2b5b29 SM |
45 | ;; If you are using a version of Emacs that does not ship with this |
46 | ;; package, be sure to have `savehist.el' in a directory that is in | |
47 | ;; your load-path, and to byte-compile it. | |
216ee1a4 | 48 | |
cb23c7c1 RS |
49 | ;;; Code: |
50 | ||
216ee1a4 | 51 | (require 'custom) |
2a2b5b29 SM |
52 | (eval-when-compile |
53 | (require 'cl)) | |
216ee1a4 | 54 | |
cb23c7c1 RS |
55 | ;; User variables |
56 | ||
57 | (defgroup savehist nil | |
58 | "Save minibuffer history." | |
59 | :group 'minibuffer) | |
60 | ||
b91f17dc SM |
61 | ;;;###autoload |
62 | (defcustom savehist-mode nil | |
63 | "Mode for automatic saving of minibuffer history. | |
64 | Set this by calling the `savehist-mode' function or using the customize | |
65 | interface." | |
66 | :type 'boolean | |
b13e8fb3 SM |
67 | :set (if (fboundp 'custom-set-minor-mode) |
68 | 'custom-set-minor-mode | |
69 | (lambda (symbol value) (funcall symbol (or value 0)))) | |
b91f17dc SM |
70 | :initialize 'custom-initialize-default |
71 | :require 'savehist | |
72 | :group 'savehist) | |
73 | ||
2a2b5b29 | 74 | (defcustom savehist-save-minibuffer-history t |
b91f17dc SM |
75 | "*If non-nil, save all recorded minibuffer histories. |
76 | If you want to save only specific histories, use `savehist-save-hook' to | |
77 | modify the value of `savehist-minibuffer-history-variables'." | |
2a2b5b29 SM |
78 | :type 'boolean |
79 | :group 'savehist) | |
80 | ||
81 | (defcustom savehist-additional-variables () | |
b91f17dc | 82 | "*List of additional variables to save. |
2a2b5b29 SM |
83 | Each element is a symbol whose value will be persisted across Emacs |
84 | sessions that use savehist. The contents of variables should be | |
b91f17dc SM |
85 | printable with the Lisp printer. You don't need to add minibuffer |
86 | history variables to this list, all minibuffer histories will be | |
87 | saved automatically as long as `savehist-save-minibuffer-history' is | |
88 | non-nil. | |
89 | ||
90 | User options should be saved with the customize interface. This | |
91 | list is useful for saving automatically updated variables that are not | |
92 | minibuffer histories, such as `compile-command' or `kill-ring'." | |
93 | :type '(repeat variable) | |
cb23c7c1 RS |
94 | :group 'savehist) |
95 | ||
b91f17dc SM |
96 | (defcustom savehist-file |
97 | (cond | |
98 | ;; Backward compatibility with previous versions of savehist. | |
99 | ((file-exists-p "~/.emacs-history") "~/.emacs-history") | |
100 | ((and (not (featurep 'xemacs)) (file-directory-p "~/.emacs.d/")) | |
101 | "~/.emacs.d/history") | |
102 | ((and (featurep 'xemacs) (file-directory-p "~/.xemacs/")) | |
103 | "~/.xemacs/history") | |
104 | ;; For users without `~/.emacs.d/' or `~/.xemacs/'. | |
105 | (t "~/.emacs-history")) | |
106 | "*File name where minibuffer history is saved to and loaded from. | |
107 | The minibuffer history is a series of Lisp expressions loaded | |
108 | automatically when `savehist-mode' is turned on. See `savehist-mode' | |
109 | for more details. | |
110 | ||
111 | If you want your minibuffer history shared between Emacs and XEmacs, | |
112 | customize this value and make sure that `savehist-coding-system' is | |
113 | set to a coding system that exists in both emacsen." | |
cb23c7c1 RS |
114 | :type 'file |
115 | :group 'savehist) | |
116 | ||
b91f17dc SM |
117 | (defcustom savehist-file-modes #o600 |
118 | "*Default permissions of the history file. | |
216ee1a4 SM |
119 | This is decimal, not octal. The default is 384 (0600 in octal). |
120 | Set to nil to use the default permissions that Emacs uses, typically | |
121 | mandated by umask. The default is a bit more restrictive to protect | |
122 | the user's privacy." | |
cb23c7c1 RS |
123 | :type 'integer |
124 | :group 'savehist) | |
125 | ||
216ee1a4 | 126 | (defcustom savehist-autosave-interval (* 5 60) |
b91f17dc SM |
127 | "*The interval between autosaves of minibuffer history. |
128 | If set to nil, disables timer-based autosaving." | |
216ee1a4 SM |
129 | :type 'integer |
130 | :group 'savehist) | |
131 | ||
b91f17dc | 132 | (defcustom savehist-save-hook nil |
b13e8fb3 | 133 | "Hook called by `savehist-save' before saving the variables. |
b91f17dc SM |
134 | You can use this hook to influence choice and content of variables to |
135 | save." | |
136 | :type 'hook) | |
137 | ||
b13e8fb3 SM |
138 | (defvar savehist-coding-system |
139 | ;; UTF-8 is usually preferable to ISO-2022-8 when available, but under | |
140 | ;; XEmacs, UTF-8 is provided by external packages, and may not always be | |
141 | ;; available, so even if it currently is available, we prefer not to | |
142 | ;; use is. | |
143 | (if (featurep 'xemacs) 'iso-2022-8 'utf-8) | |
216ee1a4 SM |
144 | "The coding system savehist uses for saving the minibuffer history. |
145 | Changing this value while Emacs is running is supported, but considered | |
146 | unwise, unless you know what you are doing.") | |
147 | ||
148 | ;; Internal variables. | |
149 | ||
150 | (defvar savehist-timer nil) | |
151 | ||
152 | (defvar savehist-last-checksum nil) | |
153 | ||
b91f17dc SM |
154 | (defvar savehist-minibuffer-history-variables nil |
155 | "List of minibuffer histories. | |
156 | The contents of this variable is built while Emacs is running, and saved | |
157 | along with minibuffer history. You can change its value off | |
158 | `savehist-save-hook' to influence which variables are saved.") | |
2a2b5b29 | 159 | |
b13e8fb3 SM |
160 | (defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) |
161 | "Coding system without conversion, used for calculating internal checksums. | |
162 | Should be as fast as possible, ideally simply exposing the internal | |
163 | representation of buffer text.") | |
b91f17dc | 164 | |
b13e8fb3 SM |
165 | (defvar savehist-loaded nil |
166 | "Whether the history has already been loaded. | |
167 | This prevents toggling `savehist-mode' from destroying existing | |
168 | minibuffer history.") | |
b91f17dc SM |
169 | |
170 | (eval-when-compile | |
171 | (when (featurep 'xemacs) | |
172 | ;; Must declare this under XEmacs, which doesn't have built-in | |
173 | ;; minibuffer history truncation. | |
174 | (defvar history-length 100))) | |
cb23c7c1 | 175 | \f |
2a2b5b29 SM |
176 | ;; Functions. |
177 | ||
b91f17dc SM |
178 | ;;;###autoload |
179 | (defun savehist-mode (arg) | |
180 | "Toggle savehist-mode. | |
181 | Positive ARG turns on `savehist-mode'. When on, savehist-mode causes | |
182 | minibuffer history to be saved periodically and when exiting Emacs. | |
183 | When turned on for the first time in an Emacs session, it causes the | |
184 | previous minibuffer history to be loaded from `savehist-file'. | |
185 | ||
186 | This mode should normally be turned on from your Emacs init file. | |
187 | Calling it at any other time replaces your current minibuffer histories, | |
188 | which is probably undesirable." | |
189 | (interactive "P") | |
190 | (setq savehist-mode | |
191 | (if (null arg) | |
192 | (not savehist-mode) | |
193 | (> (prefix-numeric-value arg) 0))) | |
194 | (if (not savehist-mode) | |
195 | (savehist-uninstall) | |
196 | (when (and (not savehist-loaded) | |
197 | (file-exists-p savehist-file)) | |
198 | (condition-case errvar | |
199 | (progn | |
200 | ;; Don't set coding-system-for-read -- we rely on the | |
201 | ;; coding cookie to convey that information. That way, if | |
202 | ;; the user changes the value of savehist-coding-system, | |
203 | ;; we can still correctly load the old file. | |
204 | (load savehist-file nil (not (interactive-p))) | |
205 | (setq savehist-loaded t)) | |
206 | (error | |
207 | ;; Don't install the mode if reading failed. Doing so would | |
208 | ;; effectively destroy the user's data at the next save. | |
209 | (setq savehist-mode nil) | |
210 | (savehist-uninstall) | |
211 | (signal (car errvar) (cdr errvar))))) | |
b13e8fb3 SM |
212 | (savehist-install)) |
213 | ||
214 | ;; End with the usual minor-mode conventions normally provided | |
215 | ;; transparently by define-minor-mode. | |
216 | (run-hooks 'savehist-mode-hook) | |
217 | (if (interactive-p) | |
218 | (progn | |
219 | (customize-mark-as-set 'savehist-mode) | |
220 | (unless (current-message) | |
221 | (message "Savehist mode %sabled" (if savehist-mode "en" "dis"))))) | |
222 | ;; Return the new setting. | |
223 | savehist-mode) | |
b91f17dc SM |
224 | (add-minor-mode 'savehist-mode "") |
225 | ||
226 | (defun savehist-load () | |
227 | "Obsolete function provided for transition from old versions of savehist. | |
228 | Don't call this from new code, use (savehist-mode 1) instead. | |
229 | ||
230 | This function loads the variables stored in `savehist-file' and turns on | |
231 | savehist-mode. If savehist-file is in the old format that doesn't record | |
232 | the value of `savehist-minibuffer-history-variables', that value is | |
233 | deducted from the contents of the file." | |
234 | (savehist-mode 1) | |
235 | ;; Old versions of savehist distributed with XEmacs didn't save | |
236 | ;; savehist-minibuffer-history-variables. If that variable is nil | |
237 | ;; after loading the file, try to intuit the intended value. | |
238 | (when (null savehist-minibuffer-history-variables) | |
239 | (setq savehist-minibuffer-history-variables | |
240 | (with-temp-buffer | |
241 | (ignore-errors | |
242 | (insert-file-contents savehist-file)) | |
243 | (let ((vars ()) form) | |
244 | (while (setq form (condition-case nil | |
245 | (read (current-buffer)) (error nil))) | |
246 | ;; Each form read is of the form (setq VAR VALUE). | |
247 | ;; Collect VAR, i.e. (nth form 1). | |
248 | (push (nth 1 form) vars)) | |
249 | vars))))) | |
250 | (make-obsolete 'savehist-load 'savehist-mode) | |
251 | ||
2a2b5b29 SM |
252 | (defun savehist-install () |
253 | "Hook savehist into Emacs. | |
b91f17dc SM |
254 | Normally invoked by calling `savehist-mode' to set the minor mode. |
255 | Installs `savehist-autosave' in `kill-emacs-hook' and on a timer. To | |
256 | undo this, call `savehist-uninstall'." | |
2a2b5b29 SM |
257 | (add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
258 | (add-hook 'kill-emacs-hook 'savehist-autosave) | |
259 | ;; Install an invocation of savehist-autosave on a timer. This | |
260 | ;; should not cause noticeable delays for users -- savehist-autosave | |
261 | ;; executes in under 5 ms on my system. | |
b91f17dc SM |
262 | (when (and savehist-autosave-interval |
263 | (null savehist-timer)) | |
2a2b5b29 SM |
264 | (setq savehist-timer |
265 | (if (featurep 'xemacs) | |
266 | (start-itimer | |
267 | "savehist" 'savehist-autosave savehist-autosave-interval | |
268 | savehist-autosave-interval) | |
b91f17dc SM |
269 | (run-with-timer savehist-autosave-interval |
270 | savehist-autosave-interval 'savehist-autosave))))) | |
2a2b5b29 SM |
271 | |
272 | (defun savehist-uninstall () | |
b91f17dc SM |
273 | "Undo installing savehist. |
274 | Normally invoked by calling `savehist-mode' to unset the minor mode." | |
2a2b5b29 SM |
275 | (remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
276 | (remove-hook 'kill-emacs-hook 'savehist-autosave) | |
277 | (when savehist-timer | |
278 | (if (featurep 'xemacs) | |
279 | (delete-itimer savehist-timer) | |
280 | (cancel-timer savehist-timer)) | |
281 | (setq savehist-timer nil))) | |
cb23c7c1 | 282 | |
216ee1a4 | 283 | (defun savehist-save (&optional auto-save) |
2a2b5b29 SM |
284 | "Save the values of minibuffer history variables. |
285 | Unbound symbols referenced in `savehist-additional-variables' are ignored. | |
216ee1a4 SM |
286 | If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, |
287 | and don't save the buffer if they are the same." | |
cb23c7c1 | 288 | (interactive) |
216ee1a4 SM |
289 | (with-temp-buffer |
290 | (insert | |
291 | (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) | |
292 | ";; Minibuffer history file, automatically generated by `savehist'.\n\n") | |
b91f17dc | 293 | (run-hooks 'savehist-save-hook) |
216ee1a4 SM |
294 | (let ((print-length nil) |
295 | (print-string-length nil) | |
296 | (print-level nil) | |
297 | (print-readably t) | |
b91f17dc SM |
298 | (print-quoted t)) |
299 | ;; Save the minibuffer histories, along with the value of | |
300 | ;; savehist-minibuffer-history-variables itself. | |
301 | (when savehist-save-minibuffer-history | |
302 | (prin1 `(setq savehist-minibuffer-history-variables | |
303 | ',savehist-minibuffer-history-variables) | |
304 | (current-buffer)) | |
305 | (insert ?\n) | |
306 | (dolist (symbol savehist-minibuffer-history-variables) | |
307 | (when (boundp symbol) | |
308 | (let ((value (savehist-trim-history (symbol-value symbol)))) | |
309 | (when value ; don't save empty histories | |
310 | (prin1 `(setq ,symbol ',value) (current-buffer)) | |
311 | (insert ?\n)))))) | |
312 | ;; Save the additional variables. | |
313 | (dolist (symbol savehist-additional-variables) | |
314 | (when (boundp symbol) | |
315 | (let ((value (symbol-value symbol))) | |
316 | (when (savehist-printable value) | |
317 | (prin1 `(setq ,symbol ',value) (current-buffer)) | |
318 | (insert ?\n)))))) | |
216ee1a4 SM |
319 | ;; If autosaving, avoid writing if nothing has changed since the |
320 | ;; last write. | |
321 | (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) | |
322 | (unless (and auto-save (equal checksum savehist-last-checksum)) | |
323 | ;; Set file-precious-flag when saving the buffer because we | |
324 | ;; don't want a half-finished write ruining the entire | |
2a2b5b29 SM |
325 | ;; history. Remember that this is run from a timer and from |
326 | ;; kill-emacs-hook, and also that multiple Emacs instances | |
327 | ;; could write to this file at once. | |
216ee1a4 SM |
328 | (let ((file-precious-flag t) |
329 | (coding-system-for-write savehist-coding-system)) | |
330 | (write-region (point-min) (point-max) savehist-file nil | |
331 | (unless (interactive-p) 'quiet))) | |
b91f17dc SM |
332 | (when savehist-file-modes |
333 | (set-file-modes savehist-file savehist-file-modes)) | |
216ee1a4 SM |
334 | (setq savehist-last-checksum checksum))))) |
335 | ||
336 | (defun savehist-autosave () | |
b91f17dc SM |
337 | "Save the minibuffer history if it has been modified since the last save. |
338 | Does nothing if savehist-mode is off." | |
339 | (when savehist-mode | |
340 | (savehist-save t))) | |
341 | ||
342 | (defun savehist-trim-history (value) | |
343 | ;; Retain only the first history-length items in VALUE. Only used | |
344 | ;; under XEmacs, which doesn't (yet) implement automatic trimming of | |
345 | ;; history lists to history-length items. | |
346 | (if (and (featurep 'xemacs) | |
347 | (natnump history-length) | |
348 | (> (length value) history-length)) | |
349 | ;; Equivalent to `(subseq value 0 history-length)', but doesn't | |
350 | ;; need cl-extra at run-time. | |
351 | (loop repeat history-length collect (pop value)) | |
352 | value)) | |
216ee1a4 SM |
353 | |
354 | (defun savehist-printable (value) | |
3930b7e4 | 355 | "Return non-nil if VALUE is printable." |
216ee1a4 | 356 | (cond |
b91f17dc | 357 | ;; Quick response for oft-encountered types known to be printable. |
216ee1a4 SM |
358 | ((stringp value)) |
359 | ((numberp value)) | |
360 | ((symbolp value)) | |
361 | (t | |
362 | ;; For others, check explicitly. | |
b91f17dc SM |
363 | (with-temp-buffer |
364 | (condition-case nil | |
365 | (let ((print-readably t) (print-level nil)) | |
366 | ;; Print the value into a buffer... | |
367 | (prin1 value (current-buffer)) | |
216ee1a4 | 368 | ;; ...and attempt to read it. |
b91f17dc | 369 | (read (point-min-marker)) |
216ee1a4 SM |
370 | ;; The attempt worked: the object is printable. |
371 | t) | |
b91f17dc SM |
372 | ;; The attempt failed: the object is not printable. |
373 | (error nil)))))) | |
cb23c7c1 | 374 | |
2a2b5b29 SM |
375 | (defun savehist-minibuffer-hook () |
376 | (add-to-list 'savehist-minibuffer-history-variables | |
b91f17dc | 377 | minibuffer-history-variable)) |
2a2b5b29 | 378 | |
cb23c7c1 | 379 | (provide 'savehist) |
b91f17dc | 380 | \f |
16b52b61 | 381 | ;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f |
b91f17dc | 382 | |
cb23c7c1 | 383 | ;;; savehist.el ends here |