comparison lisp/savehist.el @ 66120:87310076f109

(savehist-autosave-interval, savehist-coding-system, savehist-timer) (savehist-last-checksum, savehist-no-conversion): New vars. (savehist-autosave, savehist-process-for-saving, savehist-printable): New funs. (savehist-load, savehist-save): Use them. (savehist-delimit): Remove.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Sun, 16 Oct 2005 15:02:39 +0000
parents 9b8e76617c8c
children b1015e4158db
comparison
equal deleted inserted replaced
66119:bc2d2dc9f534 66120:87310076f109
1 ;;; savehist.el --- Save minibuffer history 1 ;;; savehist.el --- Save minibuffer history.
2 2
3 ;; Copyright (c) 1997 Free Software Foundation 3 ;; Copyright (C) 1997, 2005 Free Software Foundation
4 4
5 ;; Author: Hrvoje Niksic <hniksic@xemacs.org> 5 ;; Author: Hrvoje Niksic <hniksic@xemacs.org>
6 ;; Keywords: minibuffer 6 ;; Keywords: minibuffer
7 ;; Version: 0.4 7 ;; Version: 7
8 8
9 ;; This file is part of GNU Emacs. 9 ;; This file is part of GNU Emacs.
10 10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify 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 12 ;; it under the terms of the GNU General Public License as published by
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA. 24 ;; Boston, MA 02110-1301, USA.
25 25
26 ;;; Commentary: 26 ;;; Commentary:
27 27
28 ;; This package provides the feature of saving minibuffer 28 ;; Many editors (e.g. Vim) have the feature of saving minibuffer
29 ;; history to an external file after exit. When Emacs is about the exit, 29 ;; history to an external file after exit. This package provides the
30 ;; same feature in Emacs. When Emacs is about the exit,
30 ;; `savehist-save' will dump the contents of various minibuffer 31 ;; `savehist-save' will dump the contents of various minibuffer
31 ;; histories (as determined by `savehist-history-variables') to a save 32 ;; histories (as determined by `savehist-history-variables') to a save
32 ;; file (`~/.emacs-history' by default). Although the package was 33 ;; file (`~/.emacs-history' by default). Although the package was
33 ;; designed for saving the minibuffer histories, any variables can be 34 ;; designed for saving the minibuffer histories, any variables can be
34 ;; saved that way. 35 ;; saved that way.
38 ;; (require 'savehist) 39 ;; (require 'savehist)
39 ;; (savehist-load) 40 ;; (savehist-load)
40 41
41 ;; Be sure to have `savehist.el' in a directory that is in your 42 ;; Be sure to have `savehist.el' in a directory that is in your
42 ;; load-path, and byte-compile it. 43 ;; load-path, and byte-compile it.
43 44
44 ;;; Code: 45 ;;; Code:
46
47 (require 'custom)
48 (require 'cl)
45 49
46 ;; User variables 50 ;; User variables
47 51
48 (defgroup savehist nil 52 (defgroup savehist nil
49 "Save minibuffer history." 53 "Save minibuffer history."
50 :group 'minibuffer) 54 :group 'minibuffer)
51
52 55
53 (defcustom savehist-history-variables 56 (defcustom savehist-history-variables
54 '( 57 '(
55 ;; Catch-all minibuffer history 58 ;; Catch-all minibuffer history
56 minibuffer-history 59 minibuffer-history
85 ;; Extended commands 88 ;; Extended commands
86 read-command-history 89 read-command-history
87 90
88 ;; Info, lookup, and bookmark historys 91 ;; Info, lookup, and bookmark historys
89 Info-minibuffer-history 92 Info-minibuffer-history
93 Info-search-history
90 Manual-page-minibuffer-history 94 Manual-page-minibuffer-history
91 95
92 ;; Emacs-specific: 96 ;; Emacs-specific:
93 ;; Extended commands 97 ;; Extended commands
94 extended-command-history) 98 extended-command-history)
96 Every symbol should refer to a variable. The variable will be saved 100 Every symbol should refer to a variable. The variable will be saved
97 only if it is bound and has a non-nil value. Thus it is safe to 101 only if it is bound and has a non-nil value. Thus it is safe to
98 specify a superset of the variables a user is expected to want to 102 specify a superset of the variables a user is expected to want to
99 save. 103 save.
100 104
101 Default value contains minibuffer history variables used by Emacs, XEmacs, 105 Default value contains minibuffer history variables used by Emacs, XEmacs,
102 and Viper (uh-oh)." 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'."
103 :type '(repeat (symbol :tag "Variable")) 110 :type '(repeat (symbol :tag "Variable"))
104 :group 'savehist) 111 :group 'savehist)
105 112
106 (defcustom savehist-file "~/.emacs-history" 113 (defcustom savehist-file "~/.emacs-history"
107 "*File name to save minibuffer history to. 114 "*File name to save minibuffer history to.
116 If set to nil, the length is unlimited." 123 If set to nil, the length is unlimited."
117 :type '(choice integer 124 :type '(choice integer
118 (const :tag "Unlimited" nil)) 125 (const :tag "Unlimited" nil))
119 :group 'savehist) 126 :group 'savehist)
120 127
121 (defcustom savehist-modes 384 128 (defcustom savehist-modes #o600
122 "*Default permissions of the history file. 129 "*Default permissions of the history file.
123 This is decimal, not octal. The default is 384 (0600 in octal)." 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."
124 :type 'integer 134 :type 'integer
125 :group 'savehist) 135 :group 'savehist)
126 136
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.
146 Changing this value while Emacs is running is supported, but considered
147 unwise, 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))
127 158
128 ;; Functions 159 ;; Functions
129 160
130 ;;;###autoload 161 ;;;###autoload
131 (defun savehist-load (&optional no-hook) 162 (defun savehist-load (&optional no-hook)
132 "Load the minibuffer histories from `savehist-file'. 163 "Load the minibuffer histories from `savehist-file'.
133 Unless NO-HOOK is specified, the function will also add the save function 164 Unless NO-HOOK is specified, the function will also add the save function
134 to `kill-emacs-hook', thus ensuring that the minibuffer contents will be 165 to `kill-emacs-hook' and on a timer, ensuring that the minibuffer contents
135 saved before leaving Emacs. 166 will be saved before leaving Emacs.
136 167
137 This function should be normally used from your Emacs init file. Since it 168 This function should be normally used from your Emacs init file. Since it
138 removes your current minibuffer histories, it is unwise to call it at any 169 removes your current minibuffer histories, it is unwise to call it at any
139 other time." 170 other time."
140 (interactive "P") 171 (interactive "P")
141 (unless no-hook 172 (unless no-hook
142 (add-hook 'kill-emacs-hook 'savehist-save)) 173 (add-hook 'kill-emacs-hook 'savehist-autosave)
143 (load savehist-file t)) 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))))
144 190
145 ;;;###autoload 191 ;;;###autoload
146 (defun savehist-save () 192 (defun savehist-save (&optional auto-save)
147 "Save the histories from `savehist-history-variables' to `savehist-file'. 193 "Save the histories from `savehist-history-variables' to `savehist-file'.
148 A variable will be saved if it is bound and non-nil." 194 Unbound symbols referenced in `savehist-history-variables' are ignored.
195 If 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."
149 (interactive) 197 (interactive)
150 (save-excursion 198 (with-temp-buffer
151 ;; Is it wise to junk `find-file-hooks' just like that? How else 199 (insert
152 ;; should I avoid font-lock et al.? 200 (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system)
153 (let ((find-file-hooks nil) 201 ";; Minibuffer history file, automatically generated by `savehist'.\n\n")
154 (buffer-exists-p (get-file-buffer savehist-file))) 202 (let ((print-length nil)
155 (set-buffer (find-file-noselect savehist-file)) 203 (print-string-length nil)
156 (unwind-protect 204 (print-level nil)
157 (progn 205 (print-readably t)
158 (erase-buffer) 206 (print-quoted t))
159 (insert 207 (dolist (sym savehist-history-variables)
160 ";; -*- emacs-lisp -*-\n" 208 (when (boundp sym)
161 ";; Minibuffer history file.\n\n" 209 (let ((value (savehist-process-for-saving (symbol-value sym))))
162 ";; This file is automatically generated by `savehist-save'" 210 (prin1 `(setq ,sym ',value) (current-buffer))
163 " or when\n" 211 (insert ?\n)))))
164 ";; exiting Emacs.\n" 212 ;; If autosaving, avoid writing if nothing has changed since the
165 ";; Do not edit. Unless you really want to, that is.\n\n") 213 ;; last write.
166 (let ((print-length nil) 214 (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion)))
167 (print-string-length nil) 215 (unless (and auto-save (equal checksum savehist-last-checksum))
168 (print-level nil) 216 ;; Set file-precious-flag when saving the buffer because we
169 (print-readably t)) 217 ;; don't want a half-finished write ruining the entire
170 (dolist (sym savehist-history-variables) 218 ;; history. (Remember that this is run from a timer and from
171 (when (and (boundp sym) 219 ;; kill-emacs-hook.)
172 (symbol-value sym)) 220 (let ((file-precious-flag t)
173 (prin1 221 (coding-system-for-write savehist-coding-system))
174 `(setq ,sym (quote ,(savehist-delimit (symbol-value sym) 222 (write-region (point-min) (point-max) savehist-file nil
175 savehist-length))) 223 (unless (interactive-p) 'quiet)))
176 (current-buffer)) 224 (when savehist-modes
177 (insert ?\n)))) 225 (set-file-modes savehist-file savehist-modes))
178 (save-buffer) 226 (setq savehist-last-checksum checksum)))))
179 (set-file-modes savehist-file savehist-modes)) 227
180 (or buffer-exists-p 228 (defun savehist-autosave ()
181 (kill-buffer (current-buffer))))))) 229 "Save the minibuffer history if it has been modified since the last save."
182 230 (savehist-save t))
183 ;; If ARG is a list with less than N elements, return it, else return 231
184 ;; its subsequence of N elements. If N is nil or ARG is not a list, 232 (defun savehist-process-for-saving (value)
185 ;; always return ARG. 233 ;; Process VALUE for saving to file. If it is a list, retain only
186 (defun savehist-delimit (arg n) 234 ;; the first `savehist-length' values and prune non-printable ones.
187 (if (and n 235 ;; If VALUE is not a list, return it as-is if it is printable and
188 (listp arg) 236 ;; nil otherwise.
189 (> (length arg) n)) 237 (cond
190 (subseq arg 0 n) 238 ((listp value)
191 arg)) 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)))))
192 266
193 (provide 'savehist) 267 (provide 'savehist)
194 268
195 ;;; savehist.el ends here 269 ;;; savehist.el ends here