Commit | Line | Data |
---|---|---|
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 | 47 | (require 'custom) |
216ee1a4 | 48 | |
cb23c7c1 RS |
49 | ;; User variables |
50 | ||
51 | (defgroup savehist nil | |
52 | "Save minibuffer history." | |
53 | :group 'minibuffer) | |
54 | ||
cb23c7c1 RS |
55 | (defcustom savehist-history-variables |
56 | '( | |
57 | ;; Catch-all minibuffer history | |
58 | minibuffer-history | |
59 | ;; File-oriented commands | |
60 | file-name-history | |
61 | ;; Regexp-related reads | |
62 | regexp-history | |
63 | ;; Searches in minibuffer (via `M-r' and such) | |
64 | minibuffer-history-search-history | |
65 | ;; Query replace | |
66 | query-replace-history | |
67 | ;; eval-expression (`M-:') | |
68 | read-expression-history | |
69 | ;; shell-command (`M-!') | |
70 | shell-command-history | |
71 | ;; compile | |
72 | compile-history | |
73 | ;; find-tag (`M-.') | |
74 | find-tag-history | |
75 | ;; grep | |
76 | grep-history | |
02c583a4 | 77 | grep-find-history |
cb23c7c1 RS |
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. | |
100 | Every symbol should refer to a variable. The variable will be saved | |
101 | only if it is bound and has a non-nil value. Thus it is safe to | |
102 | specify a superset of the variables a user is expected to want to | |
103 | save. | |
104 | ||
216ee1a4 SM |
105 | Default value contains minibuffer history variables used by Emacs, XEmacs, |
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'." | |
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. | |
115 | The minibuffer history is a series of Lisp expressions, which should be | |
116 | loaded using `savehist-load' from your .emacs. See `savehist-load' for | |
117 | more details." | |
118 | :type 'file | |
119 | :group 'savehist) | |
120 | ||
121 | (defcustom savehist-length 100 | |
122 | "*Maximum length of a minibuffer list. | |
123 | If 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 |
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." | |
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 | ||
e27e4e7a SM |
142 | (defvar savehist-coding-system |
143 | ;; UTF-8 is usually preferable to ISO-2022-8 when available, but under | |
144 | ;; XEmacs, UTF-8 is provided by external packages, and may not always be | |
145 | ;; available, so even if it currently is available, we prefer not to | |
146 | ;; use is. | |
147 | (if (featurep 'xemacs) 'iso-2022-8 'utf-8) | |
216ee1a4 SM |
148 | "The coding system savehist uses for saving the minibuffer history. |
149 | Changing this value while Emacs is running is supported, but considered | |
150 | unwise, unless you know what you are doing.") | |
151 | ||
152 | ;; Internal variables. | |
153 | ||
154 | (defvar savehist-timer nil) | |
155 | ||
156 | (defvar savehist-last-checksum nil) | |
157 | ||
3930b7e4 SM |
158 | (defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) |
159 | ;; FIXME: Why not use savehist-coding-system? | |
160 | "Coding system without conversion, only used for calculating checksums.") | |
cb23c7c1 RS |
161 | \f |
162 | ;; Functions | |
163 | ||
164 | ;;;###autoload | |
165 | (defun savehist-load (&optional no-hook) | |
166 | "Load the minibuffer histories from `savehist-file'. | |
167 | Unless NO-HOOK is specified, the function will also add the save function | |
216ee1a4 SM |
168 | to `kill-emacs-hook' and on a timer, ensuring that the minibuffer contents |
169 | will be saved before leaving Emacs. | |
cb23c7c1 RS |
170 | |
171 | This function should be normally used from your Emacs init file. Since it | |
172 | removes your current minibuffer histories, it is unwise to call it at any | |
173 | other time." | |
174 | (interactive "P") | |
175 | (unless no-hook | |
216ee1a4 SM |
176 | (add-hook 'kill-emacs-hook 'savehist-autosave) |
177 | ;; Install an invocation of savehist-autosave on a timer. This | |
178 | ;; should not cause a noticeable delay -- savehist-autosave | |
179 | ;; executes in under 5 ms on my system. | |
180 | (unless savehist-timer | |
181 | (setq savehist-timer | |
67f05bf6 | 182 | (if (featurep 'xemacs) |
216ee1a4 SM |
183 | (start-itimer |
184 | "savehist" 'savehist-autosave savehist-autosave-interval | |
185 | savehist-autosave-interval) | |
3930b7e4 SM |
186 | (run-with-idle-timer savehist-autosave-interval savehist-autosave-interval |
187 | 'savehist-autosave))))) | |
216ee1a4 SM |
188 | ;; Don't set coding-system-for-read here. We rely on autodetection |
189 | ;; and the coding cookie to convey that information. That way, if | |
190 | ;; the user changes the value of savehist-coding-system, we can | |
191 | ;; still correctly load the old file. | |
192 | (load savehist-file t (not (interactive-p)))) | |
cb23c7c1 RS |
193 | |
194 | ;;;###autoload | |
216ee1a4 | 195 | (defun savehist-save (&optional auto-save) |
cb23c7c1 | 196 | "Save the histories from `savehist-history-variables' to `savehist-file'. |
216ee1a4 SM |
197 | Unbound symbols referenced in `savehist-history-variables' are ignored. |
198 | If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, | |
199 | and don't save the buffer if they are the same." | |
cb23c7c1 | 200 | (interactive) |
216ee1a4 SM |
201 | (with-temp-buffer |
202 | (insert | |
203 | (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) | |
204 | ";; Minibuffer history file, automatically generated by `savehist'.\n\n") | |
205 | (let ((print-length nil) | |
206 | (print-string-length nil) | |
207 | (print-level nil) | |
208 | (print-readably t) | |
209 | (print-quoted t)) | |
210 | (dolist (sym savehist-history-variables) | |
211 | (when (boundp sym) | |
212 | (let ((value (savehist-process-for-saving (symbol-value sym)))) | |
213 | (prin1 `(setq ,sym ',value) (current-buffer)) | |
214 | (insert ?\n))))) | |
215 | ;; If autosaving, avoid writing if nothing has changed since the | |
216 | ;; last write. | |
217 | (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) | |
218 | (unless (and auto-save (equal checksum savehist-last-checksum)) | |
219 | ;; Set file-precious-flag when saving the buffer because we | |
220 | ;; don't want a half-finished write ruining the entire | |
221 | ;; history. (Remember that this is run from a timer and from | |
222 | ;; kill-emacs-hook.) | |
223 | (let ((file-precious-flag t) | |
224 | (coding-system-for-write savehist-coding-system)) | |
225 | (write-region (point-min) (point-max) savehist-file nil | |
226 | (unless (interactive-p) 'quiet))) | |
227 | (when savehist-modes | |
228 | (set-file-modes savehist-file savehist-modes)) | |
229 | (setq savehist-last-checksum checksum))))) | |
230 | ||
231 | (defun savehist-autosave () | |
232 | "Save the minibuffer history if it has been modified since the last save." | |
233 | (savehist-save t)) | |
234 | ||
235 | (defun savehist-process-for-saving (value) | |
236 | ;; Process VALUE for saving to file. If it is a list, retain only | |
237 | ;; the first `savehist-length' values and prune non-printable ones. | |
238 | ;; If VALUE is not a list, return it as-is if it is printable and | |
239 | ;; nil otherwise. | |
240 | (cond | |
241 | ((listp value) | |
242 | (when (and savehist-length (> (length value) savehist-length)) | |
67f05bf6 | 243 | ;; This should be: (setq value (subseq value 0 savehist-length)) |
3930b7e4 SM |
244 | (setq value (copy-sequence value)) |
245 | (setcdr (nthcdr savehist-length value) nil)) | |
67f05bf6 | 246 | ;; And this should be (remove-if-not #'savehist-printable value) |
3930b7e4 | 247 | (delq nil (mapcar (lambda (x) (if (savehist-printable x) x)) value))) |
216ee1a4 SM |
248 | ((savehist-printable value) value) |
249 | (t nil))) | |
250 | ||
251 | (defun savehist-printable (value) | |
3930b7e4 | 252 | "Return non-nil if VALUE is printable." |
216ee1a4 SM |
253 | ;; Quick response for oft-encountered types known to be printable. |
254 | (cond | |
255 | ((stringp value)) | |
256 | ((numberp value)) | |
257 | ((symbolp value)) | |
258 | (t | |
259 | ;; For others, check explicitly. | |
260 | (condition-case nil | |
261 | (let ((print-readably t) | |
262 | (print-level nil) | |
263 | (chars ())) | |
264 | ;; Print the value into a string... | |
265 | (prin1 value (lambda (char) (push char chars))) | |
266 | ;; ...and attempt to read it. | |
267 | (read (apply #'string (nreverse chars))) | |
268 | ;; The attempt worked: the object is printable. | |
269 | t) | |
270 | ;; The attempt failed: the object is not printable. | |
271 | (error nil))))) | |
cb23c7c1 RS |
272 | |
273 | (provide 'savehist) | |
274 | ||
16b52b61 | 275 | ;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f |
cb23c7c1 | 276 | ;;; savehist.el ends here |