4 |
|
|
5 |
;; Author: Hrvoje Niksic <hniksic@xemacs.org> |
;; Author: Hrvoje Niksic <hniksic@xemacs.org> |
6 |
;; Keywords: minibuffer |
;; Keywords: minibuffer |
7 |
;; Version: 9 |
;; Version: 19 |
8 |
|
|
9 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
10 |
|
|
32 |
;; variables may be specified by customizing |
;; variables may be specified by customizing |
33 |
;; `savehist-additional-variables'. |
;; `savehist-additional-variables'. |
34 |
|
|
35 |
;; To use savehist, put the following to `~/.emacs': |
;; To use savehist, turn on savehist-mode by putting the following in |
36 |
|
;; `~/.emacs': |
37 |
;; |
;; |
38 |
;; (require 'savehist) |
;; (savehist-mode 1) |
39 |
;; (savehist-load) |
;; |
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'. |
44 |
|
|
45 |
;; If you are using a version of Emacs that does not ship with this |
;; 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 |
;; package, be sure to have `savehist.el' in a directory that is in |
58 |
"Save minibuffer history." |
"Save minibuffer history." |
59 |
:group 'minibuffer) |
:group 'minibuffer) |
60 |
|
|
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 |
67 |
|
:set (lambda (symbol value) (savehist-mode (or value 0))) |
68 |
|
:initialize 'custom-initialize-default |
69 |
|
:require 'savehist |
70 |
|
:group 'savehist) |
71 |
|
|
72 |
(defcustom savehist-save-minibuffer-history t |
(defcustom savehist-save-minibuffer-history t |
73 |
"If non-nil, save all recorded minibuffer histories." |
"*If non-nil, save all recorded minibuffer histories. |
74 |
|
If you want to save only specific histories, use `savehist-save-hook' to |
75 |
|
modify the value of `savehist-minibuffer-history-variables'." |
76 |
:type 'boolean |
:type 'boolean |
77 |
:group 'savehist) |
:group 'savehist) |
78 |
|
|
79 |
(defcustom savehist-additional-variables () |
(defcustom savehist-additional-variables () |
80 |
"List of additional variables to save. |
"*List of additional variables to save. |
81 |
Each element is a symbol whose value will be persisted across Emacs |
Each element is a symbol whose value will be persisted across Emacs |
82 |
sessions that use savehist. The contents of variables should be |
sessions that use savehist. The contents of variables should be |
83 |
printable with the Lisp printer. If the variable's value is a list, |
printable with the Lisp printer. You don't need to add minibuffer |
84 |
it will be trimmed to `savehist-length' elements. |
history variables to this list, all minibuffer histories will be |
85 |
|
saved automatically as long as `savehist-save-minibuffer-history' is |
86 |
You don't need to add minibuffer history variables to this list. All |
non-nil. |
87 |
minibuffer histories will be saved automatically." |
|
88 |
:type '(repeat (symbol :tag "Variable")) |
User options should be saved with the customize interface. This |
89 |
|
list is useful for saving automatically updated variables that are not |
90 |
|
minibuffer histories, such as `compile-command' or `kill-ring'." |
91 |
|
:type '(repeat variable) |
92 |
:group 'savehist) |
:group 'savehist) |
93 |
|
|
94 |
(defcustom savehist-file "~/.emacs-history" |
(defcustom savehist-file |
95 |
"File name to save minibuffer history to. |
(cond |
96 |
The minibuffer history is a series of Lisp expressions, which should be |
;; Backward compatibility with previous versions of savehist. |
97 |
loaded using `savehist-load' from your .emacs. See `savehist-load' for |
((file-exists-p "~/.emacs-history") "~/.emacs-history") |
98 |
more details." |
((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. |
105 |
|
The minibuffer history is a series of Lisp expressions loaded |
106 |
|
automatically when `savehist-mode' is turned on. See `savehist-mode' |
107 |
|
for more details. |
108 |
|
|
109 |
|
If you want your minibuffer history shared between Emacs and XEmacs, |
110 |
|
customize this value and make sure that `savehist-coding-system' is |
111 |
|
set to a coding system that exists in both emacsen." |
112 |
:type 'file |
:type 'file |
113 |
:group 'savehist) |
:group 'savehist) |
114 |
|
|
115 |
(defcustom savehist-length 100 |
(defcustom savehist-file-modes #o600 |
116 |
"Maximum length of a minibuffer list. |
"*Default permissions of the history file. |
|
Minibuffer histories with more entries are trimmed when saved, the older |
|
|
entries being removed first. If set to nil, the length is unlimited." |
|
|
:type '(choice integer |
|
|
(const :tag "Unlimited" nil)) |
|
|
:group 'savehist) |
|
|
|
|
|
(defcustom savehist-modes #o600 |
|
|
"Default permissions of the history file. |
|
117 |
This is decimal, not octal. The default is 384 (0600 in octal). |
This is decimal, not octal. The default is 384 (0600 in octal). |
118 |
Set to nil to use the default permissions that Emacs uses, typically |
Set to nil to use the default permissions that Emacs uses, typically |
119 |
mandated by umask. The default is a bit more restrictive to protect |
mandated by umask. The default is a bit more restrictive to protect |
122 |
:group 'savehist) |
:group 'savehist) |
123 |
|
|
124 |
(defcustom savehist-autosave-interval (* 5 60) |
(defcustom savehist-autosave-interval (* 5 60) |
125 |
"The interval during which savehist should autosave the history buffer." |
"*The interval between autosaves of minibuffer history. |
126 |
|
If set to nil, disables timer-based autosaving." |
127 |
:type 'integer |
:type 'integer |
128 |
:group 'savehist) |
:group 'savehist) |
129 |
|
|
130 |
(defvar savehist-coding-system |
(defcustom savehist-save-hook nil |
131 |
;; UTF-8 is usually preferable to ISO-2022-8 when available, but under |
"Hook called by savehist-save before saving the variables. |
132 |
;; XEmacs, UTF-8 is provided by external packages, and may not always be |
You can use this hook to influence choice and content of variables to |
133 |
;; available, so even if it currently is available, we prefer not to |
save." |
134 |
;; use is. |
:type 'hook) |
135 |
(if (featurep 'xemacs) 'iso-2022-8 'utf-8) |
|
136 |
|
(defvar savehist-coding-system (if (featurep 'xemacs) 'iso-2022-8 'utf-8) |
137 |
"The coding system savehist uses for saving the minibuffer history. |
"The coding system savehist uses for saving the minibuffer history. |
138 |
Changing this value while Emacs is running is supported, but considered |
Changing this value while Emacs is running is supported, but considered |
139 |
unwise, unless you know what you are doing.") |
unwise, unless you know what you are doing.") |
144 |
|
|
145 |
(defvar savehist-last-checksum nil) |
(defvar savehist-last-checksum nil) |
146 |
|
|
147 |
(defvar savehist-minibuffer-history-variables nil) |
(defvar savehist-minibuffer-history-variables nil |
148 |
|
"List of minibuffer histories. |
149 |
|
The contents of this variable is built while Emacs is running, and saved |
150 |
|
along with minibuffer history. You can change its value off |
151 |
|
`savehist-save-hook' to influence which variables are saved.") |
152 |
|
|
153 |
|
;; Coding system without any conversion, used for calculating an |
154 |
|
;; internal checksum. Should be as fast as possible, ideally simply |
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 |
(defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) |
(eval-when-compile |
163 |
"Coding system without conversion, only used for calculating checksums. |
(when (featurep 'xemacs) |
164 |
It should be as discriminating as `savehist-coding-system' but faster.") |
;; Must declare this under XEmacs, which doesn't have built-in |
165 |
|
;; minibuffer history truncation. |
166 |
|
(defvar history-length 100))) |
167 |
|
|
168 |
;; Functions. |
;; Functions. |
169 |
|
|
170 |
|
;;;###autoload |
171 |
|
(defun savehist-mode (arg) |
172 |
|
"Toggle savehist-mode. |
173 |
|
Positive ARG turns on `savehist-mode'. When on, savehist-mode causes |
174 |
|
minibuffer history to be saved periodically and when exiting Emacs. |
175 |
|
When turned on for the first time in an Emacs session, it causes the |
176 |
|
previous minibuffer history to be loaded from `savehist-file'. |
177 |
|
|
178 |
|
This mode should normally be turned on from your Emacs init file. |
179 |
|
Calling it at any other time replaces your current minibuffer histories, |
180 |
|
which 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. |
209 |
|
Don't call this from new code, use (savehist-mode 1) instead. |
210 |
|
|
211 |
|
This function loads the variables stored in `savehist-file' and turns on |
212 |
|
savehist-mode. If savehist-file is in the old format that doesn't record |
213 |
|
the value of `savehist-minibuffer-history-variables', that value is |
214 |
|
deducted 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 |
|
|
233 |
(defun savehist-install () |
(defun savehist-install () |
234 |
"Hook savehist into Emacs. |
"Hook savehist into Emacs. |
235 |
This will install `savehist-autosave' in `kill-emacs-hook' and on a timer. |
Normally invoked by calling `savehist-mode' to set the minor mode. |
236 |
To undo this, call `savehist-uninstall'." |
Installs `savehist-autosave' in `kill-emacs-hook' and on a timer. To |
237 |
|
undo this, call `savehist-uninstall'." |
238 |
(add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
(add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
239 |
(add-hook 'kill-emacs-hook 'savehist-autosave) |
(add-hook 'kill-emacs-hook 'savehist-autosave) |
240 |
;; Install an invocation of savehist-autosave on a timer. This |
;; Install an invocation of savehist-autosave on a timer. This |
241 |
;; should not cause noticeable delays for users -- savehist-autosave |
;; should not cause noticeable delays for users -- savehist-autosave |
242 |
;; executes in under 5 ms on my system. |
;; executes in under 5 ms on my system. |
243 |
(unless savehist-timer |
(when (and savehist-autosave-interval |
244 |
|
(null savehist-timer)) |
245 |
(setq savehist-timer |
(setq savehist-timer |
246 |
(if (featurep 'xemacs) |
(if (featurep 'xemacs) |
247 |
(start-itimer |
(start-itimer |
248 |
"savehist" 'savehist-autosave savehist-autosave-interval |
"savehist" 'savehist-autosave savehist-autosave-interval |
249 |
savehist-autosave-interval) |
savehist-autosave-interval) |
250 |
(run-with-timer savehist-autosave-interval savehist-autosave-interval |
(run-with-timer savehist-autosave-interval |
251 |
'savehist-autosave))))) |
savehist-autosave-interval 'savehist-autosave))))) |
252 |
|
|
253 |
(defun savehist-uninstall () |
(defun savehist-uninstall () |
254 |
"Undo installing savehist." |
"Undo installing savehist. |
255 |
|
Normally invoked by calling `savehist-mode' to unset the minor mode." |
256 |
(remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
(remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
257 |
(remove-hook 'kill-emacs-hook 'savehist-autosave) |
(remove-hook 'kill-emacs-hook 'savehist-autosave) |
258 |
(when savehist-timer |
(when savehist-timer |
261 |
(cancel-timer savehist-timer)) |
(cancel-timer savehist-timer)) |
262 |
(setq savehist-timer nil))) |
(setq savehist-timer nil))) |
263 |
|
|
|
;;;###autoload |
|
|
(defun savehist-load (&optional no-install) |
|
|
"Load the minibuffer histories from `savehist-file'. |
|
|
Unless NO-INSTALL is present and non-nil, the function will also install |
|
|
`savehist-autosave' in `kill-emacs-hook' and on a timer, ensuring that |
|
|
history is saved before leaving Emacs. |
|
|
|
|
|
This function should be normally used from your Emacs init file. Since |
|
|
it removes your current minibuffer histories, it is unwise to call it at |
|
|
any other time." |
|
|
(interactive "P") |
|
|
;; Don't set coding-system-for-read here. We rely on autodetection |
|
|
;; and the coding cookie to convey that information. That way, if |
|
|
;; the user changes the value of savehist-coding-system, we can |
|
|
;; still correctly load the old file. |
|
|
(load savehist-file t (not (interactive-p))) |
|
|
(unless no-install |
|
|
(savehist-install))) |
|
|
|
|
|
;;;###autoload |
|
264 |
(defun savehist-save (&optional auto-save) |
(defun savehist-save (&optional auto-save) |
265 |
"Save the values of minibuffer history variables. |
"Save the values of minibuffer history variables. |
266 |
Unbound symbols referenced in `savehist-additional-variables' are ignored. |
Unbound symbols referenced in `savehist-additional-variables' are ignored. |
271 |
(insert |
(insert |
272 |
(format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) |
(format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) |
273 |
";; Minibuffer history file, automatically generated by `savehist'.\n\n") |
";; Minibuffer history file, automatically generated by `savehist'.\n\n") |
274 |
|
(run-hooks 'savehist-save-hook) |
275 |
(let ((print-length nil) |
(let ((print-length nil) |
276 |
(print-string-length nil) |
(print-string-length nil) |
277 |
(print-level nil) |
(print-level nil) |
278 |
(print-readably t) |
(print-readably t) |
279 |
(print-quoted t) |
(print-quoted t)) |
280 |
(symbol-list (append |
;; Save the minibuffer histories, along with the value of |
281 |
(and savehist-save-minibuffer-history |
;; savehist-minibuffer-history-variables itself. |
282 |
(cons 'savehist-minibuffer-history-variables |
(when savehist-save-minibuffer-history |
283 |
savehist-minibuffer-history-variables)) |
(prin1 `(setq savehist-minibuffer-history-variables |
284 |
savehist-additional-variables))) |
',savehist-minibuffer-history-variables) |
285 |
(dolist (sym symbol-list) |
(current-buffer)) |
286 |
(when (boundp sym) |
(insert ?\n) |
287 |
(let ((value (savehist-process-for-saving (symbol-value sym)))) |
(dolist (symbol savehist-minibuffer-history-variables) |
288 |
(prin1 `(setq ,sym ',value) (current-buffer)) |
(when (boundp symbol) |
289 |
(insert ?\n))))) |
(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)))))) |
300 |
;; If autosaving, avoid writing if nothing has changed since the |
;; If autosaving, avoid writing if nothing has changed since the |
301 |
;; last write. |
;; last write. |
302 |
(let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) |
(let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) |
310 |
(coding-system-for-write savehist-coding-system)) |
(coding-system-for-write savehist-coding-system)) |
311 |
(write-region (point-min) (point-max) savehist-file nil |
(write-region (point-min) (point-max) savehist-file nil |
312 |
(unless (interactive-p) 'quiet))) |
(unless (interactive-p) 'quiet))) |
313 |
(when savehist-modes |
(when savehist-file-modes |
314 |
(set-file-modes savehist-file savehist-modes)) |
(set-file-modes savehist-file savehist-file-modes)) |
315 |
(setq savehist-last-checksum checksum))))) |
(setq savehist-last-checksum checksum))))) |
316 |
|
|
317 |
(defun savehist-autosave () |
(defun savehist-autosave () |
318 |
"Save the minibuffer history if it has been modified since the last save." |
"Save the minibuffer history if it has been modified since the last save. |
319 |
(savehist-save t)) |
Does nothing if savehist-mode is off." |
320 |
|
(when savehist-mode |
321 |
(defun savehist-process-for-saving (value) |
(savehist-save t))) |
322 |
;; Process VALUE for saving to file. If it is a list, retain only |
|
323 |
;; the first `savehist-length' values and prune non-printable ones. |
(defun savehist-trim-history (value) |
324 |
;; If VALUE is not a list, return it as-is if it is printable and |
;; Retain only the first history-length items in VALUE. Only used |
325 |
;; nil otherwise. |
;; under XEmacs, which doesn't (yet) implement automatic trimming of |
326 |
(cond |
;; history lists to history-length items. |
327 |
((listp value) |
(if (and (featurep 'xemacs) |
328 |
(when (and savehist-length (> (length value) savehist-length)) |
(natnump history-length) |
329 |
;; This should be: (setq value (subseq value 0 savehist-length)) |
(> (length value) history-length)) |
330 |
(setq value (copy-sequence value)) |
;; Equivalent to `(subseq value 0 history-length)', but doesn't |
331 |
(setcdr (nthcdr savehist-length value) nil)) |
;; need cl-extra at run-time. |
332 |
;; And this should be (remove-if-not #'savehist-printable value) |
(loop repeat history-length collect (pop value)) |
333 |
(delq nil (mapcar (lambda (x) (if (savehist-printable x) x)) value))) |
value)) |
|
((savehist-printable value) value) |
|
|
(t nil))) |
|
334 |
|
|
335 |
(defun savehist-printable (value) |
(defun savehist-printable (value) |
336 |
"Return non-nil if VALUE is printable." |
"Return non-nil if VALUE is printable." |
|
;; Quick response for oft-encountered types known to be printable. |
|
337 |
(cond |
(cond |
338 |
|
;; Quick response for oft-encountered types known to be printable. |
339 |
((stringp value)) |
((stringp value)) |
340 |
((numberp value)) |
((numberp value)) |
341 |
((symbolp value)) |
((symbolp value)) |
342 |
(t |
(t |
343 |
;; For others, check explicitly. |
;; For others, check explicitly. |
344 |
(condition-case nil |
(with-temp-buffer |
345 |
(let ((print-readably t) |
(condition-case nil |
346 |
(print-level nil) |
(let ((print-readably t) (print-level nil)) |
347 |
(chars ())) |
;; Print the value into a buffer... |
348 |
;; Print the value into a string... |
(prin1 value (current-buffer)) |
|
(prin1 value (lambda (char) (push char chars))) |
|
349 |
;; ...and attempt to read it. |
;; ...and attempt to read it. |
350 |
(read (apply #'string (nreverse chars))) |
(read (point-min-marker)) |
351 |
;; The attempt worked: the object is printable. |
;; The attempt worked: the object is printable. |
352 |
t) |
t) |
353 |
;; The attempt failed: the object is not printable. |
;; The attempt failed: the object is not printable. |
354 |
(error nil))))) |
(error nil)))))) |
355 |
|
|
356 |
(defun savehist-minibuffer-hook () |
(defun savehist-minibuffer-hook () |
357 |
(add-to-list 'savehist-minibuffer-history-variables |
(add-to-list 'savehist-minibuffer-history-variables |
358 |
minibuffer-history-variable)) |
minibuffer-history-variable)) |
359 |
|
|
360 |
(provide 'savehist) |
(provide 'savehist) |
361 |
|
|
362 |
;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f |
;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f |
363 |
|
|
364 |
;;; savehist.el ends here |
;;; savehist.el ends here |