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 | |
77 | ;; Viper stuff | |
78 | vip-ex-history vip-search-history | |
79 | vip-replace1-history vip-replace2-history | |
80 | vip-shell-history vip-search-history | |
81 | ||
82 | ;; XEmacs-specific: | |
83 | ;; Buffer-related commands | |
84 | buffer-history | |
85 | ;; Reads of variables and functions | |
86 | variable-history function-history | |
87 | ;; Extended commands | |
88 | read-command-history | |
89 | ||
90 | ;; Info, lookup, and bookmark historys | |
91 | Info-minibuffer-history | |
216ee1a4 | 92 | Info-search-history |
cb23c7c1 RS |
93 | Manual-page-minibuffer-history |
94 | ||
95 | ;; Emacs-specific: | |
96 | ;; Extended commands | |
97 | extended-command-history) | |
98 | "*List of symbols to be saved. | |
99 | Every symbol should refer to a variable. The variable will be saved | |
100 | only if it is bound and has a non-nil value. Thus it is safe to | |
101 | specify a superset of the variables a user is expected to want to | |
102 | save. | |
103 | ||
216ee1a4 SM |
104 | Default value contains minibuffer history variables used by Emacs, XEmacs, |
105 | and Viper (uh-oh). Note that, if you customize this variable, you | |
106 | can lose the benefit of future versions of Emacs adding new values to | |
107 | the list. Because of that it might be more useful to add values using | |
108 | `add-to-list'." | |
cb23c7c1 RS |
109 | :type '(repeat (symbol :tag "Variable")) |
110 | :group 'savehist) | |
111 | ||
112 | (defcustom savehist-file "~/.emacs-history" | |
113 | "*File name to save minibuffer history to. | |
114 | The minibuffer history is a series of Lisp expressions, which should be | |
115 | loaded using `savehist-load' from your .emacs. See `savehist-load' for | |
116 | more details." | |
117 | :type 'file | |
118 | :group 'savehist) | |
119 | ||
120 | (defcustom savehist-length 100 | |
121 | "*Maximum length of a minibuffer list. | |
122 | If set to nil, the length is unlimited." | |
123 | :type '(choice integer | |
124 | (const :tag "Unlimited" nil)) | |
125 | :group 'savehist) | |
126 | ||
216ee1a4 | 127 | (defcustom savehist-modes #o600 |
cb23c7c1 | 128 | "*Default permissions of the history file. |
216ee1a4 SM |
129 | This is decimal, not octal. The default is 384 (0600 in octal). |
130 | Set to nil to use the default permissions that Emacs uses, typically | |
131 | mandated by umask. The default is a bit more restrictive to protect | |
132 | the user's privacy." | |
cb23c7c1 RS |
133 | :type 'integer |
134 | :group 'savehist) | |
135 | ||
216ee1a4 SM |
136 | (defcustom savehist-autosave-interval (* 5 60) |
137 | "*The interval during which savehist should autosave the history buffer." | |
138 | :type 'integer | |
139 | :group 'savehist) | |
140 | ||
3930b7e4 | 141 | (defvar savehist-coding-system (if (coding-system-p 'utf-8) 'utf-8 'iso-2022-8) |
216ee1a4 SM |
142 | "The coding system savehist uses for saving the minibuffer history. |
143 | Changing this value while Emacs is running is supported, but considered | |
144 | unwise, unless you know what you are doing.") | |
145 | ||
146 | ;; Internal variables. | |
147 | ||
148 | (defvar savehist-timer nil) | |
149 | ||
150 | (defvar savehist-last-checksum nil) | |
151 | ||
3930b7e4 SM |
152 | (defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) |
153 | ;; FIXME: Why not use savehist-coding-system? | |
154 | "Coding system without conversion, only used for calculating checksums.") | |
cb23c7c1 RS |
155 | \f |
156 | ;; Functions | |
157 | ||
158 | ;;;###autoload | |
159 | (defun savehist-load (&optional no-hook) | |
160 | "Load the minibuffer histories from `savehist-file'. | |
161 | Unless NO-HOOK is specified, the function will also add the save function | |
216ee1a4 SM |
162 | to `kill-emacs-hook' and on a timer, ensuring that the minibuffer contents |
163 | will be saved before leaving Emacs. | |
cb23c7c1 RS |
164 | |
165 | This function should be normally used from your Emacs init file. Since it | |
166 | removes your current minibuffer histories, it is unwise to call it at any | |
167 | other time." | |
168 | (interactive "P") | |
169 | (unless no-hook | |
216ee1a4 SM |
170 | (add-hook 'kill-emacs-hook 'savehist-autosave) |
171 | ;; Install an invocation of savehist-autosave on a timer. This | |
172 | ;; should not cause a noticeable delay -- savehist-autosave | |
173 | ;; executes in under 5 ms on my system. | |
174 | (unless savehist-timer | |
175 | (setq savehist-timer | |
3930b7e4 | 176 | (if (fboundp 'start-itimer) |
216ee1a4 SM |
177 | (start-itimer |
178 | "savehist" 'savehist-autosave savehist-autosave-interval | |
179 | savehist-autosave-interval) | |
3930b7e4 SM |
180 | (run-with-idle-timer savehist-autosave-interval savehist-autosave-interval |
181 | 'savehist-autosave))))) | |
216ee1a4 SM |
182 | ;; Don't set coding-system-for-read here. We rely on autodetection |
183 | ;; and the coding cookie to convey that information. That way, if | |
184 | ;; the user changes the value of savehist-coding-system, we can | |
185 | ;; still correctly load the old file. | |
186 | (load savehist-file t (not (interactive-p)))) | |
cb23c7c1 RS |
187 | |
188 | ;;;###autoload | |
216ee1a4 | 189 | (defun savehist-save (&optional auto-save) |
cb23c7c1 | 190 | "Save the histories from `savehist-history-variables' to `savehist-file'. |
216ee1a4 SM |
191 | Unbound symbols referenced in `savehist-history-variables' are ignored. |
192 | If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, | |
193 | and don't save the buffer if they are the same." | |
cb23c7c1 | 194 | (interactive) |
216ee1a4 SM |
195 | (with-temp-buffer |
196 | (insert | |
197 | (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) | |
198 | ";; Minibuffer history file, automatically generated by `savehist'.\n\n") | |
199 | (let ((print-length nil) | |
200 | (print-string-length nil) | |
201 | (print-level nil) | |
202 | (print-readably t) | |
203 | (print-quoted t)) | |
204 | (dolist (sym savehist-history-variables) | |
205 | (when (boundp sym) | |
206 | (let ((value (savehist-process-for-saving (symbol-value sym)))) | |
207 | (prin1 `(setq ,sym ',value) (current-buffer)) | |
208 | (insert ?\n))))) | |
209 | ;; If autosaving, avoid writing if nothing has changed since the | |
210 | ;; last write. | |
211 | (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) | |
212 | (unless (and auto-save (equal checksum savehist-last-checksum)) | |
213 | ;; Set file-precious-flag when saving the buffer because we | |
214 | ;; don't want a half-finished write ruining the entire | |
215 | ;; history. (Remember that this is run from a timer and from | |
216 | ;; kill-emacs-hook.) | |
217 | (let ((file-precious-flag t) | |
218 | (coding-system-for-write savehist-coding-system)) | |
219 | (write-region (point-min) (point-max) savehist-file nil | |
220 | (unless (interactive-p) 'quiet))) | |
221 | (when savehist-modes | |
222 | (set-file-modes savehist-file savehist-modes)) | |
223 | (setq savehist-last-checksum checksum))))) | |
224 | ||
225 | (defun savehist-autosave () | |
226 | "Save the minibuffer history if it has been modified since the last save." | |
227 | (savehist-save t)) | |
228 | ||
229 | (defun savehist-process-for-saving (value) | |
230 | ;; Process VALUE for saving to file. If it is a list, retain only | |
231 | ;; the first `savehist-length' values and prune non-printable ones. | |
232 | ;; If VALUE is not a list, return it as-is if it is printable and | |
233 | ;; nil otherwise. | |
234 | (cond | |
235 | ((listp value) | |
236 | (when (and savehist-length (> (length value) savehist-length)) | |
3930b7e4 SM |
237 | (setq value (copy-sequence value)) |
238 | (setcdr (nthcdr savehist-length value) nil)) | |
239 | (delq nil (mapcar (lambda (x) (if (savehist-printable x) x)) value))) | |
216ee1a4 SM |
240 | ((savehist-printable value) value) |
241 | (t nil))) | |
242 | ||
243 | (defun savehist-printable (value) | |
3930b7e4 | 244 | "Return non-nil if VALUE is printable." |
216ee1a4 SM |
245 | ;; Quick response for oft-encountered types known to be printable. |
246 | (cond | |
247 | ((stringp value)) | |
248 | ((numberp value)) | |
249 | ((symbolp value)) | |
250 | (t | |
251 | ;; For others, check explicitly. | |
252 | (condition-case nil | |
253 | (let ((print-readably t) | |
254 | (print-level nil) | |
255 | (chars ())) | |
256 | ;; Print the value into a string... | |
257 | (prin1 value (lambda (char) (push char chars))) | |
258 | ;; ...and attempt to read it. | |
259 | (read (apply #'string (nreverse chars))) | |
260 | ;; The attempt worked: the object is printable. | |
261 | t) | |
262 | ;; The attempt failed: the object is not printable. | |
263 | (error nil))))) | |
cb23c7c1 RS |
264 | |
265 | (provide 'savehist) | |
266 | ||
267 | ;;; savehist.el ends here |