(easy-mmode-define-global-mode): Don't add a dummy doc-string-elt property.
[emacs.git] / lisp / savehist.el
blob3021f2805bbcec111d1e40e8b0ccc0f17be28936
1 ;;; savehist.el --- Save minibuffer history.
3 ;; Copyright (C) 1997, 2005 Free Software Foundation
5 ;; Author: Hrvoje Niksic <hniksic@xemacs.org>
6 ;; Keywords: minibuffer
7 ;; Version: 7
9 ;; This file is part of GNU Emacs.
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.
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.
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.
26 ;;; Commentary:
28 ;; Many editors (e.g. Vim) have the feature of saving minibuffer
29 ;; history to an external file after exit. This package provides the
30 ;; same feature in Emacs. When Emacs is about the exit,
31 ;; `savehist-save' will dump the contents of various minibuffer
32 ;; histories (as determined by `savehist-history-variables') to a save
33 ;; file (`~/.emacs-history' by default). Although the package was
34 ;; designed for saving the minibuffer histories, any variables can be
35 ;; saved that way.
37 ;; To use savehist, put the following to `~/.emacs':
39 ;; (require 'savehist)
40 ;; (savehist-load)
42 ;; Be sure to have `savehist.el' in a directory that is in your
43 ;; load-path, and byte-compile it.
45 ;;; Code:
47 (require 'custom)
49 ;; User variables
51 (defgroup savehist nil
52 "Save minibuffer history."
53 :group 'minibuffer)
55 (defcustom savehist-history-variables
57 ;; Catch-all minibuffer history
58 minibuffer-history
59 ;; File-oriented commands
60 file-name-history
61 ;; Regexp-related reads
62 regexp-history
63 ;; Searches in minibuffer (via `M-r' and such)
64 minibuffer-history-search-history
65 ;; Query replace
66 query-replace-history
67 ;; eval-expression (`M-:')
68 read-expression-history
69 ;; shell-command (`M-!')
70 shell-command-history
71 ;; compile
72 compile-history
73 ;; find-tag (`M-.')
74 find-tag-history
75 ;; grep
76 grep-history
77 grep-find-history
78 ;; Viper stuff
79 vip-ex-history vip-search-history
80 vip-replace1-history vip-replace2-history
81 vip-shell-history vip-search-history
83 ;; XEmacs-specific:
84 ;; Buffer-related commands
85 buffer-history
86 ;; Reads of variables and functions
87 variable-history function-history
88 ;; Extended commands
89 read-command-history
91 ;; Info, lookup, and bookmark historys
92 Info-minibuffer-history
93 Info-search-history
94 Manual-page-minibuffer-history
96 ;; Emacs-specific:
97 ;; Extended commands
98 extended-command-history)
99 "*List of symbols to be saved.
100 Every symbol should refer to a variable. The variable will be saved
101 only if it is bound and has a non-nil value. Thus it is safe to
102 specify a superset of the variables a user is expected to want to
103 save.
105 Default value contains minibuffer history variables used by Emacs, XEmacs,
106 and Viper (uh-oh). Note that, if you customize this variable, you
107 can lose the benefit of future versions of Emacs adding new values to
108 the list. Because of that it might be more useful to add values using
109 `add-to-list'."
110 :type '(repeat (symbol :tag "Variable"))
111 :group 'savehist)
113 (defcustom savehist-file "~/.emacs-history"
114 "*File name to save minibuffer history to.
115 The minibuffer history is a series of Lisp expressions, which should be
116 loaded using `savehist-load' from your .emacs. See `savehist-load' for
117 more details."
118 :type 'file
119 :group 'savehist)
121 (defcustom savehist-length 100
122 "*Maximum length of a minibuffer list.
123 If set to nil, the length is unlimited."
124 :type '(choice integer
125 (const :tag "Unlimited" nil))
126 :group 'savehist)
128 (defcustom savehist-modes #o600
129 "*Default permissions of the history file.
130 This is decimal, not octal. The default is 384 (0600 in octal).
131 Set to nil to use the default permissions that Emacs uses, typically
132 mandated by umask. The default is a bit more restrictive to protect
133 the user's privacy."
134 :type 'integer
135 :group 'savehist)
137 (defcustom savehist-autosave-interval (* 5 60)
138 "*The interval during which savehist should autosave the history buffer."
139 :type 'integer
140 :group 'savehist)
142 (defvar savehist-coding-system
143 ;; UTF-8 is usually preferable to ISO-2022-8 when available, but under
144 ;; XEmacs, UTF-8 is provided by external packages, and may not always be
145 ;; available, so even if it currently is available, we prefer not to
146 ;; use is.
147 (if (featurep 'xemacs) 'iso-2022-8 'utf-8)
148 "The coding system savehist uses for saving the minibuffer history.
149 Changing this value while Emacs is running is supported, but considered
150 unwise, unless you know what you are doing.")
152 ;; Internal variables.
154 (defvar savehist-timer nil)
156 (defvar savehist-last-checksum nil)
158 (defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion)
159 ;; FIXME: Why not use savehist-coding-system?
160 "Coding system without conversion, only used for calculating checksums.")
162 ;; Functions
164 ;;;###autoload
165 (defun savehist-load (&optional no-hook)
166 "Load the minibuffer histories from `savehist-file'.
167 Unless NO-HOOK is specified, the function will also add the save function
168 to `kill-emacs-hook' and on a timer, ensuring that the minibuffer contents
169 will be saved before leaving Emacs.
171 This function should be normally used from your Emacs init file. Since it
172 removes your current minibuffer histories, it is unwise to call it at any
173 other time."
174 (interactive "P")
175 (unless no-hook
176 (add-hook 'kill-emacs-hook 'savehist-autosave)
177 ;; Install an invocation of savehist-autosave on a timer. This
178 ;; should not cause a noticeable delay -- savehist-autosave
179 ;; executes in under 5 ms on my system.
180 (unless savehist-timer
181 (setq savehist-timer
182 (if (featurep 'xemacs)
183 (start-itimer
184 "savehist" 'savehist-autosave savehist-autosave-interval
185 savehist-autosave-interval)
186 (run-with-idle-timer savehist-autosave-interval savehist-autosave-interval
187 'savehist-autosave)))))
188 ;; Don't set coding-system-for-read here. We rely on autodetection
189 ;; and the coding cookie to convey that information. That way, if
190 ;; the user changes the value of savehist-coding-system, we can
191 ;; still correctly load the old file.
192 (load savehist-file t (not (interactive-p))))
194 ;;;###autoload
195 (defun savehist-save (&optional auto-save)
196 "Save the histories from `savehist-history-variables' to `savehist-file'.
197 Unbound symbols referenced in `savehist-history-variables' are ignored.
198 If AUTO-SAVE is non-nil, compare the saved contents to the one last saved,
199 and don't save the buffer if they are the same."
200 (interactive)
201 (with-temp-buffer
202 (insert
203 (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system)
204 ";; Minibuffer history file, automatically generated by `savehist'.\n\n")
205 (let ((print-length nil)
206 (print-string-length nil)
207 (print-level nil)
208 (print-readably t)
209 (print-quoted t))
210 (dolist (sym savehist-history-variables)
211 (when (boundp sym)
212 (let ((value (savehist-process-for-saving (symbol-value sym))))
213 (prin1 `(setq ,sym ',value) (current-buffer))
214 (insert ?\n)))))
215 ;; If autosaving, avoid writing if nothing has changed since the
216 ;; last write.
217 (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion)))
218 (unless (and auto-save (equal checksum savehist-last-checksum))
219 ;; Set file-precious-flag when saving the buffer because we
220 ;; don't want a half-finished write ruining the entire
221 ;; history. (Remember that this is run from a timer and from
222 ;; kill-emacs-hook.)
223 (let ((file-precious-flag t)
224 (coding-system-for-write savehist-coding-system))
225 (write-region (point-min) (point-max) savehist-file nil
226 (unless (interactive-p) 'quiet)))
227 (when savehist-modes
228 (set-file-modes savehist-file savehist-modes))
229 (setq savehist-last-checksum checksum)))))
231 (defun savehist-autosave ()
232 "Save the minibuffer history if it has been modified since the last save."
233 (savehist-save t))
235 (defun savehist-process-for-saving (value)
236 ;; Process VALUE for saving to file. If it is a list, retain only
237 ;; the first `savehist-length' values and prune non-printable ones.
238 ;; If VALUE is not a list, return it as-is if it is printable and
239 ;; nil otherwise.
240 (cond
241 ((listp value)
242 (when (and savehist-length (> (length value) savehist-length))
243 ;; This should be: (setq value (subseq value 0 savehist-length))
244 (setq value (copy-sequence value))
245 (setcdr (nthcdr savehist-length value) nil))
246 ;; And this should be (remove-if-not #'savehist-printable value)
247 (delq nil (mapcar (lambda (x) (if (savehist-printable x) x)) value)))
248 ((savehist-printable value) value)
249 (t nil)))
251 (defun savehist-printable (value)
252 "Return non-nil if VALUE is printable."
253 ;; Quick response for oft-encountered types known to be printable.
254 (cond
255 ((stringp value))
256 ((numberp value))
257 ((symbolp value))
259 ;; For others, check explicitly.
260 (condition-case nil
261 (let ((print-readably t)
262 (print-level nil)
263 (chars ()))
264 ;; Print the value into a string...
265 (prin1 value (lambda (char) (push char chars)))
266 ;; ...and attempt to read it.
267 (read (apply #'string (nreverse chars)))
268 ;; The attempt worked: the object is printable.
270 ;; The attempt failed: the object is not printable.
271 (error nil)))))
273 (provide 'savehist)
275 ;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f
276 ;;; savehist.el ends here