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