| 1 | ;;; savehist.el --- Save minibuffer history. |
| 2 | |
| 3 | ;; Copyright (C) 1997, 2005, 2006, 2007 Free Software Foundation, Inc. |
| 4 | |
| 5 | ;; Author: Hrvoje Niksic <hniksic@xemacs.org> |
| 6 | ;; Keywords: minibuffer |
| 7 | ;; Version: 24 |
| 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 3, 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 | |
| 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 set up, it saves recorded minibuffer |
| 31 | ;; histories to a file (`~/.emacs-history' by default). Additional |
| 32 | ;; variables may be specified by customizing |
| 33 | ;; `savehist-additional-variables'. |
| 34 | |
| 35 | ;; To use savehist, turn on savehist-mode by putting the following in |
| 36 | ;; `~/.emacs': |
| 37 | ;; |
| 38 | ;; (savehist-mode 1) |
| 39 | ;; |
| 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-file'. |
| 44 | |
| 45 | ;; 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 |
| 47 | ;; your load-path, and to byte-compile it. |
| 48 | |
| 49 | ;;; Code: |
| 50 | |
| 51 | (require 'custom) |
| 52 | (eval-when-compile |
| 53 | (require 'cl)) |
| 54 | |
| 55 | ;; User variables |
| 56 | |
| 57 | (defgroup savehist nil |
| 58 | "Save minibuffer history." |
| 59 | :version "22.1" |
| 60 | :group 'minibuffer) |
| 61 | |
| 62 | ;;;###autoload |
| 63 | (defcustom savehist-mode nil |
| 64 | "Mode for automatic saving of minibuffer history. |
| 65 | Set this by calling the `savehist-mode' function or using the customize |
| 66 | interface." |
| 67 | :type 'boolean |
| 68 | :set (lambda (symbol value) (savehist-mode (or value 0))) |
| 69 | :initialize 'custom-initialize-default |
| 70 | :require 'savehist |
| 71 | :group 'savehist) |
| 72 | |
| 73 | (defcustom savehist-save-minibuffer-history t |
| 74 | "*If non-nil, save all recorded minibuffer histories. |
| 75 | If you want to save only specific histories, use `savehist-save-hook' to |
| 76 | modify the value of `savehist-minibuffer-history-variables'." |
| 77 | :type 'boolean |
| 78 | :group 'savehist) |
| 79 | |
| 80 | (defcustom savehist-additional-variables () |
| 81 | "*List of additional variables to save. |
| 82 | Each element is a symbol whose value will be persisted across Emacs |
| 83 | sessions that use savehist. The contents of variables should be |
| 84 | printable with the Lisp printer. You don't need to add minibuffer |
| 85 | history variables to this list, all minibuffer histories will be |
| 86 | saved automatically as long as `savehist-save-minibuffer-history' is |
| 87 | non-nil. |
| 88 | |
| 89 | User options should be saved with the customize interface. This |
| 90 | list is useful for saving automatically updated variables that are not |
| 91 | minibuffer histories, such as `compile-command' or `kill-ring'." |
| 92 | :type '(repeat variable) |
| 93 | :group 'savehist) |
| 94 | |
| 95 | (defcustom savehist-ignored-variables nil ;; '(command-history) |
| 96 | "*List of additional variables not to save." |
| 97 | :type '(repeat variable) |
| 98 | :group 'savehist) |
| 99 | |
| 100 | (defcustom savehist-file |
| 101 | (cond |
| 102 | ;; Backward compatibility with previous versions of savehist. |
| 103 | ((file-exists-p "~/.emacs-history") "~/.emacs-history") |
| 104 | ((and (not (featurep 'xemacs)) (file-directory-p "~/.emacs.d/")) |
| 105 | "~/.emacs.d/history") |
| 106 | ((and (featurep 'xemacs) (file-directory-p "~/.xemacs/")) |
| 107 | "~/.xemacs/history") |
| 108 | ;; For users without `~/.emacs.d/' or `~/.xemacs/'. |
| 109 | (t "~/.emacs-history")) |
| 110 | "*File name where minibuffer history is saved to and loaded from. |
| 111 | The minibuffer history is a series of Lisp expressions loaded |
| 112 | automatically when `savehist-mode' is turned on. See `savehist-mode' |
| 113 | for more details. |
| 114 | |
| 115 | If you want your minibuffer history shared between Emacs and XEmacs, |
| 116 | customize this value and make sure that `savehist-coding-system' is |
| 117 | set to a coding system that exists in both emacsen." |
| 118 | :type 'file |
| 119 | :group 'savehist) |
| 120 | |
| 121 | (defcustom savehist-file-modes #o600 |
| 122 | "*Default permissions of the history file. |
| 123 | This is decimal, not octal. The default is 384 (0600 in octal). |
| 124 | Set to nil to use the default permissions that Emacs uses, typically |
| 125 | mandated by umask. The default is a bit more restrictive to protect |
| 126 | the user's privacy." |
| 127 | :type 'integer |
| 128 | :group 'savehist) |
| 129 | |
| 130 | (defcustom savehist-autosave-interval (* 5 60) |
| 131 | "*The interval between autosaves of minibuffer history. |
| 132 | If set to nil, disables timer-based autosaving." |
| 133 | :type 'integer |
| 134 | :group 'savehist) |
| 135 | |
| 136 | (defcustom savehist-mode-hook nil |
| 137 | "Hook called when `savehist-mode' is turned on." |
| 138 | :type 'hook |
| 139 | :group 'savehist) |
| 140 | |
| 141 | (defcustom savehist-save-hook nil |
| 142 | "Hook called by `savehist-save' before saving the variables. |
| 143 | You can use this hook to influence choice and content of variables to |
| 144 | save." |
| 145 | :type 'hook |
| 146 | :group 'savehist) |
| 147 | |
| 148 | ;; This should be capable of representing characters used by Emacs. |
| 149 | ;; We prefer UTF-8 over ISO 2022 because it is well-known outside |
| 150 | ;; Mule. XEmacs prir to 21.5 had UTF-8 provided by an external |
| 151 | ;; package which may not be loaded, which is why we check for version. |
| 152 | (defvar savehist-coding-system (if (and (featurep 'xemacs) |
| 153 | (<= emacs-major-version 21) |
| 154 | (< emacs-minor-version 5)) |
| 155 | 'iso-2022-8 'utf-8) |
| 156 | "The coding system savehist uses for saving the minibuffer history. |
| 157 | Changing this value while Emacs is running is supported, but considered |
| 158 | unwise, unless you know what you are doing.") |
| 159 | |
| 160 | ;; Internal variables. |
| 161 | |
| 162 | (defvar savehist-timer nil) |
| 163 | |
| 164 | (defvar savehist-last-checksum nil) |
| 165 | |
| 166 | (defvar savehist-minibuffer-history-variables nil |
| 167 | "List of minibuffer histories. |
| 168 | The contents of this variable is built while Emacs is running, and saved |
| 169 | along with minibuffer history. You can change its value off |
| 170 | `savehist-save-hook' to influence which variables are saved.") |
| 171 | |
| 172 | (defconst savehist-no-conversion (if (featurep 'xemacs) 'binary 'no-conversion) |
| 173 | "Coding system without any conversion. |
| 174 | This is used for calculating an internal checksum. Should be as fast |
| 175 | as possible, ideally simply exposing the internal representation of |
| 176 | buffer text.") |
| 177 | |
| 178 | (defvar savehist-loaded nil |
| 179 | "Whether the history has already been loaded. |
| 180 | This prevents toggling `savehist-mode' from destroying existing |
| 181 | minibuffer history.") |
| 182 | |
| 183 | (when (featurep 'xemacs) |
| 184 | ;; Must declare this under XEmacs, which doesn't have built-in |
| 185 | ;; minibuffer history truncation. |
| 186 | (defvar history-length 100)) |
| 187 | \f |
| 188 | ;; Functions. |
| 189 | |
| 190 | ;;;###autoload |
| 191 | (defun savehist-mode (arg) |
| 192 | "Toggle savehist-mode. |
| 193 | Positive ARG turns on `savehist-mode'. When on, savehist-mode causes |
| 194 | minibuffer history to be saved periodically and when exiting Emacs. |
| 195 | When turned on for the first time in an Emacs session, it causes the |
| 196 | previous minibuffer history to be loaded from `savehist-file'. |
| 197 | |
| 198 | This mode should normally be turned on from your Emacs init file. |
| 199 | Calling it at any other time replaces your current minibuffer histories, |
| 200 | which is probably undesirable." |
| 201 | (interactive "P") |
| 202 | (setq savehist-mode |
| 203 | (if (null arg) |
| 204 | (not savehist-mode) |
| 205 | (> (prefix-numeric-value arg) 0))) |
| 206 | (if (not savehist-mode) |
| 207 | (savehist-uninstall) |
| 208 | (when (and (not savehist-loaded) |
| 209 | (file-exists-p savehist-file)) |
| 210 | (condition-case errvar |
| 211 | (progn |
| 212 | ;; Don't set coding-system-for-read -- we rely on the |
| 213 | ;; coding cookie to convey that information. That way, if |
| 214 | ;; the user changes the value of savehist-coding-system, |
| 215 | ;; we can still correctly load the old file. |
| 216 | (load savehist-file nil (not (interactive-p))) |
| 217 | (setq savehist-loaded t)) |
| 218 | (error |
| 219 | ;; Don't install the mode if reading failed. Doing so would |
| 220 | ;; effectively destroy the user's data at the next save. |
| 221 | (setq savehist-mode nil) |
| 222 | (savehist-uninstall) |
| 223 | (signal (car errvar) (cdr errvar))))) |
| 224 | (savehist-install) |
| 225 | (run-hooks 'savehist-mode-hook)) |
| 226 | ;; Return the new setting. |
| 227 | savehist-mode) |
| 228 | (add-minor-mode 'savehist-mode "") |
| 229 | |
| 230 | (defun savehist-load () |
| 231 | "Obsolete function provided for transition from old versions of savehist. |
| 232 | Don't call this from new code, use (savehist-mode 1) instead. |
| 233 | |
| 234 | This function loads the variables stored in `savehist-file' and turns on |
| 235 | `savehist-mode'. If `savehist-file' is in the old format that doesn't |
| 236 | record the value of `savehist-minibuffer-history-variables', that value |
| 237 | is deducted from the contents of the file." |
| 238 | (savehist-mode 1) |
| 239 | ;; Old versions of savehist distributed with XEmacs didn't save |
| 240 | ;; savehist-minibuffer-history-variables. If that variable is nil |
| 241 | ;; after loading the file, try to intuit the intended value. |
| 242 | (when (null savehist-minibuffer-history-variables) |
| 243 | (setq savehist-minibuffer-history-variables |
| 244 | (with-temp-buffer |
| 245 | (ignore-errors |
| 246 | (insert-file-contents savehist-file)) |
| 247 | (let ((vars ()) form) |
| 248 | (while (setq form (condition-case nil |
| 249 | (read (current-buffer)) (error nil))) |
| 250 | ;; Each form read is of the form (setq VAR VALUE). |
| 251 | ;; Collect VAR, i.e. (nth form 1). |
| 252 | (push (nth 1 form) vars)) |
| 253 | vars))))) |
| 254 | (make-obsolete 'savehist-load 'savehist-mode) |
| 255 | |
| 256 | (defun savehist-install () |
| 257 | "Hook savehist into Emacs. |
| 258 | Normally invoked by calling `savehist-mode' to set the minor mode. |
| 259 | Installs `savehist-autosave' in `kill-emacs-hook' and on a timer. |
| 260 | To undo this, call `savehist-uninstall'." |
| 261 | (add-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
| 262 | (add-hook 'kill-emacs-hook 'savehist-autosave) |
| 263 | ;; Install an invocation of savehist-autosave on a timer. This |
| 264 | ;; should not cause noticeable delays for users -- savehist-autosave |
| 265 | ;; executes in under 5 ms on my system. |
| 266 | (when (and savehist-autosave-interval |
| 267 | (null savehist-timer)) |
| 268 | (setq savehist-timer |
| 269 | (if (featurep 'xemacs) |
| 270 | (start-itimer |
| 271 | "savehist" 'savehist-autosave savehist-autosave-interval |
| 272 | savehist-autosave-interval) |
| 273 | (run-with-timer savehist-autosave-interval |
| 274 | savehist-autosave-interval 'savehist-autosave))))) |
| 275 | |
| 276 | (defun savehist-uninstall () |
| 277 | "Undo installing savehist. |
| 278 | Normally invoked by calling `savehist-mode' to unset the minor mode." |
| 279 | (remove-hook 'minibuffer-setup-hook 'savehist-minibuffer-hook) |
| 280 | (remove-hook 'kill-emacs-hook 'savehist-autosave) |
| 281 | (when savehist-timer |
| 282 | (if (featurep 'xemacs) |
| 283 | (delete-itimer savehist-timer) |
| 284 | (cancel-timer savehist-timer)) |
| 285 | (setq savehist-timer nil))) |
| 286 | |
| 287 | (defun savehist-save (&optional auto-save) |
| 288 | "Save the values of minibuffer history variables. |
| 289 | Unbound symbols referenced in `savehist-additional-variables' are ignored. |
| 290 | If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, |
| 291 | and don't save the buffer if they are the same." |
| 292 | (interactive) |
| 293 | (with-temp-buffer |
| 294 | (insert |
| 295 | (format ";; -*- mode: emacs-lisp; coding: %s -*-\n" savehist-coding-system) |
| 296 | ";; Minibuffer history file, automatically generated by `savehist'.\n\n") |
| 297 | (run-hooks 'savehist-save-hook) |
| 298 | (let ((print-length nil) |
| 299 | (print-string-length nil) |
| 300 | (print-level nil) |
| 301 | (print-readably t) |
| 302 | (print-quoted t)) |
| 303 | ;; Save the minibuffer histories, along with the value of |
| 304 | ;; savehist-minibuffer-history-variables itself. |
| 305 | (when savehist-save-minibuffer-history |
| 306 | (prin1 `(setq savehist-minibuffer-history-variables |
| 307 | ',savehist-minibuffer-history-variables) |
| 308 | (current-buffer)) |
| 309 | (insert ?\n) |
| 310 | (dolist (symbol savehist-minibuffer-history-variables) |
| 311 | (when (boundp symbol) |
| 312 | (let ((value (savehist-trim-history (symbol-value symbol))) |
| 313 | excess-space) |
| 314 | (when value ; Don't save empty histories. |
| 315 | (insert "(setq ") |
| 316 | (prin1 symbol (current-buffer)) |
| 317 | (insert " '(") |
| 318 | ;; We will print an extra space before the first element. |
| 319 | ;; Record where that is. |
| 320 | (setq excess-space (point)) |
| 321 | ;; Print elements of VALUE one by one, carefully. |
| 322 | (dolist (elt value) |
| 323 | (let ((start (point))) |
| 324 | (insert " ") |
| 325 | (prin1 elt (current-buffer)) |
| 326 | ;; Try to read the element we just printed. |
| 327 | (condition-case nil |
| 328 | (save-excursion |
| 329 | (goto-char start) |
| 330 | (read (current-buffer))) |
| 331 | (error |
| 332 | ;; If reading it gets an error, comment it out. |
| 333 | (goto-char start) |
| 334 | (insert "\n") |
| 335 | (while (not (eobp)) |
| 336 | (insert ";;; ") |
| 337 | (forward-line 1)) |
| 338 | (insert "\n"))) |
| 339 | (goto-char (point-max)))) |
| 340 | ;; Delete the extra space before the first element. |
| 341 | (save-excursion |
| 342 | (goto-char excess-space) |
| 343 | (if (eq (following-char) ?\s) |
| 344 | (delete-region (point) (1+ (point))))) |
| 345 | (insert "))\n")))))) |
| 346 | ;; Save the additional variables. |
| 347 | (dolist (symbol savehist-additional-variables) |
| 348 | (when (boundp symbol) |
| 349 | (let ((value (symbol-value symbol))) |
| 350 | (when (savehist-printable value) |
| 351 | (prin1 `(setq ,symbol ',value) (current-buffer)) |
| 352 | (insert ?\n)))))) |
| 353 | ;; If autosaving, avoid writing if nothing has changed since the |
| 354 | ;; last write. |
| 355 | (let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion))) |
| 356 | (unless (and auto-save (equal checksum savehist-last-checksum)) |
| 357 | ;; Set file-precious-flag when saving the buffer because we |
| 358 | ;; don't want a half-finished write ruining the entire |
| 359 | ;; history. Remember that this is run from a timer and from |
| 360 | ;; kill-emacs-hook, and also that multiple Emacs instances |
| 361 | ;; could write to this file at once. |
| 362 | (let ((file-precious-flag t) |
| 363 | (coding-system-for-write savehist-coding-system)) |
| 364 | (write-region (point-min) (point-max) savehist-file nil |
| 365 | (unless (interactive-p) 'quiet))) |
| 366 | (when savehist-file-modes |
| 367 | (set-file-modes savehist-file savehist-file-modes)) |
| 368 | (setq savehist-last-checksum checksum))))) |
| 369 | |
| 370 | (defun savehist-autosave () |
| 371 | "Save the minibuffer history if it has been modified since the last save. |
| 372 | Does nothing if `savehist-mode' is off." |
| 373 | (when savehist-mode |
| 374 | (savehist-save t))) |
| 375 | |
| 376 | (defun savehist-trim-history (value) |
| 377 | "Retain only the first `history-length' items in VALUE. |
| 378 | Only used under XEmacs, which doesn't (yet) implement automatic |
| 379 | trimming of history lists to `history-length' items." |
| 380 | (if (and (featurep 'xemacs) |
| 381 | (natnump history-length) |
| 382 | (> (length value) history-length)) |
| 383 | ;; Equivalent to `(subseq value 0 history-length)', but doesn't |
| 384 | ;; need cl-extra at run-time. |
| 385 | (loop repeat history-length collect (pop value)) |
| 386 | value)) |
| 387 | |
| 388 | (defun savehist-printable (value) |
| 389 | "Return non-nil if VALUE is printable." |
| 390 | (cond |
| 391 | ;; Quick response for oft-encountered types known to be printable. |
| 392 | ((stringp value)) |
| 393 | ((numberp value)) |
| 394 | ((symbolp value)) |
| 395 | (t |
| 396 | ;; For others, check explicitly. |
| 397 | (with-temp-buffer |
| 398 | (condition-case nil |
| 399 | (let ((print-readably t) (print-level nil)) |
| 400 | ;; Print the value into a buffer... |
| 401 | (prin1 value (current-buffer)) |
| 402 | ;; ...and attempt to read it. |
| 403 | (read (point-min-marker)) |
| 404 | ;; The attempt worked: the object is printable. |
| 405 | t) |
| 406 | ;; The attempt failed: the object is not printable. |
| 407 | (error nil)))))) |
| 408 | |
| 409 | (defun savehist-minibuffer-hook () |
| 410 | (unless (or (eq minibuffer-history-variable t) |
| 411 | ;; XEmacs sets minibuffer-history-variable to t to mean "no |
| 412 | ;; history is being recorded". |
| 413 | (memq minibuffer-history-variable savehist-ignored-variables)) |
| 414 | (add-to-list 'savehist-minibuffer-history-variables |
| 415 | minibuffer-history-variable))) |
| 416 | |
| 417 | (provide 'savehist) |
| 418 | \f |
| 419 | ;; arch-tag: b3ce47f4-c5ad-4ebc-ad02-73aba705cf9f |
| 420 | |
| 421 | ;;; savehist.el ends here |