aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2005-11-01 05:49:46 +0000
committerStefan Monnier2005-11-01 05:49:46 +0000
commitb91f17dcc62ba3e510bb26f2a9dd6124269686c1 (patch)
tree59c970278d31216443200527d78054727cab9940
parentd08a1c88d63c66a8553025e85ee548c98a75ef26 (diff)
downloademacs-b91f17dcc62ba3e510bb26f2a9dd6124269686c1.tar.gz
emacs-b91f17dcc62ba3e510bb26f2a9dd6124269686c1.zip
Sync up to version 19.
(savehist-mode): New minor mode. (savehist-file): Use ~/.emacs.d or ~/.xemacs if available. (savehist-length): Remove (use history-length instead). (savehist-file-modes): Rename from savehist-modes. (savehist-save-hook, savehist-loaded): New vars. (savehist-load): Use savehist-mode. Try to smooth up transition from old format to new format. (savehist-install): Allow savehist-autosave-interval to be nil. (savehist-save): Run the new hook. Be more careful to only trim the history variables. (savehist-trim-history): New fun. Replaces savehist-process-for-saving. (savehist-printable): Print into a buffer rather than char-by-char.
-rw-r--r--lisp/savehist.el312
1 files changed, 205 insertions, 107 deletions
diff --git a/lisp/savehist.el b/lisp/savehist.el
index 98012d02114..a6e445435a2 100644
--- a/lisp/savehist.el
+++ b/lisp/savehist.el
@@ -4,7 +4,7 @@
4 4
5;; Author: Hrvoje Niksic <hniksic@xemacs.org> 5;; Author: Hrvoje Niksic <hniksic@xemacs.org>
6;; Keywords: minibuffer 6;; Keywords: minibuffer
7;; Version: 9 7;; Version: 19
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
@@ -32,10 +32,15 @@
32;; variables may be specified by customizing 32;; variables may be specified by customizing
33;; `savehist-additional-variables'. 33;; `savehist-additional-variables'.
34 34
35;; To use savehist, put the following to `~/.emacs': 35;; To use savehist, turn on savehist-mode by putting the following in
36;; `~/.emacs':
36;; 37;;
37;; (require 'savehist) 38;; (savehist-mode 1)
38;; (savehist-load) 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
43;; load it by loading the `savehist-file' with `M-x load'.
39 44
40;; If you are using a version of Emacs that does not ship with this 45;; If you are using a version of Emacs that does not ship with this
41;; package, be sure to have `savehist.el' in a directory that is in 46;; package, be sure to have `savehist.el' in a directory that is in
@@ -53,41 +58,62 @@
53 "Save minibuffer history." 58 "Save minibuffer history."
54 :group 'minibuffer) 59 :group 'minibuffer)
55 60
61;;;###autoload
62(defcustom savehist-mode nil
63 "Mode for automatic saving of minibuffer history.
64Set this by calling the `savehist-mode' function or using the customize
65interface."
66 :type 'boolean
67 :set (lambda (symbol value) (savehist-mode (or value 0)))
68 :initialize 'custom-initialize-default
69 :require 'savehist
70 :group 'savehist)
71
56(defcustom savehist-save-minibuffer-history t 72(defcustom savehist-save-minibuffer-history t
57 "If non-nil, save all recorded minibuffer histories." 73 "*If non-nil, save all recorded minibuffer histories.
74If you want to save only specific histories, use `savehist-save-hook' to
75modify the value of `savehist-minibuffer-history-variables'."
58 :type 'boolean 76 :type 'boolean
59 :group 'savehist) 77 :group 'savehist)
60 78
61(defcustom savehist-additional-variables () 79(defcustom savehist-additional-variables ()
62 "List of additional variables to save. 80 "*List of additional variables to save.
63Each element is a symbol whose value will be persisted across Emacs 81Each element is a symbol whose value will be persisted across Emacs
64sessions that use savehist. The contents of variables should be 82sessions that use savehist. The contents of variables should be
65printable with the Lisp printer. If the variable's value is a list, 83printable with the Lisp printer. You don't need to add minibuffer
66it will be trimmed to `savehist-length' elements. 84history variables to this list, all minibuffer histories will be
67 85saved automatically as long as `savehist-save-minibuffer-history' is
68You don't need to add minibuffer history variables to this list. All 86non-nil.
69minibuffer histories will be saved automatically." 87
70 :type '(repeat (symbol :tag "Variable")) 88User options should be saved with the customize interface. This
89list is useful for saving automatically updated variables that are not
90minibuffer histories, such as `compile-command' or `kill-ring'."
91 :type '(repeat variable)
71 :group 'savehist) 92 :group 'savehist)
72 93
73(defcustom savehist-file "~/.emacs-history" 94(defcustom savehist-file
74 "File name to save minibuffer history to. 95 (cond
75The minibuffer history is a series of Lisp expressions, which should be 96 ;; Backward compatibility with previous versions of savehist.
76loaded using `savehist-load' from your .emacs. See `savehist-load' for 97 ((file-exists-p "~/.emacs-history") "~/.emacs-history")
77more details." 98 ((and (not (featurep 'xemacs)) (file-directory-p "~/.emacs.d/"))
99 "~/.emacs.d/history")
100 ((and (featurep 'xemacs) (file-directory-p "~/.xemacs/"))
101 "~/.xemacs/history")
102 ;; For users without `~/.emacs.d/' or `~/.xemacs/'.
103 (t "~/.emacs-history"))
104 "*File name where minibuffer history is saved to and loaded from.
105The minibuffer history is a series of Lisp expressions loaded
106automatically when `savehist-mode' is turned on. See `savehist-mode'
107for more details.
108
109If you want your minibuffer history shared between Emacs and XEmacs,
110customize this value and make sure that `savehist-coding-system' is
111set to a coding system that exists in both emacsen."
78 :type 'file 112 :type 'file
79 :group 'savehist) 113 :group 'savehist)
80 114
81(defcustom savehist-length 100 115(defcustom savehist-file-modes #o600
82 "Maximum length of a minibuffer list. 116 "*Default permissions of the history file.
83Minibuffer histories with more entries are trimmed when saved, the older
84entries being removed first. If set to nil, the length is unlimited."
85 :type '(choice integer
86 (const :tag "Unlimited" nil))
87 :group 'savehist)
88
89(defcustom savehist-modes #o600
90 "Default permissions of the history file.
91This is decimal, not octal. The default is 384 (0600 in octal). 117This is decimal, not octal. The default is 384 (0600 in octal).
92Set to nil to use the default permissions that Emacs uses, typically 118Set to nil to use the default permissions that Emacs uses, typically
93mandated by umask. The default is a bit more restrictive to protect 119mandated by umask. The default is a bit more restrictive to protect
@@ -96,16 +122,18 @@ the user's privacy."
96 :group 'savehist) 122 :group 'savehist)
97 123
98(defcustom savehist-autosave-interval (* 5 60) 124(defcustom savehist-autosave-interval (* 5 60)
99 "The interval during which savehist should autosave the history buffer." 125 "*The interval between autosaves of minibuffer history.
126If set to nil, disables timer-based autosaving."
100 :type 'integer 127 :type 'integer
101 :group 'savehist) 128 :group 'savehist)
102 129
103(defvar savehist-coding-system 130(defcustom savehist-save-hook nil
104 ;; UTF-8 is usually preferable to ISO-2022-8 when available, but under 131 "Hook called by savehist-save before saving the variables.
105 ;; XEmacs, UTF-8 is provided by external packages, and may not always be 132You can use this hook to influence choice and content of variables to
106 ;; available, so even if it currently is available, we prefer not to 133save."
107 ;; use is. 134 :type 'hook)
108 (if (featurep 'xemacs) 'iso-2022-8 'utf-8) 135
136(defvar savehist-coding-system (if (featurep 'xemacs) 'iso-2022-8 'utf-8)
109 "The coding system savehist uses for saving the minibuffer history. 137 "The coding system savehist uses for saving the minibuffer history.
110Changing this value while Emacs is running is supported, but considered 138Changing this value while Emacs is running is supported, but considered
111unwise, unless you know what you are doing.") 139unwise, unless you know what you are doing.")
@@ -116,34 +144,115 @@ unwise, unless you know what you are doing.")
116 144
117(defvar savehist-last-checksum nil) 145(defvar savehist-last-checksum nil)
118 146
119(defvar savehist-minibuffer-history-variables nil) 147(defvar savehist-minibuffer-history-variables nil
148 "List of minibuffer histories.
149The contents of this variable is built while Emacs is running, and saved
150along with minibuffer history. You can change its value off
151`savehist-save-hook' to influence which variables are saved.")
120 152
121(defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) 153;; Coding system without any conversion, used for calculating an
122 "Coding system without conversion, only used for calculating checksums. 154;; internal checksum. Should be as fast as possible, ideally simply
123It should be as discriminating as `savehist-coding-system' but faster.") 155;; exposing the internal representation of buffer text.
156(defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion))
157
158;; Whether the history has already been loaded. This prevents
159;; toggling savehist-mode from destroying existing minibuffer history.
160(defvar savehist-loaded nil)
161
162(eval-when-compile
163 (when (featurep 'xemacs)
164 ;; Must declare this under XEmacs, which doesn't have built-in
165 ;; minibuffer history truncation.
166 (defvar history-length 100)))
124 167
125;; Functions. 168;; Functions.
126 169
170;;;###autoload
171(defun savehist-mode (arg)
172 "Toggle savehist-mode.
173Positive ARG turns on `savehist-mode'. When on, savehist-mode causes
174minibuffer history to be saved periodically and when exiting Emacs.
175When turned on for the first time in an Emacs session, it causes the
176previous minibuffer history to be loaded from `savehist-file'.
177
178This mode should normally be turned on from your Emacs init file.
179Calling it at any other time replaces your current minibuffer histories,
180which is probably undesirable."
181 (interactive "P")
182 (setq savehist-mode
183 (if (null arg)
184 (not savehist-mode)
185 (> (prefix-numeric-value arg) 0)))
186 (if (not savehist-mode)
187 (savehist-uninstall)
188 (when (and (not savehist-loaded)
189 (file-exists-p savehist-file))
190 (condition-case errvar
191 (progn
192 ;; Don't set coding-system-for-read -- we rely on the
193 ;; coding cookie to convey that information. That way, if
194 ;; the user changes the value of savehist-coding-system,
195 ;; we can still correctly load the old file.
196 (load savehist-file nil (not (interactive-p)))
197 (setq savehist-loaded t))
198 (error
199 ;; Don't install the mode if reading failed. Doing so would
200 ;; effectively destroy the user's data at the next save.
201 (setq savehist-mode nil)
202 (savehist-uninstall)
203 (signal (car errvar) (cdr errvar)))))
204 (savehist-install)))
205(add-minor-mode 'savehist-mode "")
206
207(defun savehist-load ()
208 "Obsolete function provided for transition from old versions of savehist.
209Don't call this from new code, use (savehist-mode 1) instead.
210
211This function loads the variables stored in `savehist-file' and turns on
212savehist-mode. If savehist-file is in the old format that doesn't record
213the value of `savehist-minibuffer-history-variables', that value is
214deducted from the contents of the file."
215 (savehist-mode 1)
216 ;; Old versions of savehist distributed with XEmacs didn't save
217 ;; savehist-minibuffer-history-variables. If that variable is nil
218 ;; after loading the file, try to intuit the intended value.
219 (when (null savehist-minibuffer-history-variables)
220 (setq savehist-minibuffer-history-variables
221 (with-temp-buffer
222 (ignore-errors
223 (insert-file-contents savehist-file))
224 (let ((vars ()) form)
225 (while (setq form (condition-case nil
226 (read (current-buffer)) (error nil)))
227 ;; Each form read is of the form (setq VAR VALUE).
228 ;; Collect VAR, i.e. (nth form 1).
229 (push (nth 1 form) vars))
230 vars)))))
231(make-obsolete 'savehist-load 'savehist-mode)
232
127(defun savehist-install () 233(defun savehist-install ()
128 "Hook savehist into Emacs. 234 "Hook savehist into Emacs.
129This will install `savehist-autosave' in `kill-emacs-hook' and on a timer. 235Normally invoked by calling `savehist-mode' to set the minor mode.
130To undo this, call `savehist-uninstall'." 236Installs `savehist-autosave' in `kill-emacs-hook' and on a timer. To
237undo this, call `savehist-uninstall'."
131 (add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) 238 (add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook)
132 (add-hook 'kill-emacs-hook 'savehist-autosave) 239 (add-hook 'kill-emacs-hook 'savehist-autosave)
133 ;; Install an invocation of savehist-autosave on a timer. This 240 ;; Install an invocation of savehist-autosave on a timer. This
134 ;; should not cause noticeable delays for users -- savehist-autosave 241 ;; should not cause noticeable delays for users -- savehist-autosave
135 ;; executes in under 5 ms on my system. 242 ;; executes in under 5 ms on my system.
136 (unless savehist-timer 243 (when (and savehist-autosave-interval
244 (null savehist-timer))
137 (setq savehist-timer 245 (setq savehist-timer
138 (if (featurep 'xemacs) 246 (if (featurep 'xemacs)
139 (start-itimer 247 (start-itimer
140 "savehist" 'savehist-autosave savehist-autosave-interval 248 "savehist" 'savehist-autosave savehist-autosave-interval
141 savehist-autosave-interval) 249 savehist-autosave-interval)
142 (run-with-timer savehist-autosave-interval savehist-autosave-interval 250 (run-with-timer savehist-autosave-interval
143 'savehist-autosave))))) 251 savehist-autosave-interval 'savehist-autosave)))))
144 252
145(defun savehist-uninstall () 253(defun savehist-uninstall ()
146 "Undo installing savehist." 254 "Undo installing savehist.
255Normally invoked by calling `savehist-mode' to unset the minor mode."
147 (remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) 256 (remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook)
148 (remove-hook 'kill-emacs-hook 'savehist-autosave) 257 (remove-hook 'kill-emacs-hook 'savehist-autosave)
149 (when savehist-timer 258 (when savehist-timer
@@ -152,26 +261,6 @@ To undo this, call `savehist-uninstall'."
152 (cancel-timer savehist-timer)) 261 (cancel-timer savehist-timer))
153 (setq savehist-timer nil))) 262 (setq savehist-timer nil)))
154 263
155;;;###autoload
156(defun savehist-load (&optional no-install)
157 "Load the minibuffer histories from `savehist-file'.
158Unless NO-INSTALL is present and non-nil, the function will also install
159`savehist-autosave' in `kill-emacs-hook' and on a timer, ensuring that
160history is saved before leaving Emacs.
161
162This function should be normally used from your Emacs init file. Since
163it removes your current minibuffer histories, it is unwise to call it at
164any other time."
165 (interactive "P")
166 ;; Don't set coding-system-for-read here. We rely on autodetection
167 ;; and the coding cookie to convey that information. That way, if
168 ;; the user changes the value of savehist-coding-system, we can
169 ;; still correctly load the old file.
170 (load savehist-file t (not (interactive-p)))
171 (unless no-install
172 (savehist-install)))
173
174;;;###autoload
175(defun savehist-save (&optional auto-save) 264(defun savehist-save (&optional auto-save)
176 "Save the values of minibuffer history variables. 265 "Save the values of minibuffer history variables.
177Unbound symbols referenced in `savehist-additional-variables' are ignored. 266Unbound symbols referenced in `savehist-additional-variables' are ignored.
@@ -182,21 +271,32 @@ If AUTO-SAVE is non-nil, compare the saved contents to the one last saved,
182 (insert 271 (insert
183 (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) 272 (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system)
184 ";; Minibuffer history file, automatically generated by `savehist'.\n\n") 273 ";; Minibuffer history file, automatically generated by `savehist'.\n\n")
274 (run-hooks 'savehist-save-hook)
185 (let ((print-length nil) 275 (let ((print-length nil)
186 (print-string-length nil) 276 (print-string-length nil)
187 (print-level nil) 277 (print-level nil)
188 (print-readably t) 278 (print-readably t)
189 (print-quoted t) 279 (print-quoted t))
190 (symbol-list (append 280 ;; Save the minibuffer histories, along with the value of
191 (and savehist-save-minibuffer-history 281 ;; savehist-minibuffer-history-variables itself.
192 (cons 'savehist-minibuffer-history-variables 282 (when savehist-save-minibuffer-history
193 savehist-minibuffer-history-variables)) 283 (prin1 `(setq savehist-minibuffer-history-variables
194 savehist-additional-variables))) 284 ',savehist-minibuffer-history-variables)
195 (dolist (sym symbol-list) 285 (current-buffer))
196 (when (boundp sym) 286 (insert ?\n)
197 (let ((value (savehist-process-for-saving (symbol-value sym)))) 287 (dolist (symbol savehist-minibuffer-history-variables)
198 (prin1 `(setq ,sym ',value) (current-buffer)) 288 (when (boundp symbol)
199 (insert ?\n))))) 289 (let ((value (savehist-trim-history (symbol-value symbol))))
290 (when value ; don't save empty histories
291 (prin1 `(setq ,symbol ',value) (current-buffer))
292 (insert ?\n))))))
293 ;; Save the additional variables.
294 (dolist (symbol savehist-additional-variables)
295 (when (boundp symbol)
296 (let ((value (symbol-value symbol)))
297 (when (savehist-printable value)
298 (prin1 `(setq ,symbol ',value) (current-buffer))
299 (insert ?\n))))))
200 ;; If autosaving, avoid writing if nothing has changed since the 300 ;; If autosaving, avoid writing if nothing has changed since the
201 ;; last write. 301 ;; last write.
202 (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) 302 (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion)))
@@ -210,57 +310,55 @@ If AUTO-SAVE is non-nil, compare the saved contents to the one last saved,
210 (coding-system-for-write savehist-coding-system)) 310 (coding-system-for-write savehist-coding-system))
211 (write-region (point-min) (point-max) savehist-file nil 311 (write-region (point-min) (point-max) savehist-file nil
212 (unless (interactive-p) 'quiet))) 312 (unless (interactive-p) 'quiet)))
213 (when savehist-modes 313 (when savehist-file-modes
214 (set-file-modes savehist-file savehist-modes)) 314 (set-file-modes savehist-file savehist-file-modes))
215 (setq savehist-last-checksum checksum))))) 315 (setq savehist-last-checksum checksum)))))
216 316
217(defun savehist-autosave () 317(defun savehist-autosave ()
218 "Save the minibuffer history if it has been modified since the last save." 318 "Save the minibuffer history if it has been modified since the last save.
219 (savehist-save t)) 319Does nothing if savehist-mode is off."
220 320 (when savehist-mode
221(defun savehist-process-for-saving (value) 321 (savehist-save t)))
222 ;; Process VALUE for saving to file. If it is a list, retain only 322
223 ;; the first `savehist-length' values and prune non-printable ones. 323(defun savehist-trim-history (value)
224 ;; If VALUE is not a list, return it as-is if it is printable and 324 ;; Retain only the first history-length items in VALUE. Only used
225 ;; nil otherwise. 325 ;; under XEmacs, which doesn't (yet) implement automatic trimming of
226 (cond 326 ;; history lists to history-length items.
227 ((listp value) 327 (if (and (featurep 'xemacs)
228 (when (and savehist-length (> (length value) savehist-length)) 328 (natnump history-length)
229 ;; This should be: (setq value (subseq value 0 savehist-length)) 329 (> (length value) history-length))
230 (setq value (copy-sequence value)) 330 ;; Equivalent to `(subseq value 0 history-length)', but doesn't
231 (setcdr (nthcdr savehist-length value) nil)) 331 ;; need cl-extra at run-time.
232 ;; And this should be (remove-if-not #'savehist-printable value) 332 (loop repeat history-length collect (pop value))
233 (delq nil (mapcar (lambda (x) (if (savehist-printable x) x)) value))) 333 value))
234 ((savehist-printable value) value)
235 (t nil)))
236 334
237(defun savehist-printable (value) 335(defun savehist-printable (value)
238 "Return non-nil if VALUE is printable." 336 "Return non-nil if VALUE is printable."
239 ;; Quick response for oft-encountered types known to be printable.
240 (cond 337 (cond
338 ;; Quick response for oft-encountered types known to be printable.
241 ((stringp value)) 339 ((stringp value))
242 ((numberp value)) 340 ((numberp value))
243 ((symbolp value)) 341 ((symbolp value))
244 (t 342 (t
245 ;; For others, check explicitly. 343 ;; For others, check explicitly.
246 (condition-case nil 344 (with-temp-buffer
247 (let ((print-readably t) 345 (condition-case nil
248 (print-level nil) 346 (let ((print-readably t) (print-level nil))
249 (chars ())) 347 ;; Print the value into a buffer...
250 ;; Print the value into a string... 348 (prin1 value (current-buffer))
251 (prin1 value (lambda (char) (push char chars)))
252 ;; ...and attempt to read it. 349 ;; ...and attempt to read it.
253 (read (apply #'string (nreverse chars))) 350 (read (point-min-marker))
254 ;; The attempt worked: the object is printable. 351 ;; The attempt worked: the object is printable.
255 t) 352 t)
256 ;; The attempt failed: the object is not printable. 353 ;; The attempt failed: the object is not printable.
257 (error nil))))) 354 (error nil))))))
258 355
259(defun savehist-minibuffer-hook () 356(defun savehist-minibuffer-hook ()
260 (add-to-list 'savehist-minibuffer-history-variables 357 (add-to-list 'savehist-minibuffer-history-variables
261 minibuffer-history-variable)) 358 minibuffer-history-variable))
262 359
263(provide 'savehist) 360(provide 'savehist)
264 361
265;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f 362;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f
363
266;;; savehist.el ends here 364;;; savehist.el ends here