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 SM |
47 | (require 'custom) |
48 | (require 'cl) | |
49 | ||
cb23c7c1 RS |
50 | ;; User variables |
51 | ||
52 | (defgroup savehist nil | |
53 | "Save minibuffer history." | |
54 | :group 'minibuffer) | |
55 | ||
cb23c7c1 RS |
56 | (defcustom savehist-history-variables |
57 | '( | |
58 | ;; Catch-all minibuffer history | |
59 | minibuffer-history | |
60 | ;; File-oriented commands | |
61 | file-name-history | |
62 | ;; Regexp-related reads | |
63 | regexp-history | |
64 | ;; Searches in minibuffer (via `M-r' and such) | |
65 | minibuffer-history-search-history | |
66 | ;; Query replace | |
67 | query-replace-history | |
68 | ;; eval-expression (`M-:') | |
69 | read-expression-history | |
70 | ;; shell-command (`M-!') | |
71 | shell-command-history | |
72 | ;; compile | |
73 | compile-history | |
74 | ;; find-tag (`M-.') | |
75 | find-tag-history | |
76 | ;; grep | |
77 | grep-history | |
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 | ||
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)) | |
cb23c7c1 RS |
158 | \f |
159 | ;; Functions | |
160 | ||
161 | ;;;###autoload | |
162 | (defun savehist-load (&optional no-hook) | |
163 | "Load the minibuffer histories from `savehist-file'. | |
164 | Unless NO-HOOK is specified, the function will also add the save function | |
216ee1a4 SM |
165 | to `kill-emacs-hook' and on a timer, ensuring that the minibuffer contents |
166 | will be saved before leaving Emacs. | |
cb23c7c1 RS |
167 | |
168 | This function should be normally used from your Emacs init file. Since it | |
169 | removes your current minibuffer histories, it is unwise to call it at any | |
170 | other time." | |
171 | (interactive "P") | |
172 | (unless no-hook | |
216ee1a4 SM |
173 | (add-hook 'kill-emacs-hook 'savehist-autosave) |
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)))) | |
cb23c7c1 RS |
190 | |
191 | ;;;###autoload | |
216ee1a4 | 192 | (defun savehist-save (&optional auto-save) |
cb23c7c1 | 193 | "Save the histories from `savehist-history-variables' to `savehist-file'. |
216ee1a4 SM |
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." | |
cb23c7c1 | 197 | (interactive) |
216ee1a4 SM |
198 | (with-temp-buffer |
199 | (insert | |
200 | (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) | |
201 | ";; Minibuffer history file, automatically generated by `savehist'.\n\n") | |
202 | (let ((print-length nil) | |
203 | (print-string-length nil) | |
204 | (print-level nil) | |
205 | (print-readably t) | |
206 | (print-quoted t)) | |
207 | (dolist (sym savehist-history-variables) | |
208 | (when (boundp sym) | |
209 | (let ((value (savehist-process-for-saving (symbol-value sym)))) | |
210 | (prin1 `(setq ,sym ',value) (current-buffer)) | |
211 | (insert ?\n))))) | |
212 | ;; If autosaving, avoid writing if nothing has changed since the | |
213 | ;; last write. | |
214 | (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) | |
215 | (unless (and auto-save (equal checksum savehist-last-checksum)) | |
216 | ;; Set file-precious-flag when saving the buffer because we | |
217 | ;; don't want a half-finished write ruining the entire | |
218 | ;; history. (Remember that this is run from a timer and from | |
219 | ;; kill-emacs-hook.) | |
220 | (let ((file-precious-flag t) | |
221 | (coding-system-for-write savehist-coding-system)) | |
222 | (write-region (point-min) (point-max) savehist-file nil | |
223 | (unless (interactive-p) 'quiet))) | |
224 | (when savehist-modes | |
225 | (set-file-modes savehist-file savehist-modes)) | |
226 | (setq savehist-last-checksum checksum))))) | |
227 | ||
228 | (defun savehist-autosave () | |
229 | "Save the minibuffer history if it has been modified since the last save." | |
230 | (savehist-save t)) | |
231 | ||
232 | (defun savehist-process-for-saving (value) | |
233 | ;; Process VALUE for saving to file. If it is a list, retain only | |
234 | ;; the first `savehist-length' values and prune non-printable ones. | |
235 | ;; If VALUE is not a list, return it as-is if it is printable and | |
236 | ;; nil otherwise. | |
237 | (cond | |
238 | ((listp value) | |
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))))) | |
cb23c7c1 RS |
266 | |
267 | (provide 'savehist) | |
268 | ||
269 | ;;; savehist.el ends here |