[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: savehist and multiple Emacs sessions
From: |
Stefan Monnier |
Subject: |
Re: savehist and multiple Emacs sessions |
Date: |
Wed, 21 Dec 2005 12:01:14 -0500 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) |
>> So I think it's worth it to make savehist.el handle such
>> situations better.
> I agree. I don't have time to thoroughly review the patch right now,
> but I trust that you got it right.
> The only thing I disagree with is the resurrection of `savehist-load'.
Well, the code is long enough to warrant a function of its own, and it
seemed like the most natural name for it. But if you prefer to keep it
separate, I can call it something else, e.g. savehist-reload.
> BTW with the new semantics of savehist-loaded, you might want to
> rename it to savehist-load-time or something like that.
In that case I'd name it savehist-file-sync-time, since it can also be the
time it was last saved.
>> It's only be lightly tested. It also includes the changes to the
>> minor mode definition that make it handle Custom setting slightly
>> better and which make it run the minor mode hook in the same way as
>> all other minor modes defined by define-minor-mode.
> This breaks savehist under XEmacs and Emacs 21.4, which I use.
Oh yes, now I remember. Sorry 'bout that. This new patch should fix all
the above.
Stefan
--- orig/lisp/savehist.el
+++ mod/lisp/savehist.el
@@ -168,10 +168,8 @@
as possible, ideally simply exposing the internal representation of
buffer text.")
-(defvar savehist-loaded nil
- "Whether the history has already been loaded.
-This prevents toggling savehist-mode from destroying existing
-minibuffer history.")
+(defvar savehist-file-sync-modtime nil
+ "Modtime of the `savehist-file' when we last sync'd up with it.")
(when (featurep 'xemacs)
;; Must declare this under XEmacs, which doesn't have built-in
@@ -198,34 +196,21 @@
(> (prefix-numeric-value arg) 0)))
(if (not savehist-mode)
(savehist-uninstall)
- (when (and (not savehist-loaded)
- (file-exists-p savehist-file))
- (condition-case errvar
- (progn
- ;; Don't set coding-system-for-read -- we rely on the
- ;; coding cookie to convey that information. That way, if
- ;; the user changes the value of savehist-coding-system,
- ;; we can still correctly load the old file.
- (load savehist-file nil (not (interactive-p)))
- (setq savehist-loaded t))
- (error
- ;; Don't install the mode if reading failed. Doing so would
- ;; effectively destroy the user's data at the next save.
- (setq savehist-mode nil)
- (savehist-uninstall)
- (signal (car errvar) (cdr errvar)))))
- (savehist-install)
- (run-hooks 'savehist-mode-hook))
+ (savehist-reload)
+ (savehist-install))
+ (if (and (fboundp 'customize-mark-as-set) (interactive-p))
+ (customize-mark-as-set 'savehist-mode))
+ (run-hooks 'savehist-mode-hook)
;; Return the new setting.
savehist-mode)
-(add-minor-mode 'savehist-mode "")
+(add-minor-mode 'savehist-mode nil)
(defun savehist-load ()
"Obsolete function provided for transition from old versions of savehist.
Don't call this from new code, use (savehist-mode 1) instead.
This function loads the variables stored in `savehist-file' and turns on
-savehist-mode. If savehist-file is in the old format that doesn't record
+`savehist-mode'. If `savehist-file' is in the old format that doesn't record
the value of `savehist-minibuffer-history-variables', that value is
deducted from the contents of the file."
(savehist-mode 1)
@@ -238,14 +223,52 @@
(ignore-errors
(insert-file-contents savehist-file))
(let ((vars ()) form)
- (while (setq form (condition-case nil
- (read (current-buffer)) (error nil)))
+ (while (setq form (ignore-errors (read (current-buffer))))
;; Each form read is of the form (setq VAR VALUE).
;; Collect VAR, i.e. (nth form 1).
(push (nth 1 form) vars))
vars)))))
(make-obsolete 'savehist-load 'savehist-mode)
+(defun savehist-reload ()
+ "Load the history data from `savehist-file' while preserving the current
history data."
+ (let ((savehist-old-minibuffer-history-variables
+ (mapcar (lambda (s) (and (boundp s) (cons s (symbol-value s))))
+ (cons 'savehist-minibuffer-history-variables
+ savehist-minibuffer-history-variables))))
+ (when (and (file-exists-p savehist-file)
+ (not (equal savehist-file-sync-modtime
+ (nth 5 (file-attributes savehist-file)))))
+ (condition-case errvar
+ (progn
+ ;; Don't set coding-system-for-read -- we rely on the
+ ;; coding cookie to convey that information. That way, if
+ ;; the user changes the value of savehist-coding-system,
+ ;; we can still correctly load the old file.
+ (load savehist-file nil (not (interactive-p)))
+ (setq savehist-file-sync-modtime
+ (nth 5 (file-attributes savehist-file))))
+ (error
+ ;; Don't install the mode if reading failed. Doing so would
+ ;; effectively destroy the user's data at the next save.
+ (setq savehist-mode nil)
+ (savehist-uninstall)
+ (signal (car errvar) (cdr errvar)))))
+
+ ;; In case we're loading the file late, there was info in the history
+ ;; variables that may have been overwritten by the info extracted from
+ ;; the file, so put it back in.
+ (dolist (sv savehist-old-minibuffer-history-variables)
+ ;; For each histvar that we knew about, make sure all the entries that
+ ;; were there before are still here now and in the same order.
+ (ignore-errors ; Maybe some var is not a list or something.
+ (let* ((s (car sv))
+ (v (cdr sv))
+ (newv (symbol-value s)))
+ (unless (equal newv v) ;Simple optimization.
+ (dolist (x v) (setq newv (delete x newv)))
+ (set s (append v newv))))))))
+
(defun savehist-install ()
"Hook savehist into Emacs.
Normally invoked by calling `savehist-mode' to set the minor mode.
@@ -283,6 +306,13 @@
If AUTO-SAVE is non-nil, compare the saved contents to the one last saved,
and don't save the buffer if they are the same."
(interactive)
+ (unless (equal savehist-file-sync-modtime
+ (nth 5 (file-attributes savehist-file)))
+ ;; The file has been changed since last time we touched it.
+ ;; Probably some other Emacs session. Load the corresponding info so we
+ ;; don't end up throwing it away by blindly overwriting it. There's
+ ;; still a race-condition, but I don't think it's that important.
+ (savehist-reload))
(with-temp-buffer
(insert
(format ";; -*- mode: emacs-lisp; coding: %s -*-\n"
savehist-coding-system)
@@ -328,6 +358,8 @@
(unless (interactive-p) 'quiet)))
(when savehist-file-modes
(set-file-modes savehist-file savehist-file-modes))
+ (setq savehist-file-sync-modtime
+ (nth 5 (file-attributes savehist-file)))
(setq savehist-last-checksum checksum)))))
(defun savehist-autosave ()