Mercurial > emacs
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 |