unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* A few questions about desktop.el
@ 2005-07-22  2:42 Juanma Barranquero
  2005-07-22 10:53 ` Juanma Barranquero
                   ` (4 more replies)
  0 siblings, 5 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-22  2:42 UTC (permalink / raw)


(These questions are mainly for Lars Hansen, who did most of the
recent cleanup work on desktop.el)

I'm having a few problems with highlight-changes-mode, which is a
not-very-standard minor mode.

I do (global-highlight-changes 'passive) on my .emacs, so most buffers
have a local `highlight-changes-mode' variable with value 'passive.
Logically, `highlight-changes-mode' goes to the minor-modes list in
.emacs.desktop, and it gets restored by calling
(highlight-changes-mode 1)... so highlight-changes-mode is active on
all buffers after loading Emacs :)

I can fix it with the attached patch. Is it reasonable to add to
desktop.el code to deal with minor modes from the Emacs library, or
should it be done in hilit-chg.el or the user's .emacs?

The other question is: why does `desktop-save' save `nil' for active
minor-modes which do appear in `desktop-minor-mode-table' as
non-restorable? I mean, why

  (let ((special (assq minor-mode desktop-minor-mode-table)))
    (when (or special (functionp minor-mode))
      (setq ret
            (cons
             (if special (cadr special) minor-mode)
             ret))))

instead of simply

  (let ((special (cadr (assq minor-mode desktop-minor-mode-table))))
    (when (or special (functionp minor-mode))
      (add-to-list 'ret (or special minor-mode))))

which wouldn't save nil values to the minor-mode list?

-- 
                    /L/e/k/t/u


Index: lisp/desktop.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/desktop.el,v
retrieving revision 1.88
diff -u -2 -r1.88 desktop.el
--- lisp/desktop.el	21 Jul 2005 11:49:32 -0000	1.88
+++ lisp/desktop.el	22 Jul 2005 02:27:41 -0000
@@ -229,5 +229,6 @@
     change-log-default-name
     line-number-mode
-    buffer-file-coding-system)
+    buffer-file-coding-system
+    highlight-changes-mode)
   "List of local variables to save for each buffer.
 The variables are saved only when they really are local."
@@ -346,5 +347,6 @@
  (defcustom desktop-minor-mode-table
   '((auto-fill-function auto-fill-mode)
-    (vc-mode nil))
+    (vc-mode nil)
+    (highlight-changes-mode nil))
   "Table mapping minor mode variables to minor mode functions.
 Each entry has the form (NAME RESTORE-FUNCTION).

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
@ 2005-07-22 10:53 ` Juanma Barranquero
  2005-07-22 22:52   ` Richard M. Stallman
  2005-08-08 15:02   ` Lars Hansen
  2005-07-22 13:50 ` Juanma Barranquero
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-22 10:53 UTC (permalink / raw)


In fact, I'm not sure what criterion is used to decide the default
value of `desktop-locals-to-save'. I'd include (at least)

  - indent-tabs-mode
  - indicate-buffer-boundaries
  - indicate-empty-lines
  - show-trailing-whitespace
  - save-place

and I'm not sure why does it include `line-number-mode'. Why not
`column-number-mode' or `size-indication-mode'?

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
  2005-07-22 10:53 ` Juanma Barranquero
@ 2005-07-22 13:50 ` Juanma Barranquero
  2005-07-22 14:36   ` Juanma Barranquero
  2005-07-22 19:11 ` Lars Hansen
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-22 13:50 UTC (permalink / raw)


On 7/22/05, Juanma Barranquero <lekktu@gmail.com> wrote:

> instead of simply
> 
>   (let ((special (cadr (assq minor-mode desktop-minor-mode-table))))
>     (when (or special (functionp minor-mode))
>       (add-to-list 'ret (or special minor-mode))))

My fault, for posting untested code. I meant:

  (let* ((special (assq minor-mode desktop-minor-mode-table))
         (value (cond (special (cadr special))
                      ((functionp minor-mode) minor-mode))))
    (when value (add-to-list 'ret value)))))

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 13:50 ` Juanma Barranquero
@ 2005-07-22 14:36   ` Juanma Barranquero
  2005-07-26  8:27     ` Juanma Barranquero
  2005-08-08 15:04     ` Lars Hansen
  0 siblings, 2 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-22 14:36 UTC (permalink / raw)


The very end of `desktop-save' contains:

  (setq default-directory dirname)
  (when (file-exists-p filename) (delete-file filename))
  (let ((coding-system-for-write 'emacs-mule))
    (write-region (point-min) (point-max) filename nil 'nomessage))))

The code to delete the desktop file before writing into it has
existed, AFAICS, since release 1.1 of desktop.el.

However, it is bringing me pain on Windows. If I try to exit Emacs
while viewing the .emacs.desktop from a command shell, Emacs tries to
delete the file (and apparently succeeds), and then tries to write it
anew (and it fails). After exiting the viewer program, .emacs.desktop
no longer exists. Not nice.

It is really necessary to delete the file prior to `write-region' it?
Are there use cases where that is an advantage?

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
  2005-07-22 10:53 ` Juanma Barranquero
  2005-07-22 13:50 ` Juanma Barranquero
@ 2005-07-22 19:11 ` Lars Hansen
  2005-07-22 21:24   ` Juanma Barranquero
  2005-07-22 22:50 ` Richard M. Stallman
  2005-08-08 14:51 ` Lars Hansen
  4 siblings, 1 reply; 72+ messages in thread
From: Lars Hansen @ 2005-07-22 19:11 UTC (permalink / raw)
  Cc: emacs-devel

Juanma Barranquero wrote:
> (These questions are mainly for Lars Hansen, who did most of the
> recent cleanup work on desktop.el)
I am just about to go to Greece on vacation, far away form e-mail. But I
will be glad to use a bit of time to look into your questions (I bring a
laptop). When I return in about 16 days, I will post an answer.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 19:11 ` Lars Hansen
@ 2005-07-22 21:24   ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-22 21:24 UTC (permalink / raw)
  Cc: emacs-devel

On 7/22/05, Lars Hansen <larsh@soem.dk> wrote:

> But I
> will be glad to use a bit of time to look into your questions (I bring a
> laptop). When I return in about 16 days, I will post an answer.

Thanks, and happy holidays.

                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
                   ` (2 preceding siblings ...)
  2005-07-22 19:11 ` Lars Hansen
@ 2005-07-22 22:50 ` Richard M. Stallman
  2005-07-26  9:11   ` Juanma Barranquero
  2005-08-08 14:51 ` Lars Hansen
  4 siblings, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-22 22:50 UTC (permalink / raw)
  Cc: emacs-devel

It would be cleaner if this could be done with code in hilit-chg.el
itself.  However, making that possible would probably require
another way to customize desktop.el.  It would be useful to add
a suitable mechanism to desktop.el that would make this possible
in a clean way.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 10:53 ` Juanma Barranquero
@ 2005-07-22 22:52   ` Richard M. Stallman
  2005-07-26  8:56     ` Juanma Barranquero
  2005-08-08 15:02   ` Lars Hansen
  1 sibling, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-22 22:52 UTC (permalink / raw)
  Cc: emacs-devel

      - indent-tabs-mode
      - indicate-buffer-boundaries
      - indicate-empty-lines
      - show-trailing-whitespace

I guess those are all reasonable to include.

How about this: save all minor modes, based on minor-mode-list.

    and I'm not sure why does it include `line-number-mode'. Why not
    `column-number-mode' or `size-indication-mode'?

Those are newer and not used much, so most likely nobody thought to add
them.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 14:36   ` Juanma Barranquero
@ 2005-07-26  8:27     ` Juanma Barranquero
  2005-08-08 15:04     ` Lars Hansen
  1 sibling, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-26  8:27 UTC (permalink / raw)


Regarding this code in `desktop-save':

>   (setq default-directory dirname)
>   (when (file-exists-p filename) (delete-file filename))
>   (let ((coding-system-for-write 'emacs-mule))
>     (write-region (point-min) (point-max) filename nil 'nomessage))))

No one, not even the original author (I've just asked him), knows for
sure whether the `delete-file' call is needed or why, and I know for
certain it can produce some unexpected results in Windows
("unexpected" including data loss, meaning losing the .emacs.desktop
file).

So, if no one objects, in a few days I'm gonna delete that line. As
we're not even in pretesting, we'll have plenty of time to know
whether it causes problems in some environment or other, and
reintroduce it (conditional to non-Windows, or not) if needed.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 22:52   ` Richard M. Stallman
@ 2005-07-26  8:56     ` Juanma Barranquero
  2005-07-27 14:03       ` Richard M. Stallman
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-26  8:56 UTC (permalink / raw)
  Cc: emacs-devel

On 7/23/05, Richard M. Stallman <rms@gnu.org> wrote:
>       - indent-tabs-mode
>       - indicate-buffer-boundaries
>       - indicate-empty-lines
>       - show-trailing-whitespace
> 
> I guess those are all reasonable to include.
> 
> How about this: save all minor modes, based on minor-mode-list.

AFAICS, `desktop-save' already saves all active minor-modes except
those listed in `desktop-minor-mode-table', which get special
processing. The ones listed above are ones that should need a special
processing because they're not normal minor modes (there's no
`indent-tabs-mode' function, for example).

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 22:50 ` Richard M. Stallman
@ 2005-07-26  9:11   ` Juanma Barranquero
  2005-07-27 14:04     ` Richard M. Stallman
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-26  9:11 UTC (permalink / raw)
  Cc: emacs-devel

On 7/23/05, Richard M. Stallman <rms@gnu.org> wrote:

> However, making that possible would probably require
> another way to customize desktop.el.  It would be useful to add
> a suitable mechanism to desktop.el that would make this possible
> in a clean way.

I can add that mechanism, but I'm not sure it is worth it. There are a
bunch of variables that other packages could possibly want to modify:

  desktop-globals-to-save
  desktop-globals-to-clear
 desktop-clear-preserve-buffers-regexp
 desktop-clear-preserve-buffers
 desktop-locals-to-save
 desktop-buffers-not-to-save
 desktop-files-not-to-save
 desktop-modes-not-to-save
 desktop-buffer-mode-handlers
 desktop-minor-mode-table

and the various hooks. I see no clear pattern about what would other
packages want to modify; *-locals-to-save and *-minor-mode-table are
perhaps the most useful, but other than that everything's game. I
don't see what do we gain by adding functions to manipulate these vars
instead of doing it directly.
  
-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-26  8:56     ` Juanma Barranquero
@ 2005-07-27 14:03       ` Richard M. Stallman
  2005-07-27 14:28         ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-27 14:03 UTC (permalink / raw)
  Cc: emacs-devel

    AFAICS, `desktop-save' already saves all active minor-modes except
    those listed in `desktop-minor-mode-table', which get special
    processing. The ones listed above are ones that should need a special
    processing because they're not normal minor modes (there's no
    `indent-tabs-mode' function, for example).

As you can see, I don't know much about desktop.el--I don't use it.

If you see that a certain mode needs special processing,
please just implement that.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-26  9:11   ` Juanma Barranquero
@ 2005-07-27 14:04     ` Richard M. Stallman
  2005-07-27 14:16       ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-27 14:04 UTC (permalink / raw)
  Cc: emacs-devel

    and the various hooks. I see no clear pattern about what would other
    packages want to modify; *-locals-to-save and *-minor-mode-table are
    perhaps the most useful, but other than that everything's game.

How many minor modes could you take care of with just those two?

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:04     ` Richard M. Stallman
@ 2005-07-27 14:16       ` Juanma Barranquero
  2005-07-28  3:20         ` Richard M. Stallman
  2005-08-10  9:50         ` Lars Hansen
  0 siblings, 2 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-27 14:16 UTC (permalink / raw)
  Cc: emacs-devel

On 7/27/05, Richard M. Stallman <rms@gnu.org> wrote:

> How many minor modes could you take care of with just those two?

Difficult to say without looking at each one, particularly because
we're talking not of the "normal" minor modes, but the ones that do a
minor-mode work in a non-conventional way: highlight-change,
overwrite, indent-tabs...

All in all, though, I suppose that most of them. But, as a datapoint,
I recently added "*server*" directly to
`desktop-clear-preserve-buffers-regexp' in desktop.el; now I see the
clean way would be for server.el to add it (but that would require a
redesign of a bit of desktop.el interface).

[time passes...]

You're gonna say "Then add a function to customize these two and we'll
see whether we need to add anything more", aren't you? :) OK, I'll see
what I can do.

Anyway, I'd prefer not to make many changes to desktop.el (even quite
non-intrusive changes like these) until Lars returns from holidays, as
he said he would take a look at some questions I posed. I'll post a
patch as soon as I've got it ready, and wait for him.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:03       ` Richard M. Stallman
@ 2005-07-27 14:28         ` Juanma Barranquero
  2005-07-28  3:20           ` Richard M. Stallman
                             ` (3 more replies)
  0 siblings, 4 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-27 14:28 UTC (permalink / raw)
  Cc: emacs-devel

> As you can see, I don't know much about desktop.el--I don't use it.

It's quite useful, and it'll be great the day we can make it
save/restore window and frame configurations. But I don't think
there's an easy way to turn a window configuration into elisp and back
:(

> If you see that a certain mode needs special processing,
> please just implement that.

I'll do.

Not-totally-unrelated: running two or more Emacs instances that use
the same desktop file is a classical race condition; the last one to
exit overwrites the desktop file (quite funny when the desktop was
very elaborate and the last instance to exit uses almost no buffers).

It'd be very useful to try to detect it and at least stop the second
instance from loading and using the desktop file if it's already in
use. There's no way to do that from Emacs, is there?

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:28         ` Juanma Barranquero
@ 2005-07-28  3:20           ` Richard M. Stallman
  2005-07-28  7:34             ` David Kastrup
  2005-07-28  3:20           ` Richard M. Stallman
                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-28  3:20 UTC (permalink / raw)
  Cc: emacs-devel

    It's quite useful, and it'll be great the day we can make it
    save/restore window and frame configurations. But I don't think
    there's an easy way to turn a window configuration into elisp and back

It is straightforward to do walk-windows and record the size and
contents of each leaf window.  It's necessary in addition to record
the structure.  I think this can be deduced from that info as follows:

Notice when consecutive windows (in the standard window ordering) have
the same left and right edges, and when they have the same top and
bottom edges.  In those cases, you have vertical or horizontal
siblings.  So make a list of them and replace them with an item
that corresponds to the combination of them.

Do this over and over until you're left with one "window",
and you've reconstructed the whole tree.

We could add a primitive which constructs a window configuration
from a list of window sizes and contents.  If the above algorithm
fails to reduce the specified data to a single window, it would
signal an error.

(We could conceive of making window configurations transparent data
using this method.  This would make save-window-configuration slower;
would it be enough slowdown to cause a problem?  Perhaps nowadays
it would not be a problem.)

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:28         ` Juanma Barranquero
  2005-07-28  3:20           ` Richard M. Stallman
@ 2005-07-28  3:20           ` Richard M. Stallman
  2005-07-29  0:37             ` Juanma Barranquero
  2005-07-28  4:24           ` Masatake YAMATO
  2006-04-27 23:05           ` Stuart D. Herring
  3 siblings, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-28  3:20 UTC (permalink / raw)
  Cc: emacs-devel

    It'd be very useful to try to detect it and at least stop the second
    instance from loading and using the desktop file if it's already in
    use. There's no way to do that from Emacs, is there?

It needs to use file-locking together with testing of the file modtime.
There are primitives to do this: lock-file and unlock-file,
and file-attributes.  So when you restore an old desktop, you
record the modtime of the file.  When you update the desktop file,
you lock it, them see if its modtime is the same as it was
when you restored the desktop.  If not, you do whatever.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:16       ` Juanma Barranquero
@ 2005-07-28  3:20         ` Richard M. Stallman
  2005-07-29  0:44           ` Juanma Barranquero
  2005-08-10  9:50         ` Lars Hansen
  1 sibling, 1 reply; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-28  3:20 UTC (permalink / raw)
  Cc: emacs-devel

    > How many minor modes could you take care of with just those two?

    Difficult to say without looking at each one, particularly because
    we're talking not of the "normal" minor modes, but the ones that do a
    minor-mode work in a non-conventional way: highlight-change,
    overwrite, indent-tabs...

How about if you start checking them.  That is the only way to find
out if these two variables would really improve the situation.

    You're gonna say "Then add a function to customize these two and we'll
    see whether we need to add anything more", aren't you? :) OK, I'll see
    what I can do.

Not exactly.  The first step is to see how much good this would do.
Also, the customization mechanism for the minor modes to use does not
have to be a function to call.  It may be that an alist which major
modes can add to would be cleaner.  That's entirely a matter of
details.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:28         ` Juanma Barranquero
  2005-07-28  3:20           ` Richard M. Stallman
  2005-07-28  3:20           ` Richard M. Stallman
@ 2005-07-28  4:24           ` Masatake YAMATO
  2006-04-27 23:05           ` Stuart D. Herring
  3 siblings, 0 replies; 72+ messages in thread
From: Masatake YAMATO @ 2005-07-28  4:24 UTC (permalink / raw)
  Cc: rms, emacs-devel

> > As you can see, I don't know much about desktop.el--I don't use it.
> 
> It's quite useful, and it'll be great the day we can make it
> save/restore window and frame configurations. But I don't think
> there's an easy way to turn a window configuration into elisp and back
> :(

Look at HIROSE-san's hack.
http://www.gentei.org/~yuuji/software/revive.el

Masatake

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-28  3:20           ` Richard M. Stallman
@ 2005-07-28  7:34             ` David Kastrup
  2005-07-28 12:51               ` Juanma Barranquero
  2005-07-29  0:11               ` Richard M. Stallman
  0 siblings, 2 replies; 72+ messages in thread
From: David Kastrup @ 2005-07-28  7:34 UTC (permalink / raw)
  Cc: Juanma Barranquero, emacs-devel

"Richard M. Stallman" <rms@gnu.org> writes:

>     It's quite useful, and it'll be great the day we can make it
>     save/restore window and frame configurations. But I don't think
>     there's an easy way to turn a window configuration into elisp and back
>
> It is straightforward to do walk-windows and record the size and
> contents of each leaf window.  It's necessary in addition to record
> the structure.  I think this can be deduced from that info as
> follows:

There is no guarantee that the stored desktop file will get used on
the same display, not even with the same Emacs.  And what if you do
emacs -nw ?

It sounds like something that has potential for problems, certainly
enough to push it till after release.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-28  7:34             ` David Kastrup
@ 2005-07-28 12:51               ` Juanma Barranquero
  2005-07-29  0:11               ` Richard M. Stallman
  1 sibling, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-28 12:51 UTC (permalink / raw)
  Cc: rms, emacs-devel

On 7/28/05, David Kastrup <dak@gnu.org> wrote:

> There is no guarantee that the stored desktop file will get used on
> the same display, not even with the same Emacs.  And what if you do
> emacs -nw ?

Even with -nw Emacs supports multiple frames and multiple windows.
Moreover, at the very worst what can happen? Emacs not creating enough
windows?

> It sounds like something that has potential for problems,

Sure.

> certainly
> enough to push it till after release.

I agree, not because of the problems you see, but because it is a new
feature (I wouldn't count adding this to desktop.el as a bug fix).

I don't think we should be postponing features with "potential for
problems"; we should be postponing *all* new features. IMO.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-28  7:34             ` David Kastrup
  2005-07-28 12:51               ` Juanma Barranquero
@ 2005-07-29  0:11               ` Richard M. Stallman
  1 sibling, 0 replies; 72+ messages in thread
From: Richard M. Stallman @ 2005-07-29  0:11 UTC (permalink / raw)
  Cc: lekktu, emacs-devel

    There is no guarantee that the stored desktop file will get used on
    the same display, not even with the same Emacs.  And what if you do
    emacs -nw ?

What's the problem?  If it does not make sense to restore the window
configuration, don't restore it.

    It sounds like something that has potential for problems, certainly
    enough to push it till after release.

Yes, this is for after the release.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-28  3:20           ` Richard M. Stallman
@ 2005-07-29  0:37             ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-29  0:37 UTC (permalink / raw)
  Cc: emacs-devel

On 7/28/05, Richard M. Stallman <rms@gnu.org> wrote:

> It needs to use file-locking together with testing of the file modtime.
> There are primitives to do this: lock-file and unlock-file,
> and file-attributes.

I don't see any `lock-file' and `unlock-file'. There are functions
`lock-buffer', `unlock-buffer', and `file-locked-p'. Unfortunately,
they do nothing on Windows.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-28  3:20         ` Richard M. Stallman
@ 2005-07-29  0:44           ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-07-29  0:44 UTC (permalink / raw)
  Cc: emacs-devel

On 7/28/05, Richard M. Stallman <rms@gnu.org> wrote:

> How about if you start checking them.  That is the only way to find
> out if these two variables would really improve the situation.

Yeah, I'll do that.

> Also, the customization mechanism for the minor modes to use does not
> have to be a function to call.  It may be that an alist which major
> modes can add to would be cleaner.

In fact, the current "API", which is a list of lists and alists, is
quite clean except for the variables that store regexps:
`desktop-clear-preserve-buffers-regexp',
`desktop-buffers-not-to-save', `desktop-files-not-to-save'. The easier
way to customize these would be turning them into lists and adding
functions to generate the regexps from the lists.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
                   ` (3 preceding siblings ...)
  2005-07-22 22:50 ` Richard M. Stallman
@ 2005-08-08 14:51 ` Lars Hansen
  2005-08-08 18:35   ` Juanma Barranquero
  4 siblings, 1 reply; 72+ messages in thread
From: Lars Hansen @ 2005-08-08 14:51 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1728 bytes --]

Juanma Barranquero wrote:

>I'm having a few problems with highlight-changes-mode, which is a
>not-very-standard minor mode.
>  
>
Yes, the desktop module expects minor modes to follow the conventions.
The only mechanism
to deal with non-conventional minor modes is `desktop-minor-mode-table'
that allows the
minor mode variable and minor mode function to have different names.

To restore highlight changes mode, the function `highlight-changes-mode'
needs to be
called with the value of `highlight-changes-mode' to get the correct
"sub-mode". So what
is needed is something like `desktop-buffer-mode-handlers', but for
minor modes.
I suggest the patch below.
It allows modules defining minor modes to define their own restore
function without
having to change the desktop module.

>The other question is: why does `desktop-save' save `nil' for active
>minor-modes which do appear in `desktop-minor-mode-table' as
>non-restorable?
>  
>
I don't think there is any good reason. The patch below includes your
suggested change
(the second one).

Now I have a question: To allow modules defining major or minor modes to
add a special
handler to `desktop-buffer-mode-handlers' or
`desktop-minor-mode-handlers', the module
in question must be loaded before the major or minor mode function is
called. To do that,
the patch below defines the following function:

   (defun desktop-load-file (function)
     "Load the file where auto loaded FUNCTION is defined."
     (let ((fcell (symbol-function function)))
       (when (and (listp fcell)
                  (eq 'autoload (car fcell)))
         (load (cadr fcell)))))

This function assumes that the mode function is autoloaded. Is this
requirement ok?
Is there a better solution?



[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 20725 bytes --]

*** /home/lh/cvsroot/emacs/lisp/desktop.el	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.desktop.el	2005-08-08 16:27:09.416541856 +0200
***************
*** 51,63 ****
  ;; function is added to the `after-init-hook'. This function is
  ;; responsible for loading the desktop when Emacs is started.
  
! ;; Some words on minor modes: Most minor modes are controlled by
! ;; buffer-local variables, which have a standard save / restore
! ;; mechanism.  To handle all minor modes, we take the following
! ;; approach: (1) check whether the variable name from
! ;; `minor-mode-alist' is also a function; and (2) use translation
! ;; table `desktop-minor-mode-table' in the case where the two names
! ;; are not the same.
  
  ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
  ;; in your home directory is used for that.  Saving global default values
--- 51,116 ----
  ;; function is added to the `after-init-hook'. This function is
  ;; responsible for loading the desktop when Emacs is started.
  
! ;; Special handling.
! ;; -----------------
! ;; Variables `desktop-buffer-mode-handlers' and `desktop-minor-mode-handlers'
! ;; are supplied to handle special major and minor modes respectively.
! ;; `desktop-buffer-mode-handlers' is an alist of major mode specific functions
! ;; to restore a desktop buffer. Elements must have the form
! ;; 
! ;;    (MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
! ;; 
! ;; Functions listed are called by `desktop-create-buffer' when `desktop-read'
! ;; evaluates the desktop file. Buffers with a major mode not specified here,
! ;; are restored by the default handler `desktop-restore-file-buffer'.
! ;; `desktop-minor-mode-handlers' is an alist of functions to restore
! ;; non-standard minor modes.  Elements must have the form
! ;; 
! ;;    (MINOR-MODE . RESTORE-FUNCTION).
! ;; 
! ;; Functions are called by `desktop-create-buffer' to restore minor modes.
! ;; Minor modes not specified here, are restored by the standard minor mode
! ;; function.  If you write a module that defines a major or minor mode that
! ;; needs a special handler, then place code like
! 
! ;;    (defun foo-restore-desktop-buffer
! ;;    ...
! ;;    (add-to-list 'desktop-buffer-mode-handlers
! ;;                 '(foo-mode . foo-restore-desktop-buffer))
! 
! ;; or
! 
! ;;    (defun bar-desktop-restore
! ;;    ...
! ;;    (add-to-list 'desktop-minor-mode-handlers
! ;;                 '(bar-mode . bar-desktop-restore))
! 
! ;; in the module itself, and make shure that the mode function is
! ;; autoloaded. See the docstrings of `desktop-buffer-mode-handlers' and
! ;; `desktop-minor-mode-handlers' for more info.
! 
! ;; Minor modes.
! ;; ------------
! ;; Conventional minor modes (see node "Minor Mode Conventions" in the elisp
! ;; manual) are handled in the following way:
! ;; When `desktop-save' saves the state of a buffer to the desktop file, it
! ;; saves as `desktop-minor-modes' the list of names of those variables in
! ;; `minor-mode-alist' that have a non-nil value.
! ;; When `desktop-create' restores the buffer, each of the symbols in
! ;; `desktop-minor-modes' is called as function with parameter 1.
! ;; The variables `desktop-minor-mode-table' and `desktop-minor-mode-handlers'
! ;; are used to handle non-conventional minor modes.  `desktop-save' uses
! ;; `desktop-minor-mode-table' to map minor mode variables to minor mode
! ;; functions before writing `desktop-minor-modes'. If a minor mode has a
! ;; variable name that is different form its function name, an entry
! 
! ;;    (NAME RESTORE-FUNCTION)
! 
! ;; should be added to `desktop-minor-mode-table'.  If a minor mode should not
! ;; be restored, RESTORE-FUNCTION should be set to nil.  `desktop-create' uses
! ;; `desktop-minor-mode-handlers' to lookup minor modes that needs a restore
! ;; function different from the usual minor mode function.
! ;; ---------------------------------------------------------------------------
  
  ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
  ;; in your home directory is used for that.  Saving global default values
***************
*** 221,226 ****
--- 274,280 ----
    :type '(repeat string)
    :group 'desktop)
  
+ ;;;###autoload
  (defcustom desktop-locals-to-save
    '(desktop-locals-to-save  ; Itself!  Think it over.
      truncate-lines
***************
*** 230,238 ****
      overwrite-mode
      change-log-default-name
      line-number-mode
!     buffer-file-coding-system)
    "List of local variables to save for each buffer.
! The variables are saved only when they really are local."
    :type '(repeat symbol)
    :group 'desktop)
  (make-variable-buffer-local 'desktop-locals-to-save)
--- 284,299 ----
      overwrite-mode
      change-log-default-name
      line-number-mode
!     column-number-mode
!     size-indication-mode
!     buffer-file-coding-system
!     indent-tabs-mode
!     indicate-buffer-boundaries
!     indicate-empty-lines
!     show-trailing-whitespace)
    "List of local variables to save for each buffer.
! The variables are saved only when they really are local.  Conventional minor
! modes are restored automatically; they should not be listed here."
    :type '(repeat symbol)
    :group 'desktop)
  (make-variable-buffer-local 'desktop-locals-to-save)
***************
*** 301,323 ****
  When file names are returned, they should be formatted using the call
  \"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\".
  
! Later, when `desktop-read' calls a function in `desktop-buffer-mode-handlers'
! to restore the buffer, the auxiliary information is passed as the argument
! DESKTOP-BUFFER-MISC.")
  (make-variable-buffer-local 'desktop-save-buffer)
  (make-obsolete-variable 'desktop-buffer-modes-to-save
                          'desktop-save-buffer "22.1")
  (make-obsolete-variable 'desktop-buffer-misc-functions
                          'desktop-save-buffer "22.1")
  
! (defcustom desktop-buffer-mode-handlers
!   '((dired-mode . dired-restore-desktop-buffer)
!     (rmail-mode . rmail-restore-desktop-buffer)
!     (mh-folder-mode . mh-restore-desktop-buffer)
!     (Info-mode . Info-restore-desktop-buffer))
    "Alist of major mode specific functions to restore a desktop buffer.
! Functions are called by `desktop-read'.  List elements must have the form
! \(MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
  
  Buffers with a major mode not specified here, are restored by the default
  handler `desktop-restore-file-buffer'.
--- 362,384 ----
  When file names are returned, they should be formatted using the call
  \"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\".
  
! Later, when `desktop-read' evaluates the desktop file, auxiliary information
! is passed as the argument DESKTOP-BUFFER-MISC to functions in
! `desktop-buffer-mode-handlers'.")
  (make-variable-buffer-local 'desktop-save-buffer)
  (make-obsolete-variable 'desktop-buffer-modes-to-save
                          'desktop-save-buffer "22.1")
  (make-obsolete-variable 'desktop-buffer-misc-functions
                          'desktop-save-buffer "22.1")
  
! ;;;###autoload
! (defvar desktop-buffer-mode-handlers
!   nil
    "Alist of major mode specific functions to restore a desktop buffer.
! Functions listed are called by `desktop-create-buffer' when `desktop-read'
! evaluates the desktop file.  List elements must have the form
! 
!    (MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
  
  Buffers with a major mode not specified here, are restored by the default
  handler `desktop-restore-file-buffer'.
***************
*** 337,345 ****
     desktop-buffer-locals
  
  If a handler returns a buffer, then the saved mode settings
! and variable values for that buffer are copied into it."
!   :type 'alist
!   :group 'desktop)
  
  (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
  (make-obsolete-variable 'desktop-buffer-handlers
--- 398,414 ----
     desktop-buffer-locals
  
  If a handler returns a buffer, then the saved mode settings
! and variable values for that buffer are copied into it.
! 
! Modules that define a major mode that needs a special handler should contain
! code like
! 
!    (defun foo-restore-desktop-buffer
!    ...
!    (add-to-list 'desktop-buffer-mode-handlers
!                 '(foo-mode . foo-restore-desktop-buffer))
! 
! Furthermore the major mode function must be autoloaded.")
  
  (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
  (make-obsolete-variable 'desktop-buffer-handlers
***************
*** 355,364 ****
  called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
! this table."
    :type 'sexp
    :group 'desktop)
  
  ;; ----------------------------------------------------------------------------
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
--- 424,479 ----
  called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
! this table.  See also `desktop-minor-mode-handlers'."
    :type 'sexp
    :group 'desktop)
  
+ ;;;###autoload
+ (defvar desktop-minor-mode-handlers
+   nil
+   "Alist of functions to restore non-standard minor modes.
+ Functions are called by `desktop-create-buffer' to restore minor modes.
+ List elements must have the form
+ 
+    (MINOR-MODE . RESTORE-FUNCTION).
+ 
+ Minor modes not specified here, are restored by the standard minor mode
+ function.
+ 
+ Handlers are called with argument list
+ 
+    (DESKTOP-BUFFER-LOCALS)
+ 
+ Furthermore, they may use the following variables:
+ 
+    desktop-file-version
+    desktop-buffer-file-name
+    desktop-buffer-name
+    desktop-buffer-major-mode
+    desktop-buffer-minor-modes
+    desktop-buffer-point
+    desktop-buffer-mark
+    desktop-buffer-read-only
+    desktop-buffer-misc
+ 
+ When a handler is called, the buffer has been created and the major mode has
+ been set, but local variables listed in desktop-buffer-locals has not yet been
+ created and set.
+ 
+ Modules that define a minor mode that needs a special handler should contain
+ code like
+ 
+    (defun foo-desktop-restore
+    ...
+    (add-to-list 'desktop-minor-mode-handlers
+                 '(foo-mode . foo-desktop-restore))
+ 
+ Furthermore the minor mode function must be autoloaded.
+ 
+ See also `desktop-minor-mode-table'.")
+ 
+ (put 'desktop-minor-mode-handlers 'risky-local-variable t)
+ 
  ;; ----------------------------------------------------------------------------
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
***************
*** 622,633 ****
                            (and
                              (boundp minor-mode)
                              (symbol-value minor-mode)
!                             (let ((special (assq minor-mode desktop-minor-mode-table)))
!                               (when (or special (functionp minor-mode))
!                                 (setq ret
!                                   (cons
!                                     (if special (cadr special) minor-mode)
!                                     ret))))))
                          (mapcar #'car minor-mode-alist))
                        ret)
                      (point)
--- 737,746 ----
                            (and
                              (boundp minor-mode)
                              (symbol-value minor-mode)
!                             (let* ((special (assq minor-mode desktop-minor-mode-table))
!                                    (value (cond (special (cadr special))
!                                                 ((functionp minor-mode) minor-mode))))
!                               (when value (add-to-list 'ret value)))))
                          (mapcar #'car minor-mode-alist))
                        ret)
                      (point)
***************
*** 685,691 ****
                    (insert ")\n\n")))
              info)
        (setq default-directory dirname)
-       (when (file-exists-p filename) (delete-file filename))
        (let ((coding-system-for-write 'emacs-mule))
          (write-region (point-min) (point-max) filename nil 'nomessage))))
    (setq desktop-dirname dirname))
--- 798,803 ----
***************
*** 850,862 ****
  	    buf)
  	nil)))
  
  ;; ----------------------------------------------------------------------------
  ;; Create a buffer, load its file, set its mode, ...;
  ;; called from Desktop file only.
  
! (eval-when-compile ; Just to silence the byte compiler
!    (defvar desktop-first-buffer) ;; Dynamically bound in `desktop-read'
! )
  
  (defun desktop-create-buffer
    (desktop-file-version
--- 962,981 ----
  	    buf)
  	nil)))
  
+ (defun desktop-load-file (function)
+   "Load the file where auto loaded FUNCTION is defined."
+   (let ((fcell (symbol-function function)))
+     (when (and (listp fcell)
+                (eq 'autoload (car fcell)))
+       (load (cadr fcell)))))
+ 
  ;; ----------------------------------------------------------------------------
  ;; Create a buffer, load its file, set its mode, ...;
  ;; called from Desktop file only.
  
! ;; Just to silence the byte compiler.
! (eval-when-compile
!   (defvar desktop-first-buffer)) ; Dynamically bound in `desktop-read'
  
  (defun desktop-create-buffer
    (desktop-file-version
***************
*** 877,882 ****
--- 996,1003 ----
    ;; To make desktop files with relative file names possible, we cannot
    ;; allow `default-directory' to change. Therefore we save current buffer.
    (save-current-buffer
+     ;; Give major mode module a chance to add a handler.
+     (desktop-load-file desktop-buffer-major-mode)
      (let ((buffer-list (buffer-list))
            (result
             (condition-case err
***************
*** 914,922 ****
                 (auto-fill-mode 0))
                (t
                 (mapc #'(lambda (minor-mode)
! 			 (when (functionp minor-mode) (funcall minor-mode 1)))
  		     desktop-buffer-minor-modes)))
!         ;; Even though point and mark are non-nil when written by `desktop-save'
          ;; they may be modified by handlers wanting to set point or mark themselves.
          (when desktop-buffer-point
            (goto-char
--- 1035,1049 ----
                 (auto-fill-mode 0))
                (t
                 (mapc #'(lambda (minor-mode)
!                          ;; Give minor mode module a chance to add a handler.
!                          (desktop-load-file minor-mode)
!                          (let ((handler (cdr (assq minor-mode desktop-minor-mode-handlers))))
!                            (if handler
!                                (funcall handler desktop-buffer-locals)
!                              (when (functionp minor-mode)
!                                (funcall minor-mode 1)))))
  		     desktop-buffer-minor-modes)))
!         ;; Even though point and mark are non-nil when written by `desktop-save',
          ;; they may be modified by handlers wanting to set point or mark themselves.
          (when desktop-buffer-point
            (goto-char
*** /home/lh/cvsroot/emacs/lisp/hilit-chg.el	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.hilit-chg.el	2005-08-08 16:27:55.003611568 +0200
***************
*** 673,678 ****
--- 673,679 ----
  	(if new-highlight-changes-mode
  	    ;; mode is turned on -- but may be passive
  	    (progn
+ 	      (add-to-list 'desktop-locals-to-save 'highlight-changes-mode)
  	      (hilit-chg-set new-highlight-changes-mode)
  	      (or was-on
  		  ;; run highlight-changes-enable-hook once
***************
*** 1154,1159 ****
--- 1155,1170 ----
  		 )))
     (buffer-list)))
  
+ ;;;; Desktop support.
+ 
+ ;; Called by `desktop-create-buffer' to restore `highlight-changes-mode'.
+ (defun hilit-chg-desktop-restore (desktop-buffer-locals)
+   (highlight-changes-mode
+    (or (cdr (assq 'highlight-changes-mode desktop-buffer-locals)) 1)))
+ 
+ (add-to-list 'desktop-minor-mode-handlers
+              '(highlight-changes-mode . hilit-chg-desktop-restore))
+ 
  ;; ===================== debug ==================
  ;; For debug & test use:
  ;;
*** /home/lh/cvsroot/emacs/lisp/dired.el	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.dired.el	2005-08-08 16:28:28.824470016 +0200
***************
*** 1469,1474 ****
--- 1469,1476 ----
  ;; Dired mode is suitable only for specially formatted data.
  (put 'dired-mode 'mode-class 'special)
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (defun dired-mode (&optional dirname switches)
    "\
  Mode for \"editing\" directory listings.
***************
*** 3270,3276 ****
           (function (lambda (f) (desktop-file-name (car f) desktop-dirname)))
           dired-subdir-alist)))))
  
- ;;;###autoload
  (defun dired-restore-desktop-buffer (desktop-buffer-file-name
                                       desktop-buffer-name
                                       desktop-buffer-misc)
--- 3272,3277 ----
***************
*** 3291,3296 ****
--- 3292,3300 ----
        (when desktop-missing-file-warning (sit-for 1))
        nil)))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(dired-mode . dired-restore-desktop-buffer))
+ 
  \f
  (if (eq system-type 'vax-vms)
      (load "dired-vms"))
*** /home/lh/cvsroot/emacs/lisp/info.el	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.info.el	2005-08-08 16:29:18.743881112 +0200
***************
*** 3199,3204 ****
--- 3199,3206 ----
  
  (defvar tool-bar-map)
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (defun Info-mode ()
    "Info mode provides commands for browsing through the Info documentation tree.
  Documentation in Info is divided into \"nodes\", each of which discusses
***************
*** 4168,4174 ****
    (if (not (member Info-current-file '("apropos" "history" "toc")))
        (list Info-current-file Info-current-node)))
  
- ;;;###autoload
  (defun Info-restore-desktop-buffer (desktop-buffer-file-name
                                      desktop-buffer-name
                                      desktop-buffer-misc)
--- 4170,4175 ----
***************
*** 4182,4187 ****
--- 4183,4191 ----
      (Info-find-node first second)
      (current-buffer))))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(Info-mode . Info-restore-desktop-buffer))
+ 
  (provide 'info)
  
  ;; arch-tag: f2480fe2-2139-40c1-a49b-6314991164ac
*** /home/lh/cvsroot/emacs/lisp/mail/rmail.el	2005-08-08 14:15:19.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.rmail.el	2005-08-08 16:30:28.313304952 +0200
***************
*** 4058,4064 ****
  
  ;;;;  Desktop support
  
- ;;;###autoload
  (defun rmail-restore-desktop-buffer (desktop-buffer-file-name
                                       desktop-buffer-name
                                       desktop-buffer-misc)
--- 4058,4063 ----
***************
*** 4073,4078 ****
--- 4072,4080 ----
        (kill-buffer (current-buffer))
        nil)))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(rmail-mode . rmail-restore-desktop-buffer))
+ 
  (provide 'rmail)
  
  ;;; arch-tag: cff0a950-57fe-4f73-a86e-91ff75afd06c
*** /home/lh/cvsroot/emacs/lisp/mh-e/mh-e.el	2005-07-12 15:25:36.000000000 +0200
--- /home/lh/emacs/LH-work/desktop/new.mh-e.el	2005-08-06 07:26:37.000000000 +0200
***************
*** 1507,1512 ****
--- 1507,1514 ----
             (not (member 'mh-folder-mode which-func-modes)))
    (push 'mh-folder-mode which-func-modes))
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
    "Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
  
***************
*** 1653,1659 ****
      (set (make-local-variable (car pairs)) (car (cdr pairs)))
      (setq pairs (cdr (cdr pairs)))))
  
- ;;;###autoload
  (defun mh-restore-desktop-buffer (desktop-buffer-file-name
                                    desktop-buffer-name
                                    desktop-buffer-misc)
--- 1655,1660 ----
***************
*** 1666,1671 ****
--- 1667,1675 ----
    (mh-visit-folder desktop-buffer-name)
    (current-buffer))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(mh-folder-mode . mh-restore-desktop-buffer))
+ 
  (defun mh-scan-folder (folder range &optional dont-exec-pending)
    "Scan the FOLDER over the RANGE.
  If the optional argument DONT-EXEC-PENDING is non-nil then pending deletes and

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 10:53 ` Juanma Barranquero
  2005-07-22 22:52   ` Richard M. Stallman
@ 2005-08-08 15:02   ` Lars Hansen
  1 sibling, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-08 15:02 UTC (permalink / raw)


Juanma Barranquero wrote:

>In fact, I'm not sure what criterion is used to decide the default
>value of `desktop-locals-to-save'.
>
I guess it should include variables set directly or indirectly by the
user to control
some kind of customization, minor modes excluded. But that's not exactly
a precise
criterion :-)

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-22 14:36   ` Juanma Barranquero
  2005-07-26  8:27     ` Juanma Barranquero
@ 2005-08-08 15:04     ` Lars Hansen
  1 sibling, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-08 15:04 UTC (permalink / raw)
  Cc: emacs-devel

Juanma Barranquero wrote:

>It is really necessary to delete the file prior to `write-region' it?
>  
>
I don't know of any reason why it should be necessary. To me it looks bad.
My patch (included in a prior post) deletes the deletion :-)

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-08 14:51 ` Lars Hansen
@ 2005-08-08 18:35   ` Juanma Barranquero
  2005-08-09  7:12     ` Lars Hansen
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-08-08 18:35 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

On 8/8/05, Lars Hansen <larsh@soem.dk> wrote:

> I don't think there is any good reason. The patch below includes your
> suggested change

In general I like your patch. A few more questions, though.

 - Why is desktop-locals-to-save automatically buffer local? I can
understand why should it be buffer-local, but automatically? I'd think
that most users/modes are simply going to add to the default value of
the variable. Or am I missing something?

 - Why is necessary to have `desktop-clear-preserve-buffers-regexp'
and `desktop-clear-preserve-buffers'? The first one cannot be modified
programmatically (there's no general way to automatically modify the
regexp), so modes trying to extend the list of preservable buffers
will have to add to `desktop-clear-preserve-buffers', which does not
accept regexps. I think it would be better to have just one list
(accepting regexps) and then combine them into a single regexp on
demand.

 - You say:

> This function assumes that the mode function is autoloaded. Is this
> requirement ok?  Is there a better solution?

Wouldn't suffice to add the requeriment that when a mode wants to add
to `desktop-*-mode-handlers', the added function *must* be autoloaded?

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-08 18:35   ` Juanma Barranquero
@ 2005-08-09  7:12     ` Lars Hansen
  2005-08-09  7:36       ` Lars Hansen
  2005-08-09  8:49       ` Juanma Barranquero
  0 siblings, 2 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-09  7:12 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

Juanma Barranquero wrote:

> - Why is desktop-locals-to-save automatically buffer local? I can
>understand why should it be buffer-local, but automatically? I'd think
>that most users/modes are simply going to add to the default value of
>the variable. Or am I missing something?
>  
>
I guess it does not have to be automatically buffer local. But I am not
shure what the advantages/disadvantages of either choice are.

>I think it would be better to have just one list
>(accepting regexps) and then combine them into a single regexp on
>demand.
>  
>
I agree. I will change that.

>Wouldn't suffice to add the requeriment that when a mode wants to add
>to `desktop-*-mode-handlers', the added function *must* be autoloaded?
>  
>
No. Desktop does not know that there *is* a handler since it may not
have been added to `desktop-*-mode-handlers' yet.

My motive is to make desktop as independent of other modules as
possible. I want it to be possible to add or change module foo without
having to change desktop, even if foo requires special desktop handling.
Therefore I want foo to not only define its own desktop handler, but to
add it to the variable `desktop-*-mode-handlers' as well. But then
desktop has to load foo before checking for a handler. But how can
desktop find out what file to load? It knows the name of the mode (major
or minor), so if the mode function is autoloaded, it can find the file
name that way.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-09  7:12     ` Lars Hansen
@ 2005-08-09  7:36       ` Lars Hansen
  2005-08-09  8:49       ` Juanma Barranquero
  1 sibling, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-09  7:36 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

I wrote:

>I agree. I will change that.
>  
>
Now I remember that I added `desktop-clear-preserve-buffers-regexp' to
obtain backwards compatibility. If `desktop-clear-preserve-buffers' is
changed to accept regexps, strings like "*Messages*" get another
meaning, so they must be changed.

But it's messy with those two variable, so I still think it should be
changed. I guess the compatibility issue is minor.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-09  7:12     ` Lars Hansen
  2005-08-09  7:36       ` Lars Hansen
@ 2005-08-09  8:49       ` Juanma Barranquero
  2005-08-09  9:31         ` David Kastrup
  1 sibling, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-08-09  8:49 UTC (permalink / raw)
  Cc: emacs-devel

On 8/9/05, Lars Hansen <larsh@soem.dk> wrote:

> I guess it does not have to be automatically buffer local. But I am not
> shure what the advantages/disadvantages of either choice are.

Well, the reason `make-local-variable' and
`make-variable-buffer-local' both exists is, I think, that in some
circumstances the default value of the variable is gonna weight more
than local changes (i.e, the local changes are going to be few and far
between), and in other cases the variable is going to have frequent
buffer-local modifications. Using the latter style when the former
works is not "bad", but it's a bit wasteful.

In this case, I think the former case is much more frequent; the user,
or the mode programmer, can always use `make-local-variable' to force
their way when a really local value is needed.

> My motive is to make desktop as independent of other modules as
> possible. I want it to be possible to add or change module foo without
> having to change desktop, even if foo requires special desktop handling.

Yes, that's a worthwhile goal.

> But how can
> desktop find out what file to load? It knows the name of the mode (major
> or minor), so if the mode function is autoloaded, it can find the file
> name that way.

OK, I see now.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-09  8:49       ` Juanma Barranquero
@ 2005-08-09  9:31         ` David Kastrup
  2005-08-09  9:59           ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: David Kastrup @ 2005-08-09  9:31 UTC (permalink / raw)
  Cc: Lars Hansen, emacs-devel

Juanma Barranquero <lekktu@gmail.com> writes:

> On 8/9/05, Lars Hansen <larsh@soem.dk> wrote:
>
>> I guess it does not have to be automatically buffer local. But I am
>> not shure what the advantages/disadvantages of either choice are.
>
> Well, the reason `make-local-variable' and
> `make-variable-buffer-local' both exists is, I think, that in some
> circumstances the default value of the variable is gonna weight more
> than local changes (i.e, the local changes are going to be few and far
> between), and in other cases the variable is going to have frequent
> buffer-local modifications. Using the latter style when the former
> works is not "bad", but it's a bit wasteful.

I tend to use make-variable-buffer-local when a variable is tracking
some state of a buffer, such that it would always be an error if two
buffers shared such a variable.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-09  9:31         ` David Kastrup
@ 2005-08-09  9:59           ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2005-08-09  9:59 UTC (permalink / raw)
  Cc: Lars Hansen, emacs-devel

On 8/9/05, David Kastrup <dak@gnu.org> wrote:

> I tend to use make-variable-buffer-local when a variable is tracking
> some state of a buffer, such that it would always be an error if two
> buffers shared such a variable.

Sure. For example, any variable that tracks something related to
external characteristics of the buffer (or the buffer's associated
file, if any) must usually be automatically buffer-local.

In the case at hand, I think most buffers will want the same
`desktop-locals-to-save'. I can imagine buffer X in mode M wanting to
save its value of LOCAL-VAR-1, and buffer Y also in mode M wanting to
save its own LOCAL-VAR-1, but it will be less frequent for buffer X to
want to save LOCAL-VAR-1 and for buffer Y *not* wanting to save it.

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:16       ` Juanma Barranquero
  2005-07-28  3:20         ` Richard M. Stallman
@ 2005-08-10  9:50         ` Lars Hansen
  2005-08-10 11:24           ` Juanma Barranquero
  2005-08-10 22:05           ` Luc Teirlinck
  1 sibling, 2 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-10  9:50 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 336 bytes --]

Juanma Barranquero wrote:

>Anyway, I'd prefer not to make many changes to desktop.el (even quite
>non-intrusive changes like these) until Lars returns from holidays, as
>he said he would take a look at some questions I posed. I'll post a
>patch as soon as I've got it ready, and wait for him.
>  
>
Shall I install the attached patch?

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 24358 bytes --]

*** /home/lh/cvsroot/emacs/lisp/desktop.el.~1.90.~	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/desktop.el	2005-08-10 11:38:08.519228192 +0200
***************
*** 51,63 ****
  ;; function is added to the `after-init-hook'. This function is
  ;; responsible for loading the desktop when Emacs is started.
  
! ;; Some words on minor modes: Most minor modes are controlled by
! ;; buffer-local variables, which have a standard save / restore
! ;; mechanism.  To handle all minor modes, we take the following
! ;; approach: (1) check whether the variable name from
! ;; `minor-mode-alist' is also a function; and (2) use translation
! ;; table `desktop-minor-mode-table' in the case where the two names
! ;; are not the same.
  
  ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
  ;; in your home directory is used for that.  Saving global default values
--- 51,116 ----
  ;; function is added to the `after-init-hook'. This function is
  ;; responsible for loading the desktop when Emacs is started.
  
! ;; Special handling.
! ;; -----------------
! ;; Variables `desktop-buffer-mode-handlers' and `desktop-minor-mode-handlers'
! ;; are supplied to handle special major and minor modes respectively.
! ;; `desktop-buffer-mode-handlers' is an alist of major mode specific functions
! ;; to restore a desktop buffer. Elements must have the form
! ;; 
! ;;    (MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
! ;; 
! ;; Functions listed are called by `desktop-create-buffer' when `desktop-read'
! ;; evaluates the desktop file. Buffers with a major mode not specified here,
! ;; are restored by the default handler `desktop-restore-file-buffer'.
! ;; `desktop-minor-mode-handlers' is an alist of functions to restore
! ;; non-standard minor modes.  Elements must have the form
! ;; 
! ;;    (MINOR-MODE . RESTORE-FUNCTION).
! ;; 
! ;; Functions are called by `desktop-create-buffer' to restore minor modes.
! ;; Minor modes not specified here, are restored by the standard minor mode
! ;; function.  If you write a module that defines a major or minor mode that
! ;; needs a special handler, then place code like
! 
! ;;    (defun foo-restore-desktop-buffer
! ;;    ...
! ;;    (add-to-list 'desktop-buffer-mode-handlers
! ;;                 '(foo-mode . foo-restore-desktop-buffer))
! 
! ;; or
! 
! ;;    (defun bar-desktop-restore
! ;;    ...
! ;;    (add-to-list 'desktop-minor-mode-handlers
! ;;                 '(bar-mode . bar-desktop-restore))
! 
! ;; in the module itself, and make shure that the mode function is
! ;; autoloaded. See the docstrings of `desktop-buffer-mode-handlers' and
! ;; `desktop-minor-mode-handlers' for more info.
! 
! ;; Minor modes.
! ;; ------------
! ;; Conventional minor modes (see node "Minor Mode Conventions" in the elisp
! ;; manual) are handled in the following way:
! ;; When `desktop-save' saves the state of a buffer to the desktop file, it
! ;; saves as `desktop-minor-modes' the list of names of those variables in
! ;; `minor-mode-alist' that have a non-nil value.
! ;; When `desktop-create' restores the buffer, each of the symbols in
! ;; `desktop-minor-modes' is called as function with parameter 1.
! ;; The variables `desktop-minor-mode-table' and `desktop-minor-mode-handlers'
! ;; are used to handle non-conventional minor modes.  `desktop-save' uses
! ;; `desktop-minor-mode-table' to map minor mode variables to minor mode
! ;; functions before writing `desktop-minor-modes'. If a minor mode has a
! ;; variable name that is different form its function name, an entry
! 
! ;;    (NAME RESTORE-FUNCTION)
! 
! ;; should be added to `desktop-minor-mode-table'.  If a minor mode should not
! ;; be restored, RESTORE-FUNCTION should be set to nil.  `desktop-create' uses
! ;; `desktop-minor-mode-handlers' to lookup minor modes that needs a restore
! ;; function different from the usual minor mode function.
! ;; ---------------------------------------------------------------------------
  
  ;; By the way: don't use desktop.el to customize Emacs -- the file .emacs
  ;; in your home directory is used for that.  Saving global default values
***************
*** 207,226 ****
    :group 'desktop
    :version "22.1")
  
! (defcustom desktop-clear-preserve-buffers-regexp
!   "^\\(\\*scratch\\*\\|\\*Messages\\*\\|\\*server\\*\\|\\*tramp/.+\\*\\)$"
!   "Regexp identifying buffers that `desktop-clear' should not delete.
! See also `desktop-clear-preserve-buffers'."
!   :type 'regexp
!   :group 'desktop
!   :version "22.1")
! 
! (defcustom desktop-clear-preserve-buffers nil
!   "*List of buffer names that `desktop-clear' should not delete.
! See also `desktop-clear-preserve-buffers-regexp'."
    :type '(repeat string)
    :group 'desktop)
  
  (defcustom desktop-locals-to-save
    '(desktop-locals-to-save  ; Itself!  Think it over.
      truncate-lines
--- 260,274 ----
    :group 'desktop
    :version "22.1")
  
! (defcustom desktop-clear-preserve-buffers
!   '("\\*scratch\\*" "\\*Messages\\*" "\\*server\\*" "\\*tramp/.+\\*")
!   "*List of buffers that `desktop-clear' should not delete.
! Each element is a regular expression.  Buffers with a name matched by any of
! these won't be deleted."
    :type '(repeat string)
    :group 'desktop)
  
+ ;;;###autoload
  (defcustom desktop-locals-to-save
    '(desktop-locals-to-save  ; Itself!  Think it over.
      truncate-lines
***************
*** 230,241 ****
      overwrite-mode
      change-log-default-name
      line-number-mode
!     buffer-file-coding-system)
    "List of local variables to save for each buffer.
! The variables are saved only when they really are local."
    :type '(repeat symbol)
    :group 'desktop)
- (make-variable-buffer-local 'desktop-locals-to-save)
  
  ;; We skip .log files because they are normally temporary.
  ;;         (ftp) files because they require passwords and whatnot.
--- 278,295 ----
      overwrite-mode
      change-log-default-name
      line-number-mode
!     column-number-mode
!     size-indication-mode
!     buffer-file-coding-system
!     indent-tabs-mode
!     indicate-buffer-boundaries
!     indicate-empty-lines
!     show-trailing-whitespace)
    "List of local variables to save for each buffer.
! The variables are saved only when they really are local.  Conventional minor
! modes are restored automatically; they should not be listed here."
    :type '(repeat symbol)
    :group 'desktop)
  
  ;; We skip .log files because they are normally temporary.
  ;;         (ftp) files because they require passwords and whatnot.
***************
*** 301,323 ****
  When file names are returned, they should be formatted using the call
  \"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\".
  
! Later, when `desktop-read' calls a function in `desktop-buffer-mode-handlers'
! to restore the buffer, the auxiliary information is passed as the argument
! DESKTOP-BUFFER-MISC.")
  (make-variable-buffer-local 'desktop-save-buffer)
  (make-obsolete-variable 'desktop-buffer-modes-to-save
                          'desktop-save-buffer "22.1")
  (make-obsolete-variable 'desktop-buffer-misc-functions
                          'desktop-save-buffer "22.1")
  
! (defcustom desktop-buffer-mode-handlers
!   '((dired-mode . dired-restore-desktop-buffer)
!     (rmail-mode . rmail-restore-desktop-buffer)
!     (mh-folder-mode . mh-restore-desktop-buffer)
!     (Info-mode . Info-restore-desktop-buffer))
    "Alist of major mode specific functions to restore a desktop buffer.
! Functions are called by `desktop-read'.  List elements must have the form
! \(MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
  
  Buffers with a major mode not specified here, are restored by the default
  handler `desktop-restore-file-buffer'.
--- 355,377 ----
  When file names are returned, they should be formatted using the call
  \"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\".
  
! Later, when `desktop-read' evaluates the desktop file, auxiliary information
! is passed as the argument DESKTOP-BUFFER-MISC to functions in
! `desktop-buffer-mode-handlers'.")
  (make-variable-buffer-local 'desktop-save-buffer)
  (make-obsolete-variable 'desktop-buffer-modes-to-save
                          'desktop-save-buffer "22.1")
  (make-obsolete-variable 'desktop-buffer-misc-functions
                          'desktop-save-buffer "22.1")
  
! ;;;###autoload
! (defvar desktop-buffer-mode-handlers
!   nil
    "Alist of major mode specific functions to restore a desktop buffer.
! Functions listed are called by `desktop-create-buffer' when `desktop-read'
! evaluates the desktop file.  List elements must have the form
! 
!    (MAJOR-MODE . RESTORE-BUFFER-FUNCTION).
  
  Buffers with a major mode not specified here, are restored by the default
  handler `desktop-restore-file-buffer'.
***************
*** 337,345 ****
     desktop-buffer-locals
  
  If a handler returns a buffer, then the saved mode settings
! and variable values for that buffer are copied into it."
!   :type 'alist
!   :group 'desktop)
  
  (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
  (make-obsolete-variable 'desktop-buffer-handlers
--- 391,407 ----
     desktop-buffer-locals
  
  If a handler returns a buffer, then the saved mode settings
! and variable values for that buffer are copied into it.
! 
! Modules that define a major mode that needs a special handler should contain
! code like
! 
!    (defun foo-restore-desktop-buffer
!    ...
!    (add-to-list 'desktop-buffer-mode-handlers
!                 '(foo-mode . foo-restore-desktop-buffer))
! 
! Furthermore the major mode function must be autoloaded.")
  
  (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
  (make-obsolete-variable 'desktop-buffer-handlers
***************
*** 355,364 ****
  called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
! this table."
    :type 'sexp
    :group 'desktop)
  
  ;; ----------------------------------------------------------------------------
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
--- 417,472 ----
  called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
! this table.  See also `desktop-minor-mode-handlers'."
    :type 'sexp
    :group 'desktop)
  
+ ;;;###autoload
+ (defvar desktop-minor-mode-handlers
+   nil
+   "Alist of functions to restore non-standard minor modes.
+ Functions are called by `desktop-create-buffer' to restore minor modes.
+ List elements must have the form
+ 
+    (MINOR-MODE . RESTORE-FUNCTION).
+ 
+ Minor modes not specified here, are restored by the standard minor mode
+ function.
+ 
+ Handlers are called with argument list
+ 
+    (DESKTOP-BUFFER-LOCALS)
+ 
+ Furthermore, they may use the following variables:
+ 
+    desktop-file-version
+    desktop-buffer-file-name
+    desktop-buffer-name
+    desktop-buffer-major-mode
+    desktop-buffer-minor-modes
+    desktop-buffer-point
+    desktop-buffer-mark
+    desktop-buffer-read-only
+    desktop-buffer-misc
+ 
+ When a handler is called, the buffer has been created and the major mode has
+ been set, but local variables listed in desktop-buffer-locals has not yet been
+ created and set.
+ 
+ Modules that define a minor mode that needs a special handler should contain
+ code like
+ 
+    (defun foo-desktop-restore
+    ...
+    (add-to-list 'desktop-minor-mode-handlers
+                 '(foo-mode . foo-desktop-restore))
+ 
+ Furthermore the minor mode function must be autoloaded.
+ 
+ See also `desktop-minor-mode-table'.")
+ 
+ (put 'desktop-minor-mode-handlers 'risky-local-variable t)
+ 
  ;; ----------------------------------------------------------------------------
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
***************
*** 382,404 ****
  ;; ----------------------------------------------------------------------------
  (defun desktop-clear ()
    "Empty the Desktop.
! This kills all buffers except for internal ones and those matching
! `desktop-clear-preserve-buffers-regexp' or listed in
! `desktop-clear-preserve-buffers'.  Furthermore, it clears the
! variables listed in `desktop-globals-to-clear'."
    (interactive)
    (desktop-lazy-abort)
    (dolist (var desktop-globals-to-clear)
      (if (symbolp var)
        (eval `(setq-default ,var nil))
        (eval `(setq-default ,(car var) ,(cdr var)))))
!   (let ((buffers (buffer-list)))
      (while buffers
        (let ((bufname (buffer-name (car buffers))))
           (or
             (null bufname)
!            (string-match desktop-clear-preserve-buffers-regexp bufname)
!            (member bufname desktop-clear-preserve-buffers)
             ;; Don't kill buffers made for internal purposes.
             (and (not (equal bufname "")) (eq (aref bufname 0) ?\s))
             (kill-buffer (car buffers))))
--- 490,516 ----
  ;; ----------------------------------------------------------------------------
  (defun desktop-clear ()
    "Empty the Desktop.
! This kills all buffers except for internal ones and those with names matched by
! a regular expression in the list `desktop-clear-preserve-buffers'.
! Furthermore, it clears the variables listed in `desktop-globals-to-clear'."
    (interactive)
    (desktop-lazy-abort)
    (dolist (var desktop-globals-to-clear)
      (if (symbolp var)
        (eval `(setq-default ,var nil))
        (eval `(setq-default ,(car var) ,(cdr var)))))
!   (let ((buffers (buffer-list))
!         (preserve-regexp (concat "^\\("
!                                  (mapconcat (lambda (regexp)
!                                               (concat "\\(" regexp "\\)"))
!                                             desktop-clear-preserve-buffers
!                                             "\\|")
!                                  "\\)$")))
      (while buffers
        (let ((bufname (buffer-name (car buffers))))
           (or
             (null bufname)
!            (string-match preserve-regexp bufname)
             ;; Don't kill buffers made for internal purposes.
             (and (not (equal bufname "")) (eq (aref bufname 0) ?\s))
             (kill-buffer (car buffers))))
***************
*** 622,633 ****
                            (and
                              (boundp minor-mode)
                              (symbol-value minor-mode)
!                             (let ((special (assq minor-mode desktop-minor-mode-table)))
!                               (when (or special (functionp minor-mode))
!                                 (setq ret
!                                   (cons
!                                     (if special (cadr special) minor-mode)
!                                     ret))))))
                          (mapcar #'car minor-mode-alist))
                        ret)
                      (point)
--- 734,743 ----
                            (and
                              (boundp minor-mode)
                              (symbol-value minor-mode)
!                             (let* ((special (assq minor-mode desktop-minor-mode-table))
!                                    (value (cond (special (cadr special))
!                                                 ((functionp minor-mode) minor-mode))))
!                               (when value (add-to-list 'ret value)))))
                          (mapcar #'car minor-mode-alist))
                        ret)
                      (point)
***************
*** 685,691 ****
                    (insert ")\n\n")))
              info)
        (setq default-directory dirname)
-       (when (file-exists-p filename) (delete-file filename))
        (let ((coding-system-for-write 'emacs-mule))
          (write-region (point-min) (point-max) filename nil 'nomessage))))
    (setq desktop-dirname dirname))
--- 795,800 ----
***************
*** 850,862 ****
  	    buf)
  	nil)))
  
  ;; ----------------------------------------------------------------------------
  ;; Create a buffer, load its file, set its mode, ...;
  ;; called from Desktop file only.
  
! (eval-when-compile ; Just to silence the byte compiler
!    (defvar desktop-first-buffer) ;; Dynamically bound in `desktop-read'
! )
  
  (defun desktop-create-buffer
    (desktop-file-version
--- 959,978 ----
  	    buf)
  	nil)))
  
+ (defun desktop-load-file (function)
+   "Load the file where auto loaded FUNCTION is defined."
+   (let ((fcell (symbol-function function)))
+     (when (and (listp fcell)
+                (eq 'autoload (car fcell)))
+       (load (cadr fcell)))))
+ 
  ;; ----------------------------------------------------------------------------
  ;; Create a buffer, load its file, set its mode, ...;
  ;; called from Desktop file only.
  
! ;; Just to silence the byte compiler.
! (eval-when-compile
!   (defvar desktop-first-buffer)) ; Dynamically bound in `desktop-read'
  
  (defun desktop-create-buffer
    (desktop-file-version
***************
*** 877,882 ****
--- 993,1000 ----
    ;; To make desktop files with relative file names possible, we cannot
    ;; allow `default-directory' to change. Therefore we save current buffer.
    (save-current-buffer
+     ;; Give major mode module a chance to add a handler.
+     (desktop-load-file desktop-buffer-major-mode)
      (let ((buffer-list (buffer-list))
            (result
             (condition-case err
***************
*** 914,922 ****
                 (auto-fill-mode 0))
                (t
                 (mapc #'(lambda (minor-mode)
! 			 (when (functionp minor-mode) (funcall minor-mode 1)))
  		     desktop-buffer-minor-modes)))
!         ;; Even though point and mark are non-nil when written by `desktop-save'
          ;; they may be modified by handlers wanting to set point or mark themselves.
          (when desktop-buffer-point
            (goto-char
--- 1032,1046 ----
                 (auto-fill-mode 0))
                (t
                 (mapc #'(lambda (minor-mode)
!                          ;; Give minor mode module a chance to add a handler.
!                          (desktop-load-file minor-mode)
!                          (let ((handler (cdr (assq minor-mode desktop-minor-mode-handlers))))
!                            (if handler
!                                (funcall handler desktop-buffer-locals)
!                              (when (functionp minor-mode)
!                                (funcall minor-mode 1)))))
  		     desktop-buffer-minor-modes)))
!         ;; Even though point and mark are non-nil when written by `desktop-save',
          ;; they may be modified by handlers wanting to set point or mark themselves.
          (when desktop-buffer-point
            (goto-char
*** /home/lh/cvsroot/emacs/lisp/hilit-chg.el.~1.34.~	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/hilit-chg.el	2005-08-09 08:17:02.000000000 +0200
***************
*** 673,678 ****
--- 673,679 ----
  	(if new-highlight-changes-mode
  	    ;; mode is turned on -- but may be passive
  	    (progn
+ 	      (add-to-list 'desktop-locals-to-save 'highlight-changes-mode)
  	      (hilit-chg-set new-highlight-changes-mode)
  	      (or was-on
  		  ;; run highlight-changes-enable-hook once
***************
*** 1154,1159 ****
--- 1155,1170 ----
  		 )))
     (buffer-list)))
  
+ ;;;; Desktop support.
+ 
+ ;; Called by `desktop-create-buffer' to restore `highlight-changes-mode'.
+ (defun hilit-chg-desktop-restore (desktop-buffer-locals)
+   (highlight-changes-mode
+    (or (cdr (assq 'highlight-changes-mode desktop-buffer-locals)) 1)))
+ 
+ (add-to-list 'desktop-minor-mode-handlers
+              '(highlight-changes-mode . hilit-chg-desktop-restore))
+ 
  ;; ===================== debug ==================
  ;; For debug & test use:
  ;;
*** /home/lh/cvsroot/emacs/lisp/dired.el.~1.322.~	2005-08-08 14:15:26.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/dired.el	2005-08-09 08:16:24.000000000 +0200
***************
*** 1469,1474 ****
--- 1469,1476 ----
  ;; Dired mode is suitable only for specially formatted data.
  (put 'dired-mode 'mode-class 'special)
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (defun dired-mode (&optional dirname switches)
    "\
  Mode for \"editing\" directory listings.
***************
*** 3270,3276 ****
           (function (lambda (f) (desktop-file-name (car f) desktop-dirname)))
           dired-subdir-alist)))))
  
- ;;;###autoload
  (defun dired-restore-desktop-buffer (desktop-buffer-file-name
                                       desktop-buffer-name
                                       desktop-buffer-misc)
--- 3272,3277 ----
***************
*** 3291,3296 ****
--- 3292,3300 ----
        (when desktop-missing-file-warning (sit-for 1))
        nil)))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(dired-mode . dired-restore-desktop-buffer))
+ 
  \f
  (if (eq system-type 'vax-vms)
      (load "dired-vms"))
*** /home/lh/cvsroot/emacs/lisp/info.el.~1.440.~	2005-08-09 08:01:44.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/info.el	2005-08-09 08:17:47.000000000 +0200
***************
*** 3199,3204 ****
--- 3199,3206 ----
  
  (defvar tool-bar-map)
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (defun Info-mode ()
    "Info mode provides commands for browsing through the Info documentation tree.
  Documentation in Info is divided into \"nodes\", each of which discusses
***************
*** 4168,4174 ****
    (if (not (member Info-current-file '("apropos" "history" "toc")))
        (list Info-current-file Info-current-node)))
  
- ;;;###autoload
  (defun Info-restore-desktop-buffer (desktop-buffer-file-name
                                      desktop-buffer-name
                                      desktop-buffer-misc)
--- 4170,4175 ----
***************
*** 4182,4187 ****
--- 4183,4191 ----
      (Info-find-node first second)
      (current-buffer))))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(Info-mode . Info-restore-desktop-buffer))
+ 
  (provide 'info)
  
  ;; arch-tag: f2480fe2-2139-40c1-a49b-6314991164ac
*** /home/lh/cvsroot/emacs/lisp/mail/rmail.el.~1.407.~	2005-08-08 14:15:19.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/mail/rmail.el	2005-08-09 08:19:09.000000000 +0200
***************
*** 4058,4064 ****
  
  ;;;;  Desktop support
  
- ;;;###autoload
  (defun rmail-restore-desktop-buffer (desktop-buffer-file-name
                                       desktop-buffer-name
                                       desktop-buffer-misc)
--- 4058,4063 ----
***************
*** 4073,4078 ****
--- 4072,4080 ----
        (kill-buffer (current-buffer))
        nil)))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(rmail-mode . rmail-restore-desktop-buffer))
+ 
  (provide 'rmail)
  
  ;;; arch-tag: cff0a950-57fe-4f73-a86e-91ff75afd06c
*** /home/lh/cvsroot/emacs/lisp/mh-e/mh-e.el.~1.20.~	2005-07-12 15:25:36.000000000 +0200
--- /home/lh/cvsroot/emacs/lisp/mh-e/mh-e.el	2005-08-09 08:18:27.000000000 +0200
***************
*** 1507,1512 ****
--- 1507,1514 ----
             (not (member 'mh-folder-mode which-func-modes)))
    (push 'mh-folder-mode which-func-modes))
  
+ ;; Autoload cookie needed by desktop.el
+ ;;;###autoload
  (define-derived-mode mh-folder-mode fundamental-mode "MH-Folder"
    "Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
  
***************
*** 1653,1659 ****
      (set (make-local-variable (car pairs)) (car (cdr pairs)))
      (setq pairs (cdr (cdr pairs)))))
  
- ;;;###autoload
  (defun mh-restore-desktop-buffer (desktop-buffer-file-name
                                    desktop-buffer-name
                                    desktop-buffer-misc)
--- 1655,1660 ----
***************
*** 1666,1671 ****
--- 1667,1675 ----
    (mh-visit-folder desktop-buffer-name)
    (current-buffer))
  
+ (add-to-list 'desktop-buffer-mode-handlers
+              '(mh-folder-mode . mh-restore-desktop-buffer))
+ 
  (defun mh-scan-folder (folder range &optional dont-exec-pending)
    "Scan the FOLDER over the RANGE.
  If the optional argument DONT-EXEC-PENDING is non-nil then pending deletes and

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-10  9:50         ` Lars Hansen
@ 2005-08-10 11:24           ` Juanma Barranquero
  2006-02-09 16:30             ` Juanma Barranquero
  2005-08-10 22:05           ` Luc Teirlinck
  1 sibling, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2005-08-10 11:24 UTC (permalink / raw)
  Cc: emacs-devel

On 8/10/05, Lars Hansen <larsh@soem.dk> wrote:

> Shall I install the attached patch?

You got my vote. I've been testing it and everything seems to work,
even the corner cases of `highlight-changes-mode'.

BTW, another package that would benefit from special treatment is
bs.el, in particular the variable `bs-buffer-show-mark'. I usually
have documents loaded (like my TODO) that I mark as "never to be
shown". On restoring the desktop they should stay so. Adding the
variable to the locals-to-save list is easy enough, of course.

The only (very minor) problem is, if the only buffer you have is
marked as 'never, after restoring the desktop the file is shown. It
should instead show the default *scratch*, I think.

I'm not sure whether this can be fixed with a support function in bs,
though. Properly speaking, bs is not a minor mode, and in fact the
"*buffer-selection*" buffer is not being restored...

-- 
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-10  9:50         ` Lars Hansen
  2005-08-10 11:24           ` Juanma Barranquero
@ 2005-08-10 22:05           ` Luc Teirlinck
  2005-08-10 23:45             ` Luc Teirlinck
  1 sibling, 1 reply; 72+ messages in thread
From: Luc Teirlinck @ 2005-08-10 22:05 UTC (permalink / raw)
  Cc: lekktu, rms, emacs-devel

Lars Hansen wrote:

   Shall I install the attached patch?

The installed changes apparently break bootstrapping:

Compiling /home/teirllm/emacscvsdir/emacs/lisp/./dired-x.el

In toplevel form:
dired-x.el:106:1:Error: Symbol's value as variable is void:
desktop-buffer-mode-handlers
make[1]: *** [compile] Error 1
make[1]: Leaving directory `/home/teirllm/emacscvsdir/emacs/lisp'
make: *** [bootstrap-build] Error 2

This after:

make maintainer-clean
./configure --without-toolkit-scroll-bars
make bootstrap
sudo make install

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-10 22:05           ` Luc Teirlinck
@ 2005-08-10 23:45             ` Luc Teirlinck
  2005-08-11  1:12               ` Luc Teirlinck
  0 siblings, 1 reply; 72+ messages in thread
From: Luc Teirlinck @ 2005-08-10 23:45 UTC (permalink / raw)
  Cc: larsh, lekktu, rms

The trouble during bootstrapping seems to involve the relationship
between loaddefs.el and ldefs-boot, "explained" (sort of) in lisp/Makefile.in:

# Prepare a bootstrap in the lisp subdirectory.
#
# Build loaddefs.el to make sure it's up-to-date.  If it's not, that
# might lead to errors during the bootstrap because something fails to
# autoload as expected.  If there is no emacs binary, then we can't
# build autoloads yet.  In that case we have to use ldefs-boot.el;
# bootstrap should always work with ldefs-boot.el.  (Because
# loaddefs.el is an automatically generated file, we don't want to
# store it in the source repository).

But ldefs-boot.el claims to be automatically generated too and it
appears to be stored in the source repository.

desktop-buffer-mode-handlers has a (new) autoload cookie.  That makes
it into loaddefs.el, but not into ldefs-boot.el, which is apparently
necessary for bootstrapping.

I can make bootstrapping work by manually copying the defvar for
desktop-buffer-mode-handlers from loaddefs to ldefs-boot.  I could
install this "fix".  However, this does not seem to be the right thing
to do, since ldefs-boot apparently is supposed to contain
_automatically_ extracted autoloads.

What is the right thing to do?

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-10 23:45             ` Luc Teirlinck
@ 2005-08-11  1:12               ` Luc Teirlinck
  2005-08-11  1:36                 ` Luc Teirlinck
  2005-08-11  3:01                 ` Luc Teirlinck
  0 siblings, 2 replies; 72+ messages in thread
From: Luc Teirlinck @ 2005-08-11  1:12 UTC (permalink / raw)
  Cc: larsh, lekktu, rms, emacs-devel

I figured out from the archives that the solution is to copy a good
loaddefs over it.  I will do that, after checking that my version of
loaddefs is not corrupted with local stuff.

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-11  1:12               ` Luc Teirlinck
@ 2005-08-11  1:36                 ` Luc Teirlinck
  2005-08-11  3:01                 ` Luc Teirlinck
  1 sibling, 0 replies; 72+ messages in thread
From: Luc Teirlinck @ 2005-08-11  1:36 UTC (permalink / raw)
  Cc: larsh, lekktu, rms

>From my previous message:

   I figured out from the archives that the solution is to copy a good
   loaddefs over it.

I meant: copy a good copy of loaddefs.el over ldefs-boot.el.

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-11  1:12               ` Luc Teirlinck
  2005-08-11  1:36                 ` Luc Teirlinck
@ 2005-08-11  3:01                 ` Luc Teirlinck
  2005-08-11  6:12                   ` Lars Hansen
  1 sibling, 1 reply; 72+ messages in thread
From: Luc Teirlinck @ 2005-08-11  3:01 UTC (permalink / raw)
  Cc: larsh, lekktu, rms

>From my previous message:

   I meant: copy a good copy of loaddefs.el over ldefs-boot.el.

I have done that and checked that bootstrapping now works OK.

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-11  3:01                 ` Luc Teirlinck
@ 2005-08-11  6:12                   ` Lars Hansen
  0 siblings, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2005-08-11  6:12 UTC (permalink / raw)
  Cc: lekktu, rms, emacs-devel

Luc Teirlinck wrote:
> I have done that and checked that bootstrapping now works OK.
Thanks

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-08-10 11:24           ` Juanma Barranquero
@ 2006-02-09 16:30             ` Juanma Barranquero
  2006-02-09 20:00               ` Lars Hansen
  2006-02-09 21:11               ` Lars Hansen
  0 siblings, 2 replies; 72+ messages in thread
From: Juanma Barranquero @ 2006-02-09 16:30 UTC (permalink / raw)
  Cc: emacs-devel

About seven months ago, I said:

> You got my vote. I've been testing it and everything seems
> to work, even the corner cases of `highlight-changes-mode'.

Now, either I was mistaken then or something's changed in between,
because h-c-m and desktop.el *do* have a problem.

With a simple .emacs.el like this:

;--------- .emacs.el -----------
(setq desktop-save t)
(desktop-save-mode 1)
(setq highlight-changes-global-initial-state 'passive)
(global-highlight-changes 'passive)
;-------------------------------

The steps to reproduce the problem:

 - Start Emacs.
  - Load a file (for example, .emacs.el). => It is in "-Chg" mode,
i.e., passive.
 - Exit Emacs.
  - Start Emacs. => .emacs.el is loaded, in "+Chg" mode (active)
  - M-x hilight-changes-mode RET => .emacs.el is in "-Chg" mode.
 - Exit Emacs.
  - Start Emacs. => .emacs.el is loaded, in "-Chg" mode (finally).

--
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-02-09 16:30             ` Juanma Barranquero
@ 2006-02-09 20:00               ` Lars Hansen
  2006-02-09 21:11               ` Lars Hansen
  1 sibling, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2006-02-09 20:00 UTC (permalink / raw)
  Cc: emacs-devel

I can reproduce the problem, I will try to debug it.

>With a simple .emacs.el like this:
>
>;--------- .emacs.el -----------
>(setq desktop-save t)
>(desktop-save-mode 1)
>(setq highlight-changes-global-initial-state 'passive)
>(global-highlight-changes 'passive)
>;-------------------------------
>
>The steps to reproduce the problem:
>
> - Start Emacs.
>  - Load a file (for example, .emacs.el). => It is in "-Chg" mode,
>i.e., passive.
> - Exit Emacs.
>  - Start Emacs. => .emacs.el is loaded, in "+Chg" mode (active)
>  - M-x hilight-changes-mode RET => .emacs.el is in "-Chg" mode.
> - Exit Emacs.
>  - Start Emacs. => .emacs.el is loaded, in "-Chg" mode (finally).
>
>--
>                    /L/e/k/t/u
>  
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-02-09 16:30             ` Juanma Barranquero
  2006-02-09 20:00               ` Lars Hansen
@ 2006-02-09 21:11               ` Lars Hansen
  2006-02-09 23:46                 ` Juanma Barranquero
  1 sibling, 1 reply; 72+ messages in thread
From: Lars Hansen @ 2006-02-09 21:11 UTC (permalink / raw)
  Cc: emacs-devel


>About seven months ago, I said:
>
>  
>
>>You got my vote. I've been testing it and everything seems
>>to work, even the corner cases of `highlight-changes-mode'.
>>    
>>
>
>Now, either I was mistaken then or something's changed in between,
>because h-c-m and desktop.el *do* have a problem.
>
>With a simple .emacs.el like this:
>
>;--------- .emacs.el -----------
>(setq desktop-save t)
>(desktop-save-mode 1)
>(setq highlight-changes-global-initial-state 'passive)
>(global-highlight-changes 'passive)
>;-------------------------------
>
>The steps to reproduce the problem:
>
> - Start Emacs.
>  - Load a file (for example, .emacs.el). => It is in "-Chg" mode,
>i.e., passive.
> - Exit Emacs.
>  - Start Emacs. => .emacs.el is loaded, in "+Chg" mode (active)
>  - M-x hilight-changes-mode RET => .emacs.el is in "-Chg" mode.
> - Exit Emacs.
>  - Start Emacs. => .emacs.el is loaded, in "-Chg" mode (finally).
>
>--
>                    /L/e/k/t/u
>  
>
I believe the problem should be fixed by now.

Here is the explanation: highlight-changes-mode must be added to
desktop-locals-to-save in order to be saved in the desktop file. To do
this I originally placed

   (add-to-list 'desktop-locals-to-save 'highlight-changes-mode)

inside the function highlight-changes-mode. Therefore things worked when
this function was called, but not when global-highlight-changes was
called. Now I have moved the line out of highlight-changes-mode and
placed it at top level so it is executed at load.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-02-09 21:11               ` Lars Hansen
@ 2006-02-09 23:46                 ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2006-02-09 23:46 UTC (permalink / raw)
  Cc: emacs-devel

On 2/9/06, Lars Hansen <larsh@soem.dk> wrote:

> I believe the problem should be fixed by now.

Yeah, seems to be working now. Thanks.

--
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2005-07-27 14:28         ` Juanma Barranquero
                             ` (2 preceding siblings ...)
  2005-07-28  4:24           ` Masatake YAMATO
@ 2006-04-27 23:05           ` Stuart D. Herring
  2006-04-28 14:56             ` Juanma Barranquero
  2006-04-28 15:44             ` Richard Stallman
  3 siblings, 2 replies; 72+ messages in thread
From: Stuart D. Herring @ 2006-04-27 23:05 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2219 bytes --]

Way back in July 2005, this was part of a discussion about improving
desktop.el:

> Not-totally-unrelated: running two or more Emacs instances that use
> the same desktop file is a classical race condition; the last one to
> exit overwrites the desktop file (quite funny when the desktop was
> very elaborate and the last instance to exit uses almost no buffers).
>
> It'd be very useful to try to detect it and at least stop the second
> instance from loading and using the desktop file if it's already in
> use. There's no way to do that from Emacs, is there?

Richard later suggested using the file-locking primitives along with file
timestamps to implement this.  Here's a stab at implementing the collision
detection, but without file locking because I wasn't sure how to mix that
with `load' competently.  (I suspect this matters little since Emacs
sessions are quite unlikely to be actually _accessing_ the desktop file at
the same time.)

Two things are done: first, a desktop file is modified when it is read
(without incident) to include a "in use" tag; further Emacses will
complain about this if they see it, and will leave the desktop file
unloaded unless the user accepts the collision risk.

Second, when a desktop file is read or written, its modification time
(which is typically "now", since with this patch even loading the file
modifies it) is remembered; if it's different when the desktop is to be
saved, appropriate queries are posed.  (In particular, if no desktop file
is loaded, perhaps because the user decided not to re-load a file, any
attempt to save the new desktop over an existing desktop file will be
complained about.)

I'm certainly not proposing this for installation right now; it needs lots
more testing than I've given it (possibly by people who actually use
desktop), and my papers-issues aren't yet resolved.  But I encourage
people (in particular Juanma, who raised the issue) to try it and let me
know if it's any good; if the testing and the papers go okay, it'll just
need a ChangeLog entry to be good.

Enjoy,
Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

[-- Attachment #2: desktop-conflict.patch --]
[-- Type: application/octet-stream, Size: 14483 bytes --]

Index: desktop.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/desktop.el,v
retrieving revision 1.99
diff -c -r1.99 desktop.el
*** desktop.el	10 Feb 2006 11:05:30 -0000	1.99
--- desktop.el	27 Apr 2006 23:00:03 -0000
***************
*** 475,480 ****
--- 475,484 ----
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
  
+ (defun desktop-full-file-name (&optional dirname)
+   "Return the full name of the current desktop file."
+   (expand-file-name desktop-base-file-name (or dirname desktop-dirname)))
+ 
  (defconst desktop-header
  ";; --------------------------------------------------------------------------
  ;; Desktop File for Emacs
***************
*** 484,489 ****
--- 488,503 ----
  (defvar desktop-delay-hook nil
    "Hooks run after all buffers are loaded; intended for internal use.")
  
+ (defvar desktop-file-modtime nil
+   "When the desktop file was last modified to the knowledge of this Emacs.
+ Used to detect desktop file conflicts.")
+ 
+ (defun desktop-conflict-text ()
+   "Return a string for inclusion in the desktop file to detect conflicts.
+ The string contains a comment for humans and a `setq' for Emacs."
+   (format "\n;; This desktop file was in use as of %s\n(setq desktop-owner %s)\n"
+ 	  (format-time-string "%x %X %Z") (emacs-pid)))
+ 
  ;; ----------------------------------------------------------------------------
  (defun desktop-truncate (list n)
    "Truncate LIST to at most N elements destructively."
***************
*** 531,537 ****
    (when
      (and
        desktop-save-mode
!       (let ((exists (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname))))
          (or
            (eq desktop-save t)
            (and exists (memq desktop-save '(ask-if-new if-exists)))
--- 545,551 ----
    (when
      (and
        desktop-save-mode
!       (let ((exists (file-exists-p (desktop-full-file-name))))
          (or
            (eq desktop-save t)
            (and exists (memq desktop-save '(ask-if-new if-exists)))
***************
*** 547,553 ****
              (call-interactively
                (lambda (dir) (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
!       (desktop-save desktop-dirname)
        (file-error
          (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
            (signal (car err) (cdr err)))))))
--- 561,567 ----
              (call-interactively
                (lambda (dir) (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
!       (desktop-save desktop-dirname t)
        (file-error
          (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
            (signal (car err) (cdr err)))))))
***************
*** 715,730 ****
      (t (expand-file-name filename))))
  
  ;; ----------------------------------------------------------------------------
! (defun desktop-save (dirname)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
    (run-hooks 'desktop-save-hook)
!   (setq dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((filename (expand-file-name desktop-base-file-name dirname))
!           (info
              (mapcar
                #'(lambda (b)
                    (set-buffer b)
--- 729,744 ----
      (t (expand-file-name filename))))
  
  ;; ----------------------------------------------------------------------------
! (defun desktop-save (dirname &optional release)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
+ Optional parameter RELEASE says whether we're done with this desktop.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
    (run-hooks 'desktop-save-hook)
!   (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((info
              (mapcar
                #'(lambda (b)
                    (set-buffer b)
***************
*** 765,808 ****
                (buffer-list)))
            (eager desktop-restore-eager)
            (buf (get-buffer-create "*desktop*")))
!       (set-buffer buf)
!       (erase-buffer)
! 
!       (insert
!         ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
!         desktop-header
!         ";; Created " (current-time-string) "\n"
!         ";; Desktop file format version " desktop-file-version "\n"
!         ";; Emacs version " emacs-version "\n\n"
!         ";; Global section:\n")
!       (mapc (function desktop-outvar) desktop-globals-to-save)
!       (if (memq 'kill-ring desktop-globals-to-save)
!         (insert
!           "(setq kill-ring-yank-pointer (nthcdr "
!           (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
!           " kill-ring))\n"))
! 
!       (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
!       (mapc #'(lambda (l)
!                 (when (apply 'desktop-save-buffer-p l)
!                   (insert "("
!                           (if (or (not (integerp eager))
!                                   (unless (zerop eager)
!                                     (setq eager (1- eager))
!                                     t))
!                               "desktop-create-buffer"
!                             "desktop-append-buffer-args")
!                           " "
!                           desktop-file-version)
!                   (mapc #'(lambda (e)
!                             (insert "\n  " (desktop-value-to-string e)))
!                         l)
!                   (insert ")\n\n")))
!             info)
!       (setq default-directory dirname)
!       (let ((coding-system-for-write 'emacs-mule))
!         (write-region (point-min) (point-max) filename nil 'nomessage))))
!   (setq desktop-dirname dirname))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-remove ()
--- 779,836 ----
                (buffer-list)))
            (eager desktop-restore-eager)
            (buf (get-buffer-create "*desktop*")))
!       (let ((new-modtime (nth 5 (file-attributes (desktop-full-file-name)))))
! 	(when 
! 	    (or (not new-modtime)	; nothing to overwrite
! 		(equal desktop-file-modtime new-modtime)
! 		(yes-or-no-p (if desktop-file-modtime
! 				 (if (> (float-time new-modtime) (float-time desktop-file-modtime))
! 				     "Desktop file is more recent than the one loaded.  Save anyway? "
! 				   "Desktop file isn't the one loaded.  Overwrite it? ")
! 			       "Current desktop was not loaded from a file.  Overwrite this desktop file? "))
! 		(unless release (error "Desktop file conflict")))
! 
! 	  (set-buffer buf)
! 	  (erase-buffer)
! 
! 	  (insert
! 	   ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
! 	   desktop-header
! 	   ";; Created " (current-time-string) "\n"
! 	   ";; Desktop file format version " desktop-file-version "\n"
! 	   ";; Emacs version " emacs-version "\n"
! 	   (if release "" (desktop-conflict-text))
! 	   "\n;; Global section:\n")
! 	  (mapc (function desktop-outvar) desktop-globals-to-save)
! 	  (if (memq 'kill-ring desktop-globals-to-save)
! 	      (insert
! 	       "(setq kill-ring-yank-pointer (nthcdr "
! 	       (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
! 	       " kill-ring))\n"))
! 
! 	  (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
! 	  (mapc #'(lambda (l)
! 		    (when (apply 'desktop-save-buffer-p l)
! 		      (insert "("
! 			      (if (or (not (integerp eager))
! 				      (unless (zerop eager)
! 					(setq eager (1- eager))
! 					t))
! 				  "desktop-create-buffer"
! 				"desktop-append-buffer-args")
! 			      " "
! 			      desktop-file-version)
! 		      (mapc #'(lambda (e)
! 				(insert "\n  " (desktop-value-to-string e)))
! 			    l)
! 		      (insert ")\n\n")))
! 		info)
! 
! 	  (setq default-directory dirname)
! 	  (let ((coding-system-for-write 'emacs-mule))
! 	    (write-region (point-min) (point-max) (desktop-full-file-name) nil 'nomessage))
! 	  ;; We remember when it was modified (which is presumably just now).
! 	  (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name)))))))))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-remove ()
***************
*** 810,816 ****
  This function also sets `desktop-dirname' to nil."
    (interactive)
    (when desktop-dirname
!     (let ((filename (expand-file-name desktop-base-file-name desktop-dirname)))
        (setq desktop-dirname nil)
        (when (file-exists-p filename)
          (delete-file filename)))))
--- 838,844 ----
  This function also sets `desktop-dirname' to nil."
    (interactive)
    (when desktop-dirname
!     (let ((filename (desktop-full-file-name)))
        (setq desktop-dirname nil)
        (when (file-exists-p filename)
          (delete-file filename)))))
***************
*** 833,884 ****
    (interactive)
    (unless noninteractive
      (setq desktop-dirname
!       (file-name-as-directory
!         (expand-file-name
!           (or
!             ;; If DIRNAME is specified, use it.
!             (and (< 0 (length dirname)) dirname)
!             ;; Otherwise search desktop file in desktop-path.
!             (let ((dirs desktop-path))
!               (while
!                 (and
!                   dirs
!                   (not
!                     (file-exists-p (expand-file-name desktop-base-file-name (car dirs)))))
!                 (setq dirs (cdr dirs)))
!               (and dirs (car dirs)))
!             ;; If not found and `desktop-path' is non-nil, use its first element.
!             (and desktop-path (car desktop-path))
!             ;; Default: Home directory.
!             "~"))))
!     (if (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname))
!       ;; Desktop file found, process it.
!       (let ((desktop-first-buffer nil)
!             (desktop-buffer-ok-count 0)
!             (desktop-buffer-fail-count 0))
!         (setq desktop-lazy-timer nil)
!         ;; Evaluate desktop buffer.
!         (load (expand-file-name desktop-base-file-name desktop-dirname) t t t)
!         ;; `desktop-create-buffer' puts buffers at end of the buffer list.
!         ;; We want buffers existing prior to evaluating the desktop (and not reused)
!         ;; to be placed at the end of the buffer list, so we move them here.
!         (mapc 'bury-buffer
!               (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
!         (switch-to-buffer (car (buffer-list)))
!         (run-hooks 'desktop-delay-hook)
!         (setq desktop-delay-hook nil)
!         (run-hooks 'desktop-after-read-hook)
!         (message "Desktop: %d buffer%s restored%s%s."
!                  desktop-buffer-ok-count
!                  (if (= 1 desktop-buffer-ok-count) "" "s")
!                  (if (< 0 desktop-buffer-fail-count)
!                      (format ", %d failed to restore" desktop-buffer-fail-count)
!                    "")
!                  (if desktop-buffer-args-list
!                      (format ", %d to restore lazily"
!                              (length desktop-buffer-args-list))
!                    ""))
!         t)
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))
--- 861,930 ----
    (interactive)
    (unless noninteractive
      (setq desktop-dirname
! 	  (file-name-as-directory
! 	   (expand-file-name
! 	    (or
! 	     ;; If DIRNAME is specified, use it.
! 	     (and (< 0 (length dirname)) dirname)
! 	     ;; Otherwise search desktop file in desktop-path.
! 	     (let ((dirs desktop-path))
! 	       (while
! 		   (and
! 		    dirs
! 		    (not
! 		     (file-exists-p (desktop-full-file-name (car dirs)))))
! 		 (setq dirs (cdr dirs)))
! 	       (and dirs (car dirs)))
! 	     ;; If not found and `desktop-path' is non-nil, use its first element.
! 	     (and desktop-path (car desktop-path))
! 	     ;; Default: Home directory.
! 	     "~"))))
!     (if (file-exists-p (desktop-full-file-name))
! 	;; Desktop file found, process it.
! 	(let ((desktop-first-buffer nil)
! 	      (desktop-buffer-ok-count 0)
! 	      (desktop-buffer-fail-count 0)
! 	      desktop-owner)
! 	  (setq desktop-lazy-timer nil)
! 	  ;; Evaluate desktop buffer.
! 	  (load (desktop-full-file-name) t t t)
! 	  (if (and desktop-owner
! 		   (not (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\nUsing it may cause conflicts.  Use it anyway? " desktop-owner))))
! 	      (progn (desktop-clear)
! 		     (setq desktop-dirname nil)
! 		     (message "Desktop file in use; not loaded.")
! 		     nil)
! 	    ;; If it wasn't already, mark it as in-use, to bother other
! 	    ;; desktop instances.
! 	    (unless desktop-owner
! 	      (condition-case nil
! 		  (write-region (desktop-conflict-text) nil
! 				(desktop-full-file-name) t 'nomessage)
! 		(file-error (message "Couldn't mark desktop file as active")
! 			    (sit-for 1))))
! 	    ;; We remember when it was modified (which is presumably just now).
! 	    (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name))))
! 	    ;; `desktop-create-buffer' puts buffers at end of the buffer list.
! 	    ;; We want buffers existing prior to evaluating the desktop (and
! 	    ;; not reused) to be placed at the end of the buffer list, so we
! 	    ;; move them here.
! 	    (mapc 'bury-buffer
! 		  (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
! 	    (switch-to-buffer (car (buffer-list)))
! 	    (run-hooks 'desktop-delay-hook)
! 	    (setq desktop-delay-hook nil)
! 	    (run-hooks 'desktop-after-read-hook)
! 	    (message "Desktop: %d buffer%s restored%s%s."
! 		     desktop-buffer-ok-count
! 		     (if (= 1 desktop-buffer-ok-count) "" "s")
! 		     (if (< 0 desktop-buffer-fail-count)
! 			 (format ", %d failed to restore" desktop-buffer-fail-count)
! 		       "")
! 		     (if desktop-buffer-args-list
! 			 (format ", %d to restore lazily"
! 				 (length desktop-buffer-args-list))
! 		       ""))
! 	    t))
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-27 23:05           ` Stuart D. Herring
@ 2006-04-28 14:56             ` Juanma Barranquero
  2006-04-29  4:57               ` Stuart D. Herring
  2006-04-28 15:44             ` Richard Stallman
  1 sibling, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2006-04-28 14:56 UTC (permalink / raw)
  Cc: emacs-devel

On 4/28/06, Stuart D. Herring <herring@lanl.gov> wrote:


> without file locking because I wasn't sure how to mix that
> with `load' competently.  (I suspect this matters little since Emacs
> sessions are quite unlikely to be actually _accessing_ the desktop file at
> the same time.)

I agree. The probability of two or more Emacs sessions starting or
non-catastrophically ending at the very same moment seems remote.

> But I encourage
> people (in particular Juanma, who raised the issue) to try it and let me
> know if it's any good; if the testing and the papers go okay, it'll just
> need a ChangeLog entry to be good.

Thanks a lot. I like the functionality, but it still has some rough
spots, at least for daily use.

 - Emacs process the desktop file, loading buffers and all, and only
then asks about it being in use. Can this be changed so the question
is asked at the beginning? (I imagine this could be difficult because
of the way the desktop file is loaded.)

  - If you decide *not* to load the desktop file in use, on exit
you're still asked about saving a new desktop file; at least, for
certain values of `desktop-save'. My main use case is that I'm
starting a fresh Emacs by accident (I have Emacs on another virtual
desktop, or just too many open apps), and I'm going to do C-x C-c
immediately, so it's a bit cumbersome to "M-x set-variable
desktop-save nil RET". Perhaps a  desktop-not-loaded-hook could be
useful there.

  - Not a problem with your implementation, but on Windows, using
gnuserv/gnuclient, the second Emacs instance shows a message "Server
subprocess exited" (because it wasn't able to run gnuserv a second
time) which hides the desktop question...

--
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-27 23:05           ` Stuart D. Herring
  2006-04-28 14:56             ` Juanma Barranquero
@ 2006-04-28 15:44             ` Richard Stallman
  2006-04-29  5:02               ` Stuart D. Herring
  2006-05-03 12:48               ` Juri Linkov
  1 sibling, 2 replies; 72+ messages in thread
From: Richard Stallman @ 2006-04-28 15:44 UTC (permalink / raw)
  Cc: lekktu, emacs-devel

    Two things are done: first, a desktop file is modified when it is read
    (without incident) to include a "in use" tag; further Emacses will
    complain about this if they see it, and will leave the desktop file
    unloaded unless the user accepts the collision risk.

I think it is somewhat dangerous to modify the file when reading it.
My experience tells me that that can lead to various problems in weird
cases, and it is much better if operations that only look at data
are written so that they do not change anything.

Can you use a different file name for the "in use" marker?

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-28 14:56             ` Juanma Barranquero
@ 2006-04-29  4:57               ` Stuart D. Herring
  2006-04-30  1:16                 ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Stuart D. Herring @ 2006-04-29  4:57 UTC (permalink / raw)
  Cc: emacs-devel

>  - Emacs process the desktop file, loading buffers and all, and only
> then asks about it being in use. Can this be changed so the question
> is asked at the beginning? (I imagine this could be difficult because
> of the way the desktop file is loaded.)

Well, the reason for it is really quite simple in my implementation -- the
use tag is added at the end of the file!  The other code has already run. 
Doing it this way let me do the file update with a single `write-region'
append call.  But (see other email) Richard wants that done in a separate
file, and I don't blame him.  So I'll move the check before the desktop
file is ever opened when I do that (Monday or so).

>   - If you decide *not* to load the desktop file in use, on exit
> you're still asked about saving a new desktop file; at least, for
> certain values of `desktop-save'. My main use case is that I'm
> starting a fresh Emacs by accident (I have Emacs on another virtual
> desktop, or just too many open apps), and I'm going to do C-x C-c
> immediately, so it's a bit cumbersome to "M-x set-variable
> desktop-save nil RET". Perhaps a  desktop-not-loaded-hook could be
> useful there.

I thought this was buggy when I first saw it too.  But I realized that
there's no assumption made by desktop.el that you have only one file; just
because this Emacs session isn't associated with the desktop file you
originally tried to load doesn't mean it shouldn't be associated with
another.  But since it doesn't know which other one, it asks!  It's really
a feature... sorta.  I realize that for the common "oh wait, already have
Emacs" case, it's annoying; there could be a customization option to
disable Desktop if you refuse to re-load the file.

I might point out, though, that I've carefully written it so that if you
attempt to overwrite the file that you chose not to load (typically just
pressing Enter when it offers "~/" as the save location) it'll note that
you're overwriting a file that you didn't load, and if you decline to
overwrite it, Emacs will still exit.  Admittedly, this is still annoying,
but pressing C-x C-c RET n o RET is a lot faster than doing
`set-variable'.

>   - Not a problem with your implementation, but on Windows, using
> gnuserv/gnuclient, the second Emacs instance shows a message "Server
> subprocess exited" (because it wasn't able to run gnuserv a second
> time) which hides the desktop question...

Pressing C-l will clear this up, so long as you realize that you're in the
minibuffer and need it redrawn.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-28 15:44             ` Richard Stallman
@ 2006-04-29  5:02               ` Stuart D. Herring
  2006-04-30  3:03                 ` Richard Stallman
  2006-05-03 12:48               ` Juri Linkov
  1 sibling, 1 reply; 72+ messages in thread
From: Stuart D. Herring @ 2006-04-29  5:02 UTC (permalink / raw)
  Cc: emacs-devel

> I think it is somewhat dangerous to modify the file when reading it.
> My experience tells me that that can lead to various problems in weird
> cases, and it is much better if operations that only look at data
> are written so that they do not change anything.
>
> Can you use a different file name for the "in use" marker?

I'm curious about your experience/worries -- the file is opened twice, so
there's no seek issues, and the write is just an append.  There's obvious
race conditions, but I don't think they're important (as I said
previously).  And I was trying to avoid introducing another file for which
one would have to check for conflicts and such.  But I suppose there's no
harm in having `desktop-lock-file-name', customizable but defaulted to
".emacs.desktop.lock" or so.  It can hold the PID of the owner Emacs
process.  Speaking of which, is there a way to see from Lisp if an
unrelated PID is running?

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-29  4:57               ` Stuart D. Herring
@ 2006-04-30  1:16                 ` Juanma Barranquero
  2006-05-02 15:06                   ` Stuart D. Herring
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2006-04-30  1:16 UTC (permalink / raw)
  Cc: emacs-devel

On 4/29/06, Stuart D. Herring <herring@lanl.gov> wrote:
> So I'll move the check before the desktop
> file is ever opened when I do that (Monday or so).

Cool.

> But I realized that
> there's no assumption made by desktop.el that you have only one file; just
> because this Emacs session isn't associated with the desktop file you
> originally tried to load doesn't mean it shouldn't be associated with
> another.  But since it doesn't know which other one, it asks!  It's really
> a feature... sorta.

Yes, I undestand that. That's why I said "for certain values of
desktop-save". I should've added "and for certain uses of desktop".
For example, when you're mainly using a single desktop file in your
$HOME (as I do) instead of per-directory desktop files (which are
*very* rare in my setup). In that case, if-exists or ask-if-exists are
two useful desktop-save values, and being asked about saving a new one
is inconvenient.

> there could be a customization option to
> disable Desktop if you refuse to re-load the file.

A not-loaded hook, as I proposed, would serve the same function and be
a bit more general, I think.

> Pressing C-l will clear this up, so long as you realize that you're in the
> minibuffer and need it redrawn.

Yes, realizing that is the problem. But, as I said, is not a problem
with your implementation.

--
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-29  5:02               ` Stuart D. Herring
@ 2006-04-30  3:03                 ` Richard Stallman
  0 siblings, 0 replies; 72+ messages in thread
From: Richard Stallman @ 2006-04-30  3:03 UTC (permalink / raw)
  Cc: emacs-devel

I don't remember any details--I have just seen enough problems,
over the years, with corrupted files that I have reached the conclusion
that it is much better not to alter a file when there is no logical
reason it should be changed.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-30  1:16                 ` Juanma Barranquero
@ 2006-05-02 15:06                   ` Stuart D. Herring
  2006-05-02 15:14                     ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Stuart D. Herring @ 2006-05-02 15:06 UTC (permalink / raw)
  Cc: emacs-devel

>> there could be a customization option to
>> disable Desktop if you refuse to re-load the file.
>
> A not-loaded hook, as I proposed, would serve the same function and be
> a bit more general, I think.

It seems to me that
(add-hook 'desktop-not-loaded-hook (lambda () (setq desktop-save nil)))
...would be cumbersome (especially for non-Lispy users).  Is there any
other use for such a hook (maybe `kill-emacs'? ;), or would it be just as
good to have the customization option I suggested?  Or instead to ask,
when the user chooses to honor a lock, whether to then disable Desktop?

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-02 15:06                   ` Stuart D. Herring
@ 2006-05-02 15:14                     ` Juanma Barranquero
  2006-05-02 15:42                       ` Stuart D. Herring
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2006-05-02 15:14 UTC (permalink / raw)
  Cc: emacs-devel

On 5/2/06, Stuart D. Herring <herring@lanl.gov> wrote:

> It seems to me that
> (add-hook 'desktop-not-loaded-hook (lambda () (setq desktop-save nil)))
> ...would be cumbersome (especially for non-Lispy users).

You could always do M-x customize-variable desktop-not-loaded-hook,
couldn't you?

> Is there any
> other use for such a hook (maybe `kill-emacs'? ;)

Certainly, running an external app (likely gnuclient) to bring the
other Emacs instance to focus and then killing the current one would
be my first use, yes.

> Or instead to ask,
> when the user chooses to honor a lock, whether to then disable Desktop?

I hate being asked (by a program :-) about things that could be automated.

--
                    /L/e/k/t/u

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-02 15:14                     ` Juanma Barranquero
@ 2006-05-02 15:42                       ` Stuart D. Herring
  2006-05-02 17:57                         ` Stuart D. Herring
  0 siblings, 1 reply; 72+ messages in thread
From: Stuart D. Herring @ 2006-05-02 15:42 UTC (permalink / raw)
  Cc: emacs-devel

>> It seems to me that
>> (add-hook 'desktop-not-loaded-hook (lambda () (setq desktop-save nil)))
>> ...would be cumbersome (especially for non-Lispy users).
>
> You could always do M-x customize-variable desktop-not-loaded-hook,
> couldn't you?

Hey, you're right -- the answer is to give (the new, trivial function)
`disable-desktop-save-mode' as an :option in the defcustom for
`desktop-not-loaded-hook'.

>> Is there any
>> other use for such a hook (maybe `kill-emacs'? ;)
>
> Certainly, running an external app (likely gnuclient) to bring the
> other Emacs instance to focus and then killing the current one would
> be my first use, yes.

I'll also put `save-buffers-kill-emacs' in the :options.

>> Or instead to ask,
>> when the user chooses to honor a lock, whether to then disable Desktop?
>
> I hate being asked (by a program :-) about things that could be automated.

The only problem I see is how to inform the user (aside from etc/NEWS)
that the hook exists, since the behavior with it uncustomized can be
annoying but it's not an obvious customization locus.  Certainly it could
be given an obnoxious default value like
'(announce-the-presence-of-this-hook), but that's silly.  Any ideas?

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-02 15:42                       ` Stuart D. Herring
@ 2006-05-02 17:57                         ` Stuart D. Herring
  0 siblings, 0 replies; 72+ messages in thread
From: Stuart D. Herring @ 2006-05-02 17:57 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1103 bytes --]

>From my previous message:

> The only problem I see is how to inform the user (aside from etc/NEWS)
> that the hook exists, since the behavior with it uncustomized can be
> annoying but it's not an obvious customization locus.  Certainly it could
> be given an obnoxious default value like
> '(announce-the-presence-of-this-hook), but that's silly.  Any ideas?

I haven't addressed this bit, but the attached patch (superceding the
previous one, not combined with it) redoes the locking with a separate
file and adds hook support for the not-loaded case, with useful options
provided via customize.

It also properly disposes of the temporary *desktop* buffer and, as a new
feature, runs the desktop-save-hooks with the *desktop* buffer current
(but still before any inspection of Emacs state is done) so they can be
used to add custom Lisp to the file as well as adjust Emacs state for the
write.

Let me know if it's less rough-cut now.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

[-- Attachment #2: desktop-conflict-2.patch --]
[-- Type: application/octet-stream, Size: 24213 bytes --]

Index: desktop.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/desktop.el,v
retrieving revision 1.99
diff -c -r1.99 desktop.el
*** desktop.el	10 Feb 2006 11:05:30 -0000	1.99
--- desktop.el	2 May 2006 17:56:29 -0000
***************
*** 162,167 ****
--- 162,171 ----
  (define-obsolete-variable-alias 'desktop-enable
                                  'desktop-save-mode "22.1")
  
+ (defun desktop-save-mode-off ()
+   "Disable `desktop-save-mode'.  Provided for use in hooks."
+   (desktop-save-mode 0))
+ 
  (defcustom desktop-save 'ask-if-new
    "*Specifies whether the desktop should be saved when it is killed.
  A desktop is killed when the user changes desktop or quits Emacs.
***************
*** 176,187 ****
  The variables `desktop-dirname' and `desktop-base-file-name'
  determine where the desktop is saved."
    :type '(choice
!     (const :tag "Always save" t)
!     (const :tag "Always ask" ask)
!     (const :tag "Ask if desktop file is new, else do save" ask-if-new)
!     (const :tag "Ask if desktop file exists, else don't save" ask-if-exists)
!     (const :tag "Save if desktop file exists, else don't" if-exists)
!     (const :tag "Never save" nil))
    :group 'desktop
    :version "22.1")
  
--- 180,191 ----
  The variables `desktop-dirname' and `desktop-base-file-name'
  determine where the desktop is saved."
    :type '(choice
! 	  (const :tag "Always save" t)
! 	  (const :tag "Always ask" ask)
! 	  (const :tag "Ask if desktop file is new, else do save" ask-if-new)
! 	  (const :tag "Ask if desktop file exists, else don't save" ask-if-exists)
! 	  (const :tag "Save if desktop file exists, else don't" if-exists)
! 	  (const :tag "Never save" nil))
    :group 'desktop
    :version "22.1")
  
***************
*** 193,198 ****
--- 197,209 ----
  (define-obsolete-variable-alias 'desktop-basefilename
                                  'desktop-base-file-name "22.1")
  
+ (defcustom desktop-base-lock-name
+   (convert-standard-filename ".emacs.desktop.lock")
+   "Name of lock file for Emacs desktop, excluding the directory part."
+   :type 'file
+   :group 'desktop
+   :version "22.1")
+ 
  (defcustom desktop-path '("." "~")
    "List of directories to search for the desktop file.
  The base name of the file is specified in `desktop-base-file-name'."
***************
*** 212,232 ****
  
  (defcustom desktop-no-desktop-file-hook nil
    "Normal hook run when `desktop-read' can't find a desktop file.
  May be used to show a dired buffer."
    :type 'hook
    :group 'desktop
    :version "22.1")
  
  (defcustom desktop-after-read-hook nil
    "Normal hook run after a successful `desktop-read'.
  May be used to show a buffer list."
    :type 'hook
    :group 'desktop
    :version "22.1")
  
  (defcustom desktop-save-hook nil
    "Normal hook run before the desktop is saved in a desktop file.
! This is useful for truncating history lists, for example."
    :type 'hook
    :group 'desktop)
  
--- 223,256 ----
  
  (defcustom desktop-no-desktop-file-hook nil
    "Normal hook run when `desktop-read' can't find a desktop file.
+ Run in the directory in which the desktop file was sought.
  May be used to show a dired buffer."
    :type 'hook
    :group 'desktop
    :version "22.1")
  
+ (defcustom desktop-not-loaded-hook nil
+   "Normal hook run when the user declines to re-use a desktop file.
+ Run in the directory in which the desktop file was found.
+ May be used to deal with accidental multiple Emacs jobs."
+   :type 'hook
+   :group 'desktop
+   :options '(desktop-save-mode-off save-buffers-kill-emacs)
+   :version "22.1")
+ 
  (defcustom desktop-after-read-hook nil
    "Normal hook run after a successful `desktop-read'.
  May be used to show a buffer list."
    :type 'hook
    :group 'desktop
+   :options '(list-buffers)
    :version "22.1")
  
  (defcustom desktop-save-hook nil
    "Normal hook run before the desktop is saved in a desktop file.
! Run with the desktop buffer current with only the header present.
! May be used to add to the desktop code or to truncate history lists,
! for example."
    :type 'hook
    :group 'desktop)
  
***************
*** 282,287 ****
--- 306,312 ----
      size-indication-mode
      buffer-file-coding-system
      indent-tabs-mode
+     tab-width
      indicate-buffer-boundaries
      indicate-empty-lines
      show-trailing-whitespace)
***************
*** 475,480 ****
--- 500,515 ----
  (defvar desktop-dirname nil
    "The directory in which the desktop file should be saved.")
  
+ (defun desktop-full-file-name (&optional dirname)
+   "Return the full name of the desktop file in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (expand-file-name desktop-base-file-name (or dirname desktop-dirname)))
+ 
+ (defun desktop-full-lock-name (&optional dirname)
+   "Return the full name of the desktop lock file in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (expand-file-name desktop-base-lock-name (or dirname desktop-dirname)))
+ 
  (defconst desktop-header
  ";; --------------------------------------------------------------------------
  ;; Desktop File for Emacs
***************
*** 485,490 ****
--- 520,558 ----
    "Hooks run after all buffers are loaded; intended for internal use.")
  
  ;; ----------------------------------------------------------------------------
+ ;; Desktop file conflict detection
+ (defvar desktop-file-modtime nil
+   "When the desktop file was last modified to the knowledge of this Emacs.
+ Used to detect desktop file conflicts.")
+ 
+ (defun desktop-owner (&optional dirname)
+   "Return the PID of the Emacs process that owns the desktop file in DIRNAME.
+ Return nil if no desktop file found or no Emacs process is using it.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (let (owner)
+     (and (file-exists-p (desktop-full-lock-name dirname))
+ 	 (condition-case nil
+ 	     (with-temp-buffer (insert-file-contents-literally
+ 				(desktop-full-lock-name dirname))
+ 			       (goto-char (point-min))
+ 			       (setq owner (read (current-buffer)))
+ 			       (integerp owner))
+ 	   (error nil))
+ 	 owner)))
+ 
+ (defun desktop-claim-lock (&optional dirname)
+   "Record this Emacs process as the owner of the desktop file in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (write-region (number-to-string (emacs-pid)) nil
+ 		(desktop-full-lock-name dirname)))
+ 
+ (defun desktop-release-lock (&optional dirname)
+   "Remove the lock file for the desktop in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (let ((file (desktop-full-lock-name dirname)))
+     (when (file-exists-p file) (delete-file file))))
+ 
+ ;; ----------------------------------------------------------------------------
  (defun desktop-truncate (list n)
    "Truncate LIST to at most N elements destructively."
    (let ((here (nthcdr (1- n) list)))
***************
*** 529,556 ****
  If the desktop should be saved and `desktop-dirname'
  is nil, ask the user where to save the desktop."
    (when
!     (and
!       desktop-save-mode
!       (let ((exists (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname))))
!         (or
!           (eq desktop-save t)
!           (and exists (memq desktop-save '(ask-if-new if-exists)))
!           (and
!             (or
!               (memq desktop-save '(ask ask-if-new))
!               (and exists (eq desktop-save 'ask-if-exists)))
!             (y-or-n-p "Save desktop? ")))))
      (unless desktop-dirname
        (setq desktop-dirname
!         (file-name-as-directory
!           (expand-file-name
!             (call-interactively
!               (lambda (dir) (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
!       (desktop-save desktop-dirname)
        (file-error
!         (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
!           (signal (car err) (cdr err)))))))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-list* (&rest args)
--- 597,626 ----
  If the desktop should be saved and `desktop-dirname'
  is nil, ask the user where to save the desktop."
    (when
!       (and
!        desktop-save-mode
!        (let ((exists (file-exists-p (desktop-full-file-name))))
! 	 (or
! 	  (eq desktop-save t)
! 	  (and exists (memq desktop-save '(ask-if-new if-exists)))
! 	  (and
! 	   (or
! 	    (memq desktop-save '(ask ask-if-new))
! 	    (and exists (eq desktop-save 'ask-if-exists)))
! 	   (y-or-n-p "Save desktop? ")))))
      (unless desktop-dirname
        (setq desktop-dirname
! 	    (file-name-as-directory
! 	     (expand-file-name
! 	      (call-interactively
! 	       (lambda (dir) (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
! 	(desktop-save desktop-dirname t)
        (file-error
!        (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
! 	 (signal (car err) (cdr err))))))
!   ;; If we own it, we don't anymore.
!   (if (eq (emacs-pid) (desktop-owner)) (desktop-release-lock)))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-list* (&rest args)
***************
*** 565,570 ****
--- 635,676 ----
        value)))
  
  ;; ----------------------------------------------------------------------------
+ (defun desktop-buffer-info (buffer)
+   (set-buffer buffer)
+   (list
+    ;; basic information
+    (desktop-file-name (buffer-file-name) dirname) (buffer-name) major-mode
+    ;; minor modes
+    (let (ret)
+      (mapc
+       #'(lambda (minor-mode)
+ 	  (and
+ 	   (boundp minor-mode)
+ 	   (symbol-value minor-mode)
+ 	   (let* ((special (assq minor-mode desktop-minor-mode-table))
+ 		  (value (cond (special (cadr special))
+ 			       ((functionp minor-mode) minor-mode))))
+ 	     (when value (add-to-list 'ret value)))))
+       (mapcar #'car minor-mode-alist))
+      ret)
+    ;; point and mark, and read-only status
+    (point) (list (mark t) mark-active) buffer-read-only
+    ;; auxiliary information
+    (when (functionp desktop-save-buffer)
+      (funcall desktop-save-buffer dirname))
+    ;; local variables
+    (let ((locals desktop-locals-to-save)
+ 	 (loclist (buffer-local-variables))
+ 	 (ll))
+      (while locals
+        (let ((here (assq (car locals) loclist)))
+ 	 (if here (setq ll (cons here ll))
+ 	   (when (member (car locals) loclist)
+ 	     (setq ll (cons (car locals) ll)))))
+        (setq locals (cdr locals)))
+      ll)))
+ 
+ ;; ----------------------------------------------------------------------------
  (defun desktop-internal-v2s (value)
    "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE.
  TXT is a string that when read and evaluated yields value.
***************
*** 715,808 ****
      (t (expand-file-name filename))))
  
  ;; ----------------------------------------------------------------------------
! (defun desktop-save (dirname)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
!   (run-hooks 'desktop-save-hook)
!   (setq dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((filename (expand-file-name desktop-base-file-name dirname))
!           (info
!             (mapcar
!               #'(lambda (b)
!                   (set-buffer b)
!                   (list
!                     (desktop-file-name (buffer-file-name) dirname)
!                     (buffer-name)
!                     major-mode
!                     ;; minor modes
!                     (let (ret)
!                       (mapc
!                         #'(lambda (minor-mode)
!                           (and
!                             (boundp minor-mode)
!                             (symbol-value minor-mode)
!                             (let* ((special (assq minor-mode desktop-minor-mode-table))
!                                    (value (cond (special (cadr special))
!                                                 ((functionp minor-mode) minor-mode))))
!                               (when value (add-to-list 'ret value)))))
!                         (mapcar #'car minor-mode-alist))
!                       ret)
!                     (point)
!                     (list (mark t) mark-active)
!                     buffer-read-only
!                     ;; Auxiliary information
!                     (when (functionp desktop-save-buffer)
!                       (funcall desktop-save-buffer dirname))
!                     (let ((locals desktop-locals-to-save)
!                           (loclist (buffer-local-variables))
!                           (ll))
!                       (while locals
!                         (let ((here (assq (car locals) loclist)))
!                           (if here
!                             (setq ll (cons here ll))
!                             (when (member (car locals) loclist)
!                               (setq ll (cons (car locals) ll)))))
!                         (setq locals (cdr locals)))
!                       ll)))
!               (buffer-list)))
!           (eager desktop-restore-eager)
!           (buf (get-buffer-create "*desktop*")))
!       (set-buffer buf)
!       (erase-buffer)
! 
!       (insert
!         ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
!         desktop-header
!         ";; Created " (current-time-string) "\n"
!         ";; Desktop file format version " desktop-file-version "\n"
!         ";; Emacs version " emacs-version "\n\n"
!         ";; Global section:\n")
!       (mapc (function desktop-outvar) desktop-globals-to-save)
!       (if (memq 'kill-ring desktop-globals-to-save)
!         (insert
!           "(setq kill-ring-yank-pointer (nthcdr "
!           (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
!           " kill-ring))\n"))
! 
!       (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
!       (mapc #'(lambda (l)
!                 (when (apply 'desktop-save-buffer-p l)
!                   (insert "("
!                           (if (or (not (integerp eager))
!                                   (unless (zerop eager)
!                                     (setq eager (1- eager))
!                                     t))
!                               "desktop-create-buffer"
!                             "desktop-append-buffer-args")
!                           " "
!                           desktop-file-version)
!                   (mapc #'(lambda (e)
!                             (insert "\n  " (desktop-value-to-string e)))
!                         l)
!                   (insert ")\n\n")))
!             info)
!       (setq default-directory dirname)
!       (let ((coding-system-for-write 'emacs-mule))
!         (write-region (point-min) (point-max) filename nil 'nomessage))))
!   (setq desktop-dirname dirname))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-remove ()
--- 821,891 ----
      (t (expand-file-name filename))))
  
  ;; ----------------------------------------------------------------------------
! (defun desktop-save (dirname &optional release)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
+ Optional parameter RELEASE says whether we're done with this desktop.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
!   (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((eager desktop-restore-eager)
! 	  (new-modtime (nth 5 (file-attributes (desktop-full-file-name)))))
!       (when
! 	  (or (not new-modtime)		; nothing to overwrite
! 	      (equal desktop-file-modtime new-modtime)
! 	      (yes-or-no-p (if desktop-file-modtime
! 			       (if (> (float-time new-modtime) (float-time desktop-file-modtime))
! 				   "Desktop file is more recent than the one loaded.  Save anyway? "
! 				 "Desktop file isn't the one loaded.  Overwrite it? ")
! 			     "Current desktop was not loaded from a file.  Overwrite this desktop file? "))
! 	      (unless release (error "Desktop file conflict")))
! 
! 	;; If we're done with it, release the lock.
! 	;; Otherwise, claim it if it's unclaimed or if we created it.
! 	(if release (desktop-release-lock)
! 	  (unless (and new-modtime (desktop-owner)) (desktop-claim-lock)))
! 
! 	(with-temp-buffer
! 	  (insert
! 	   ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
! 	   desktop-header
! 	   ";; Created " (current-time-string) "\n"
! 	   ";; Desktop file format version " desktop-file-version "\n"
! 	   ";; Emacs version " emacs-version "\n\n")
! 	  (save-excursion (run-hooks 'desktop-save-hook))
! 	  (goto-char (point-max))
! 	  (insert ";; Global section:\n")
! 	  (mapc (function desktop-outvar) desktop-globals-to-save)
! 	  (if (memq 'kill-ring desktop-globals-to-save)
! 	      (insert
! 	       "(setq kill-ring-yank-pointer (nthcdr "
! 	       (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
! 	       " kill-ring))\n"))
! 
! 	  (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
! 	  (mapc #'(lambda (l)
! 		    (when (apply 'desktop-save-buffer-p l)
! 		      (insert "("
! 			      (if (or (not (integerp eager))
! 				      (unless (zerop eager)
! 					(setq eager (1- eager))
! 					t))
! 				  "desktop-create-buffer"
! 				"desktop-append-buffer-args")
! 			      " "
! 			      desktop-file-version)
! 		      (mapc #'(lambda (e)
! 				(insert "\n  " (desktop-value-to-string e)))
! 			    l)
! 		      (insert ")\n\n")))
! 		(mapcar 'desktop-buffer-info (buffer-list)))
! 
! 	  (setq default-directory dirname)
! 	  (let ((coding-system-for-write 'emacs-mule))
! 	    (write-region (point-min) (point-max) (desktop-full-file-name) nil 'nomessage))
! 	  ;; We remember when it was modified (which is presumably just now).
! 	  (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name)))))))))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-remove ()
***************
*** 810,816 ****
  This function also sets `desktop-dirname' to nil."
    (interactive)
    (when desktop-dirname
!     (let ((filename (expand-file-name desktop-base-file-name desktop-dirname)))
        (setq desktop-dirname nil)
        (when (file-exists-p filename)
          (delete-file filename)))))
--- 893,899 ----
  This function also sets `desktop-dirname' to nil."
    (interactive)
    (when desktop-dirname
!     (let ((filename (desktop-full-file-name)))
        (setq desktop-dirname nil)
        (when (file-exists-p filename)
          (delete-file filename)))))
***************
*** 833,884 ****
    (interactive)
    (unless noninteractive
      (setq desktop-dirname
!       (file-name-as-directory
!         (expand-file-name
!           (or
!             ;; If DIRNAME is specified, use it.
!             (and (< 0 (length dirname)) dirname)
!             ;; Otherwise search desktop file in desktop-path.
!             (let ((dirs desktop-path))
!               (while
!                 (and
!                   dirs
!                   (not
!                     (file-exists-p (expand-file-name desktop-base-file-name (car dirs)))))
!                 (setq dirs (cdr dirs)))
!               (and dirs (car dirs)))
!             ;; If not found and `desktop-path' is non-nil, use its first element.
!             (and desktop-path (car desktop-path))
!             ;; Default: Home directory.
!             "~"))))
!     (if (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname))
!       ;; Desktop file found, process it.
!       (let ((desktop-first-buffer nil)
!             (desktop-buffer-ok-count 0)
!             (desktop-buffer-fail-count 0))
!         (setq desktop-lazy-timer nil)
!         ;; Evaluate desktop buffer.
!         (load (expand-file-name desktop-base-file-name desktop-dirname) t t t)
!         ;; `desktop-create-buffer' puts buffers at end of the buffer list.
!         ;; We want buffers existing prior to evaluating the desktop (and not reused)
!         ;; to be placed at the end of the buffer list, so we move them here.
!         (mapc 'bury-buffer
!               (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
!         (switch-to-buffer (car (buffer-list)))
!         (run-hooks 'desktop-delay-hook)
!         (setq desktop-delay-hook nil)
!         (run-hooks 'desktop-after-read-hook)
!         (message "Desktop: %d buffer%s restored%s%s."
!                  desktop-buffer-ok-count
!                  (if (= 1 desktop-buffer-ok-count) "" "s")
!                  (if (< 0 desktop-buffer-fail-count)
!                      (format ", %d failed to restore" desktop-buffer-fail-count)
!                    "")
!                  (if desktop-buffer-args-list
!                      (format ", %d to restore lazily"
!                              (length desktop-buffer-args-list))
!                    ""))
!         t)
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))
--- 916,983 ----
    (interactive)
    (unless noninteractive
      (setq desktop-dirname
! 	  (file-name-as-directory
! 	   (expand-file-name
! 	    (or
! 	     ;; If DIRNAME is specified, use it.
! 	     (and (< 0 (length dirname)) dirname)
! 	     ;; Otherwise search desktop file in desktop-path.
! 	     (let ((dirs desktop-path))
! 	       (while
! 		   (and
! 		    dirs
! 		    (not
! 		     (file-exists-p (desktop-full-file-name (car dirs)))))
! 		 (setq dirs (cdr dirs)))
! 	       (and dirs (car dirs)))
! 	     ;; If not found and `desktop-path' is non-nil, use its first element.
! 	     (and desktop-path (car desktop-path))
! 	     ;; Default: Home directory.
! 	     "~"))))
!     (if (file-exists-p (desktop-full-file-name))
! 	;; Desktop file found, but is it already in use?
! 	(let ((desktop-first-buffer nil)
! 	      (desktop-buffer-ok-count 0)
! 	      (desktop-buffer-fail-count 0)
! 	      (owner (desktop-owner)))
! 	  (if (and owner
! 		   (not (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\nUsing it may cause conflicts.  Use it anyway? " owner))))
! 	      (progn (setq desktop-dirname nil)
! 		     (let ((default-directory desktop-dirname))
! 		       (run-hooks 'desktop-not-loaded-hook))
! 		     (message "Desktop file in use; not loaded."))
! 	    (setq desktop-lazy-timer nil)
! 	    ;; Evaluate desktop buffer and remember when it was modified.
! 	    (load (desktop-full-file-name) t t t)
! 	    (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name))))
! 	    ;; If it wasn't already, mark it as in-use, to bother other
! 	    ;; desktop instances.
! 	    (unless owner
! 	      (condition-case nil (desktop-claim-lock)
! 		(file-error (message "Couldn't record use of desktop file")
! 			    (sit-for 1))))
! 
! 	    ;; `desktop-create-buffer' puts buffers at end of the buffer list.
! 	    ;; We want buffers existing prior to evaluating the desktop (and
! 	    ;; not reused) to be placed at the end of the buffer list, so we
! 	    ;; move them here.
! 	    (mapc 'bury-buffer
! 		  (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
! 	    (switch-to-buffer (car (buffer-list)))
! 	    (run-hooks 'desktop-delay-hook)
! 	    (setq desktop-delay-hook nil)
! 	    (run-hooks 'desktop-after-read-hook)
! 	    (message "Desktop: %d buffer%s restored%s%s."
! 		     desktop-buffer-ok-count
! 		     (if (= 1 desktop-buffer-ok-count) "" "s")
! 		     (if (< 0 desktop-buffer-fail-count)
! 			 (format ", %d failed to restore" desktop-buffer-fail-count)
! 		       "")
! 		     (if desktop-buffer-args-list
! 			 (format ", %d to restore lazily"
! 				 (length desktop-buffer-args-list))
! 		       ""))
! 	    t))
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-04-28 15:44             ` Richard Stallman
  2006-04-29  5:02               ` Stuart D. Herring
@ 2006-05-03 12:48               ` Juri Linkov
  2006-05-03 14:37                 ` Lars Hansen
  2006-05-04 16:17                 ` Stuart D. Herring
  1 sibling, 2 replies; 72+ messages in thread
From: Juri Linkov @ 2006-05-03 12:48 UTC (permalink / raw)
  Cc: lekktu, emacs-devel

>     Two things are done: first, a desktop file is modified when it is read
>     (without incident) to include a "in use" tag; further Emacses will
>     complain about this if they see it, and will leave the desktop file
>     unloaded unless the user accepts the collision risk.
>
> I think it is somewhat dangerous to modify the file when reading it.
> My experience tells me that that can lead to various problems in weird
> cases, and it is much better if operations that only look at data
> are written so that they do not change anything.
>
> Can you use a different file name for the "in use" marker?

Wouldn't it be better to use Emacs standard file locking mechanism,
i.e. after reading a desktop file to mark the desktop file's buffer
as modified?  This ensures that trying to save the desktop in another
Emacs session will raise a question about stealing/leaving the lock.

Another simpler solution (without touching the desktop file's buffer) is
to remember the desktop file's timestamp after reading it, and before
saving it compare it with the old timestamp, and ask the question about
whether to override it or not.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-03 12:48               ` Juri Linkov
@ 2006-05-03 14:37                 ` Lars Hansen
  2006-05-03 20:43                   ` Richard Stallman
  2006-05-04 16:27                   ` Stuart D. Herring
  2006-05-04 16:17                 ` Stuart D. Herring
  1 sibling, 2 replies; 72+ messages in thread
From: Lars Hansen @ 2006-05-03 14:37 UTC (permalink / raw)
  Cc: lekktu, rms, emacs-devel

Juri Linkov wrote:

>Wouldn't it be better to use Emacs standard file locking mechanism,
>i.e. after reading a desktop file to mark the desktop file's buffer
>as modified?  This ensures that trying to save the desktop in another
>Emacs session will raise a question about stealing/leaving the lock.
>  
>
I like the idea of using the standard locking mechanism, but I don't
like to mark an unmodified buffer as modified.

I think the desktop file should be locked as soon as we know it is going
to be changed when Emacs exits, i.e. when desktop-save-mode is turned
on. And if desktop-save-mode is turned off, the desktop file should be
unlocked if its buffer is unmodified. So maybe lock-buffer should have
an optional parameter LOCK-UNMODIFIED to make it usable in such cases (I
take it this is an after-the-release discussion.)

I guess the same type of problem exists for .recentf, .emacs-places,
.emacs-history and maybe other files. The problem should be handled in
the same way for all these files.

>Another simpler solution (without touching the desktop file's buffer) is
>to remember the desktop file's timestamp after reading it, and before
>saving it compare it with the old timestamp, and ask the question about
>whether to override it or not.
>  
>
This is pleasingly simple, but then the question would be asked when
Emacs is exited rather than when it is started. IMHO, the question
should be asked as soon as the problem is detected, i.e. when the second
Emacs is started (if desktop-save-mode is turned on).

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-03 14:37                 ` Lars Hansen
@ 2006-05-03 20:43                   ` Richard Stallman
  2006-05-04 16:27                   ` Stuart D. Herring
  1 sibling, 0 replies; 72+ messages in thread
From: Richard Stallman @ 2006-05-03 20:43 UTC (permalink / raw)
  Cc: juri, lekktu, emacs-devel

    I like the idea of using the standard locking mechanism, but I don't
    like to mark an unmodified buffer as modified.

There is nothing inconsistent with that state of affairs.
Type X DEL and you will get an unmodified buffer marked as modified.

If it makes you feel better, you could insert a string in the buffer
and then delete it.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-03 12:48               ` Juri Linkov
  2006-05-03 14:37                 ` Lars Hansen
@ 2006-05-04 16:17                 ` Stuart D. Herring
  1 sibling, 0 replies; 72+ messages in thread
From: Stuart D. Herring @ 2006-05-04 16:17 UTC (permalink / raw)
  Cc: emacs-devel

>> Can you use a different file name for the "in use" marker?
>
> Wouldn't it be better to use Emacs standard file locking mechanism,
> i.e. after reading a desktop file to mark the desktop file's buffer
> as modified?  This ensures that trying to save the desktop in another
> Emacs session will raise a question about stealing/leaving the lock.

The desktop file is never in a buffer in the current scheme.  `load' is
called on the file, and then a new desktop is prepared in a file-less
buffer "*desktop*" which is then `write-region'ed to the desktop file. 
`write-region' supports locking (even for file-less buffers), but `load'
does not.  Obviously one could actually find the desktop file, lock it,
and then `eval-buffer' or so.  I just want it understood that it's not
compatible with the current architecture.

> Another simpler solution (without touching the desktop file's buffer) is
> to remember the desktop file's timestamp after reading it, and before
> saving it compare it with the old timestamp, and ask the question about
> whether to override it or not.

My patch does this, among other things.  The question arises, though, of
what to do when the desktop is being saved to a different file; the
desktop model does not involve "loading" and "saving" a desktop _file_
which is conceptually central and always-current, but rather "storing" and
"reloading" a desktop (session data), using the file only as a persistence
mechanism.

So the statement "your desktop file has been modified since you read it"
is somewhat wrongheaded, since during any Emacs session (or some
subsession using a particular desktop; there is a function
`desktop-change-dir') there is, conceptually, no "desktop file", just the
actual desktop.  My patch attempts to say meaningful things when loading
from an in-use A and saving to a modified B, but the heuristics might be
improvable.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-03 14:37                 ` Lars Hansen
  2006-05-03 20:43                   ` Richard Stallman
@ 2006-05-04 16:27                   ` Stuart D. Herring
  2006-05-05  6:44                     ` Lars Hansen
  2007-06-05  9:24                     ` Juanma Barranquero
  1 sibling, 2 replies; 72+ messages in thread
From: Stuart D. Herring @ 2006-05-04 16:27 UTC (permalink / raw)
  Cc: emacs-devel

> I like the idea of using the standard locking mechanism, but I don't
> like to mark an unmodified buffer as modified.
>
> I think the desktop file should be locked as soon as we know it is going
> to be changed when Emacs exits, i.e. when desktop-save-mode is turned
> on. And if desktop-save-mode is turned off, the desktop file should be
> unlocked if its buffer is unmodified. So maybe lock-buffer should have
> an optional parameter LOCK-UNMODIFIED to make it usable in such cases (I
> take it this is an after-the-release discussion.)

So what happens if you turn desktop-save-mode off, another Emacs loads,
locks, overwrites, and unlocks the file, and then you turn
desktop-save-mode back on?  (The desktop file's buffer (if it is made to
have one) will always be unmodified unless the user explicitly finds it
and changes it; desktop does not use a buffer as some sort of "scratch
pad" whose state of modification would reflect the state of the abstract
desktop.)  Besides, someone could have a "standard desktop" that they load
frequently but save rarely, and so never have desktop-save-mode turned on.
 Then they might occasionally improve on or update the standard, and issue
an explicit (desktop-save) which would take place without the protections
of file locking.

In short, I don't think it's reasonable to "know it is going to be changed
when Emacs exits", because settings can change and it might even get
changed before Emacs exits (due to `desktop-save' or even
`desktop-change-dir').

>> [timestamp check suggestion]
>
> This is pleasingly simple, but then the question would be asked when
> Emacs is exited rather than when it is started. IMHO, the question
> should be asked as soon as the problem is detected, i.e. when the second
> Emacs is started (if desktop-save-mode is turned on).

My patch does this (as I mentioned in my reply to Juri); it also does what
you ask, although without the standard file-lock mechanism.  A separate
lock file is maintained which identifies (by PID) the owner of the desktop
file.  Then the second Emacs will see the file and complain about it
(regardless of the setting of `desktop-save-mode', for the reasons of
no-precognition mentioned above), although the user is allowed the option
of proceeding anyway (at which point it's up to the modification dates to
attempt a peaceful resolution later).

I encourage the testing of my patch to see if its behavior is close enough
to everyone's idea of safe, correct, vigilant, and intuitive.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-04 16:27                   ` Stuart D. Herring
@ 2006-05-05  6:44                     ` Lars Hansen
  2007-06-05  9:24                     ` Juanma Barranquero
  1 sibling, 0 replies; 72+ messages in thread
From: Lars Hansen @ 2006-05-05  6:44 UTC (permalink / raw)
  Cc: emacs-devel

Stuart D. Herring wrote:

>So what happens if you turn desktop-save-mode off, another Emacs loads,
>locks, overwrites, and unlocks the file, and then you turn
>desktop-save-mode back on?  (The desktop file's buffer (if it is made to
>have one) will always be unmodified unless the user explicitly finds it
>and changes it; desktop does not use a buffer as some sort of "scratch
>pad" whose state of modification would reflect the state of the abstract
>desktop.)  Besides, someone could have a "standard desktop" that they load
>frequently but save rarely, and so never have desktop-save-mode turned on.
> Then they might occasionally improve on or update the standard, and issue
>an explicit (desktop-save) which would take place without the protections
>of file locking.
>  
>
I see your point.

>I encourage the testing of my patch to see if its behavior is close enough
>to everyone's idea of safe, correct, vigilant, and intuitive.
>  
>
I will do so. Thanks.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2006-05-04 16:27                   ` Stuart D. Herring
  2006-05-05  6:44                     ` Lars Hansen
@ 2007-06-05  9:24                     ` Juanma Barranquero
  2007-06-08 21:17                       ` Davis Herring
  1 sibling, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2007-06-05  9:24 UTC (permalink / raw)
  To: herring; +Cc: emacs-devel

On 5/4/06, Stuart D. Herring <herring@lanl.gov> wrote:

> My patch does this (as I mentioned in my reply to Juri); it also does what
> you ask, although without the standard file-lock mechanism.  A separate
> lock file is maintained which identifies (by PID) the owner of the desktop
> file.  Then the second Emacs will see the file and complain about it
> (regardless of the setting of `desktop-save-mode', for the reasons of
> no-precognition mentioned above), although the user is allowed the option
> of proceeding anyway (at which point it's up to the modification dates to
> attempt a peaceful resolution later).

What happened to this patch to add sort-of-file-locking to desktop.el?

             Juanma

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-05  9:24                     ` Juanma Barranquero
@ 2007-06-08 21:17                       ` Davis Herring
  2007-06-08 21:29                         ` Juanma Barranquero
  2007-06-08 22:14                         ` Juri Linkov
  0 siblings, 2 replies; 72+ messages in thread
From: Davis Herring @ 2007-06-08 21:17 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1643 bytes --]

> What happened to this patch to add sort-of-file-locking to desktop.el?

As far as I know, nothing has been done with it.  I still have it in my
working copy (of course), and have, prompted by your message, just now
resolved a daunting 57/76-line conflict with the changes between 1.106 and
1.108.  My version has one of the tainted `mapc' calls, if that matters;
given Stefan's trivial (dolist (x l) (f x)) I would surely have supplied
(mapc f l) myself.  (No offense meant to Stefan; that one alone was
trivial.)

Links to the original (er, the second) discussion:
April, largely superceded:
http://lists.gnu.org/archive/html/emacs-devel/2006-04/msg01253.html
May: http://lists.gnu.org/archive/html/emacs-devel/2006-05/msg00084.html

I've attached an updated patch vs. current CVS; in it I have
optimistically tagged my two new defcustoms as new in 22.2.  Here's a stab
at a ChangeLog:

2007-06-08  Davis Herring  <herring@lanl.gov>

	* desktop.el (desktop-save-mode-off): New function.
	(desktop-base-lock-name, desktop-not-loaded-hook): New variables.
	(desktop-full-lock-name, desktop-file-modtime, desktop-owner)
	(desktop-claim-lock, desktop-release-lock): New functions.
	(desktop-kill): Tell `desktop-save' that this is the last save.
	Release the lock afterwards.
	(desktop-buffer-info): New function.
	(desktop-save): Use it.  Run `desktop-save-hook' where the doc
	says to.  Detect conflicts, and manage the lock.
	(desktop-read): Detect conflicts.  Manage the lock.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

[-- Attachment #2: desktop-conflict-4.patch --]
[-- Type: application/octet-stream, Size: 18053 bytes --]

Index: desktop.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/desktop.el,v
retrieving revision 1.108
diff -c -r1.108 desktop.el
*** desktop.el	11 Apr 2007 02:28:26 -0000	1.108
--- desktop.el	8 Jun 2007 20:58:14 -0000
***************
*** 162,167 ****
--- 162,171 ----
  (define-obsolete-variable-alias 'desktop-enable
                                  'desktop-save-mode "22.1")
  
+ (defun desktop-save-mode-off ()
+   "Disable `desktop-save-mode'.  Provided for use in hooks."
+   (desktop-save-mode 0))
+ 
  (defcustom desktop-save 'ask-if-new
    "*Specifies whether the desktop should be saved when it is killed.
  A desktop is killed when the user changes desktop or quits Emacs.
***************
*** 194,199 ****
--- 198,210 ----
  (define-obsolete-variable-alias 'desktop-basefilename
                                  'desktop-base-file-name "22.1")
  
+ (defcustom desktop-base-lock-name
+   (convert-standard-filename ".emacs.desktop.lock")
+   "Name of lock file for Emacs desktop, excluding the directory part."
+   :type 'file
+   :group 'desktop
+   :version "22.2")
+ 
  (defcustom desktop-path '("." "~")
    "List of directories to search for the desktop file.
  The base name of the file is specified in `desktop-base-file-name'."
***************
*** 219,224 ****
--- 230,244 ----
    :group 'desktop
    :version "22.1")
  
+ (defcustom desktop-not-loaded-hook nil
+   "Normal hook run when the user declines to re-use a desktop file.
+ Run in the directory in which the desktop file was found.
+ May be used to deal with accidental multiple Emacs jobs."
+   :type 'hook
+   :group 'desktop
+   :options '(desktop-save-mode-off save-buffers-kill-emacs)
+   :version "22.2")
+ 
  (defcustom desktop-after-read-hook nil
    "Normal hook run after a successful `desktop-read'.
  May be used to show a buffer list."
***************
*** 486,491 ****
--- 506,516 ----
  DIRNAME omitted or nil means use `desktop-dirname'."
    (expand-file-name desktop-base-file-name (or dirname desktop-dirname)))
  
+ (defun desktop-full-lock-name (&optional dirname)
+   "Return the full name of the desktop lock file in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (expand-file-name desktop-base-lock-name (or dirname desktop-dirname)))
+ 
  (defconst desktop-header
  ";; --------------------------------------------------------------------------
  ;; Desktop File for Emacs
***************
*** 496,501 ****
--- 521,559 ----
    "Hooks run after all buffers are loaded; intended for internal use.")
  
  ;; ----------------------------------------------------------------------------
+ ;; Desktop file conflict detection
+ (defvar desktop-file-modtime nil
+   "When the desktop file was last modified to the knowledge of this Emacs.
+ Used to detect desktop file conflicts.")
+ 
+ (defun desktop-owner (&optional dirname)
+   "Return the PID of the Emacs process that owns the desktop file in DIRNAME.
+ Return nil if no desktop file found or no Emacs process is using it.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (let (owner)
+     (and (file-exists-p (desktop-full-lock-name dirname))
+ 	 (condition-case nil
+ 	     (with-temp-buffer (insert-file-contents-literally
+ 				(desktop-full-lock-name dirname))
+ 			       (goto-char (point-min))
+ 			       (setq owner (read (current-buffer)))
+ 			       (integerp owner))
+ 	   (error nil))
+ 	 owner)))
+ 
+ (defun desktop-claim-lock (&optional dirname)
+   "Record this Emacs process as the owner of the desktop file in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (write-region (number-to-string (emacs-pid)) nil
+ 		(desktop-full-lock-name dirname)))
+ 
+ (defun desktop-release-lock (&optional dirname)
+   "Remove the lock file for the desktop in DIRNAME.
+ DIRNAME omitted or nil means use `desktop-dirname'."
+   (let ((file (desktop-full-lock-name dirname)))
+     (when (file-exists-p file) (delete-file file))))
+ 
+ ;; ----------------------------------------------------------------------------
  (defun desktop-truncate (list n)
    "Truncate LIST to at most N elements destructively."
    (let ((here (nthcdr (1- n) list)))
***************
*** 556,565 ****
                 (lambda (dir)
                   (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
!         (desktop-save desktop-dirname)
        (file-error
         (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
!          (signal (car err) (cdr err)))))))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-list* (&rest args)
--- 614,625 ----
                 (lambda (dir)
                   (interactive "DDirectory for desktop file: ") dir))))))
      (condition-case err
! 	(desktop-save desktop-dirname t)
        (file-error
         (unless (yes-or-no-p "Error while saving the desktop.  Ignore? ")
! 	 (signal (car err) (cdr err))))))
!   ;; If we own it, we don't anymore.
!   (if (eq (emacs-pid) (desktop-owner)) (desktop-release-lock)))
  
  ;; ----------------------------------------------------------------------------
  (defun desktop-list* (&rest args)
***************
*** 574,579 ****
--- 634,675 ----
        value)))
  
  ;; ----------------------------------------------------------------------------
+ (defun desktop-buffer-info (buffer)
+   (set-buffer buffer)
+   (list
+    ;; basic information
+    (desktop-file-name (buffer-file-name) dirname) (buffer-name) major-mode
+    ;; minor modes
+    (let (ret)
+      (mapc
+       #'(lambda (minor-mode)
+ 	  (and
+ 	   (boundp minor-mode)
+ 	   (symbol-value minor-mode)
+ 	   (let* ((special (assq minor-mode desktop-minor-mode-table))
+ 		  (value (cond (special (cadr special))
+ 			       ((functionp minor-mode) minor-mode))))
+ 	     (when value (add-to-list 'ret value)))))
+       (mapcar #'car minor-mode-alist))
+      ret)
+    ;; point and mark, and read-only status
+    (point) (list (mark t) mark-active) buffer-read-only
+    ;; auxiliary information
+    (when (functionp desktop-save-buffer)
+      (funcall desktop-save-buffer dirname))
+    ;; local variables
+    (let ((locals desktop-locals-to-save)
+ 	 (loclist (buffer-local-variables))
+ 	 (ll))
+      (while locals
+        (let ((here (assq (car locals) loclist)))
+ 	 (if here (setq ll (cons here ll))
+ 	   (when (member (car locals) loclist)
+ 	     (setq ll (cons (car locals) ll)))))
+        (setq locals (cdr locals)))
+      ll)))
+ 
+ ;; ----------------------------------------------------------------------------
  (defun desktop-internal-v2s (value)
    "Convert VALUE to a pair (QUOTE . TXT); (eval (read TXT)) gives VALUE.
  TXT is a string that when read and evaluated yields value.
***************
*** 724,813 ****
  
  ;; ----------------------------------------------------------------------------
  ;;;###autoload
! (defun desktop-save (dirname)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
!   (run-hooks 'desktop-save-hook)
!   (setq dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((filename (desktop-full-file-name dirname))
!           (info
!             (mapcar
!               #'(lambda (b)
!                   (set-buffer b)
!                   (list
!                     (desktop-file-name (buffer-file-name) dirname)
!                     (buffer-name)
!                     major-mode
!                     ;; minor modes
!                     (let (ret)
!                       (mapc
!                         #'(lambda (minor-mode)
!                           (and
!                             (boundp minor-mode)
!                             (symbol-value minor-mode)
!                             (let* ((special (assq minor-mode desktop-minor-mode-table))
!                                    (value (cond (special (cadr special))
!                                                 ((functionp minor-mode) minor-mode))))
!                               (when value (add-to-list 'ret value)))))
!                         (mapcar #'car minor-mode-alist))
!                       ret)
!                     (point)
!                     (list (mark t) mark-active)
!                     buffer-read-only
!                     ;; Auxiliary information
!                     (when (functionp desktop-save-buffer)
!                       (funcall desktop-save-buffer dirname))
!                     (let ((locals desktop-locals-to-save)
!                           (loclist (buffer-local-variables))
!                           (ll))
!                       (while locals
!                         (let ((here (assq (car locals) loclist)))
!                           (if here
!                             (setq ll (cons here ll))
!                             (when (member (car locals) loclist)
!                               (setq ll (cons (car locals) ll)))))
!                         (setq locals (cdr locals)))
!                       ll)))
!               (buffer-list)))
!           (eager desktop-restore-eager))
!       (with-temp-buffer
!         (insert
!          ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
!          desktop-header
!          ";; Created " (current-time-string) "\n"
!          ";; Desktop file format version " desktop-file-version "\n"
!          ";; Emacs version " emacs-version "\n\n"
!          ";; Global section:\n")
!         (dolist (varspec desktop-globals-to-save)
!           (desktop-outvar varspec))
!         (if (memq 'kill-ring desktop-globals-to-save)
!             (insert
!              "(setq kill-ring-yank-pointer (nthcdr "
!              (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
!              " kill-ring))\n"))
! 
!         (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
!         (dolist (l info)
!           (when (apply 'desktop-save-buffer-p l)
!             (insert "("
!                     (if (or (not (integerp eager))
!                             (unless (zerop eager)
!                               (setq eager (1- eager))
!                               t))
!                         "desktop-create-buffer"
!                       "desktop-append-buffer-args")
!                     " "
!                     desktop-file-version)
!             (dolist (e l)
!               (insert "\n  " (desktop-value-to-string e)))
!             (insert ")\n\n")))
!         (setq default-directory dirname)
!         (let ((coding-system-for-write 'emacs-mule))
!           (write-region (point-min) (point-max) filename nil 'nomessage)))))
!   (setq desktop-dirname dirname))
  
  ;; ----------------------------------------------------------------------------
  ;;;###autoload
--- 820,888 ----
  
  ;; ----------------------------------------------------------------------------
  ;;;###autoload
! (defun desktop-save (dirname &optional release)
    "Save the desktop in a desktop file.
  Parameter DIRNAME specifies where to save the desktop file.
+ Optional parameter RELEASE says whether we're done with this desktop.
  See also `desktop-base-file-name'."
    (interactive "DDirectory to save desktop file in: ")
!   (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
    (save-excursion
!     (let ((eager desktop-restore-eager)
! 	  (new-modtime (nth 5 (file-attributes (desktop-full-file-name)))))
!       (when
! 	  (or (not new-modtime)		; nothing to overwrite
! 	      (equal desktop-file-modtime new-modtime)
! 	      (yes-or-no-p (if desktop-file-modtime
! 			       (if (> (float-time new-modtime) (float-time desktop-file-modtime))
! 				   "Desktop file is more recent than the one loaded.  Save anyway? "
! 				 "Desktop file isn't the one loaded.  Overwrite it? ")
! 			     "Current desktop was not loaded from a file.  Overwrite this desktop file? "))
! 	      (unless release (error "Desktop file conflict")))
! 
! 	;; If we're done with it, release the lock.
! 	;; Otherwise, claim it if it's unclaimed or if we created it.
! 	(if release (desktop-release-lock)
! 	  (unless (and new-modtime (desktop-owner)) (desktop-claim-lock)))
! 
! 	(with-temp-buffer
! 	  (insert
! 	   ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
! 	   desktop-header
! 	   ";; Created " (current-time-string) "\n"
! 	   ";; Desktop file format version " desktop-file-version "\n"
! 	   ";; Emacs version " emacs-version "\n")
! 	  (save-excursion (run-hooks 'desktop-save-hook))
! 	  (goto-char (point-max))
! 	  (insert "\n;; Global section:\n")
! 	  (mapc (function desktop-outvar) desktop-globals-to-save)
! 	  (if (memq 'kill-ring desktop-globals-to-save)
! 	      (insert
! 	       "(setq kill-ring-yank-pointer (nthcdr "
! 	       (int-to-string (- (length kill-ring) (length kill-ring-yank-pointer)))
! 	       " kill-ring))\n"))
! 
! 	  (insert "\n;; Buffer section -- buffers listed in same order as in buffer list:\n")
! 	  (dolist (l (mapcar 'desktop-buffer-info (buffer-list)))
! 	    (when (apply 'desktop-save-buffer-p l)
! 	      (insert "("
! 		      (if (or (not (integerp eager))
! 			      (unless (zerop eager)
! 				(setq eager (1- eager))
! 				t))
! 			  "desktop-create-buffer"
! 			"desktop-append-buffer-args")
! 		      " "
! 		      desktop-file-version)
! 	      (dolist (e l)
! 		(insert "\n  " (desktop-value-to-string e)))
! 	      (insert ")\n\n")))
! 
! 	  (setq default-directory dirname)
! 	  (let ((coding-system-for-write 'emacs-mule))
! 	    (write-region (point-min) (point-max) (desktop-full-file-name) nil 'nomessage))
! 	  ;; We remember when it was modified (which is presumably just now).
! 	  (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name)))))))))
  
  ;; ----------------------------------------------------------------------------
  ;;;###autoload
***************
*** 856,890 ****
               ;; Default: Home directory.
               "~"))))
      (if (file-exists-p (desktop-full-file-name))
!       ;; Desktop file found, process it.
!       (let ((desktop-first-buffer nil)
!             (desktop-buffer-ok-count 0)
!             (desktop-buffer-fail-count 0)
!             ;; Avoid desktop saving during evaluation of desktop buffer.
! 	    (desktop-save nil))
! 	(desktop-lazy-abort)
!         ;; Evaluate desktop buffer.
!         (load (desktop-full-file-name) t t t)
!         ;; `desktop-create-buffer' puts buffers at end of the buffer list.
!         ;; We want buffers existing prior to evaluating the desktop (and not reused)
!         ;; to be placed at the end of the buffer list, so we move them here.
!         (mapc 'bury-buffer
!               (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
!         (switch-to-buffer (car (buffer-list)))
!         (run-hooks 'desktop-delay-hook)
!         (setq desktop-delay-hook nil)
!         (run-hooks 'desktop-after-read-hook)
!         (message "Desktop: %d buffer%s restored%s%s."
!                  desktop-buffer-ok-count
!                  (if (= 1 desktop-buffer-ok-count) "" "s")
!                  (if (< 0 desktop-buffer-fail-count)
!                      (format ", %d failed to restore" desktop-buffer-fail-count)
!                    "")
!                  (if desktop-buffer-args-list
!                      (format ", %d to restore lazily"
!                              (length desktop-buffer-args-list))
!                    ""))
!         t)
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))
--- 931,981 ----
               ;; Default: Home directory.
               "~"))))
      (if (file-exists-p (desktop-full-file-name))
! 	;; Desktop file found, but is it already in use?
! 	(let ((desktop-first-buffer nil)
! 	      (desktop-buffer-ok-count 0)
! 	      (desktop-buffer-fail-count 0)
! 	      (owner (desktop-owner))
! 	      ;; Avoid desktop saving during evaluation of desktop buffer.
! 	      (desktop-save nil))
! 	  (if (and owner
! 		   (not (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\nUsing it may cause conflicts.  Use it anyway? " owner))))
! 	      (progn (setq desktop-dirname nil)
! 		     (let ((default-directory desktop-dirname))
! 		       (run-hooks 'desktop-not-loaded-hook))
! 		     (message "Desktop file in use; not loaded."))
! 	    (desktop-lazy-abort)
! 	    ;; Evaluate desktop buffer and remember when it was modified.
! 	    (load (desktop-full-file-name) t t t)
! 	    (setq desktop-file-modtime (nth 5 (file-attributes (desktop-full-file-name))))
! 	    ;; If it wasn't already, mark it as in-use, to bother other
! 	    ;; desktop instances.
! 	    (unless owner
! 	      (condition-case nil (desktop-claim-lock)
! 		(file-error (message "Couldn't record use of desktop file")
! 			    (sit-for 1))))
! 
! 	    ;; `desktop-create-buffer' puts buffers at end of the buffer list.
! 	    ;; We want buffers existing prior to evaluating the desktop (and
! 	    ;; not reused) to be placed at the end of the buffer list, so we
! 	    ;; move them here.
! 	    (mapc 'bury-buffer
! 		  (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
! 	    (switch-to-buffer (car (buffer-list)))
! 	    (run-hooks 'desktop-delay-hook)
! 	    (setq desktop-delay-hook nil)
! 	    (run-hooks 'desktop-after-read-hook)
! 	    (message "Desktop: %d buffer%s restored%s%s."
! 		     desktop-buffer-ok-count
! 		     (if (= 1 desktop-buffer-ok-count) "" "s")
! 		     (if (< 0 desktop-buffer-fail-count)
! 			 (format ", %d failed to restore" desktop-buffer-fail-count)
! 		       "")
! 		     (if desktop-buffer-args-list
! 			 (format ", %d to restore lazily"
! 				 (length desktop-buffer-args-list))
! 		       ""))
! 	    t))
        ;; No desktop file found.
        (desktop-clear)
        (let ((default-directory desktop-dirname))

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-08 21:17                       ` Davis Herring
@ 2007-06-08 21:29                         ` Juanma Barranquero
  2007-06-08 22:05                           ` Davis Herring
  2007-06-08 22:14                         ` Juri Linkov
  1 sibling, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2007-06-08 21:29 UTC (permalink / raw)
  To: herring; +Cc: emacs-devel

On 6/8/07, Davis Herring <herring@lanl.gov> wrote:

> As far as I know, nothing has been done with it.

Well, of course. My question was like a reminder, to get the thing
back on track. So thanks for updating the patch :)

> I've attached an updated patch vs. current CVS; in it I have
> optimistically tagged my two new defcustoms as new in 22.2.

I'm gonna give it a try right now. I'm currently running 22.1,
EMACS_22_BASE and HEAD, mostly in parallel, and I'm sick of
overwriting my desktop file by accident.

             Juanma

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-08 21:29                         ` Juanma Barranquero
@ 2007-06-08 22:05                           ` Davis Herring
  0 siblings, 0 replies; 72+ messages in thread
From: Davis Herring @ 2007-06-08 22:05 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: emacs-devel

Also, I offer a trivial typo patch, which hopefully won't get wrapped badly:

*** desktop.el
--- desktop.el
***************
*** 423,429 ****
  Each entry has the form (NAME RESTORE-FUNCTION).
  NAME is the name of the buffer-local variable indicating that the minor
  mode is active.  RESTORE-FUNCTION is the function to activate the minor
mode.
! called.  RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
  this table.  See also `desktop-minor-mode-handlers'."
--- 443,449 ----
  Each entry has the form (NAME RESTORE-FUNCTION).
  NAME is the name of the buffer-local variable indicating that the minor
  mode is active.  RESTORE-FUNCTION is the function to activate the minor
mode.
! RESTORE-FUNCTION nil means don't try to restore the minor mode.
  Only minor modes for which the name of the buffer-local variable
  and the name of the minor mode function are different have to be added to
  this table.  See also `desktop-minor-mode-handlers'."

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-08 21:17                       ` Davis Herring
  2007-06-08 21:29                         ` Juanma Barranquero
@ 2007-06-08 22:14                         ` Juri Linkov
  2007-06-09  0:51                           ` Davis Herring
  1 sibling, 1 reply; 72+ messages in thread
From: Juri Linkov @ 2007-06-08 22:14 UTC (permalink / raw)
  To: herring; +Cc: Juanma Barranquero, emacs-devel

> I've attached an updated patch vs. current CVS; in it I have
> optimistically tagged my two new defcustoms as new in 22.2.  Here's a stab
> at a ChangeLog:

I have in .emacs

    (run-at-time 3600 3600 'desktop-save "~")

so desktop-save silently saves the desktop every hour.

Does you patch cause a problem by asking questions about file locks
inside such a timer?

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-08 22:14                         ` Juri Linkov
@ 2007-06-09  0:51                           ` Davis Herring
  2007-06-09 21:31                             ` Juri Linkov
  0 siblings, 1 reply; 72+ messages in thread
From: Davis Herring @ 2007-06-09  0:51 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Juanma Barranquero, emacs-devel

> I have in .emacs
>
>     (run-at-time 3600 3600 'desktop-save "~")
>
> so desktop-save silently saves the desktop every hour.
>
> Does you patch cause a problem by asking questions about file locks
> inside such a timer?

Er, I'm guessing it does... it certainly doesn't check to see if it's
being run in a less than interactive fashion.  (How does one even do that?
 Either of the standard interactive checks?)  But the real question is
what would you want it to do there instead of ask?

 - Is this sort of call supposed to automatically get priority and steal
locks and such?  If so, what happens when two Emacs instances run this
timer (as in interleaved, not even simultaneously)?
 - Alternatively, is it supposed to always fail if a clash is detected?
 - Or should there be entirely different heuristics...?

I guess I should note (partly just to give this message more than one
declarative sentence) that if you don't save the desktop from another
Emacs (even if you start one and re-use this autosaved desktop), it won't
prompt the next time the timer runs.  So if you actually "respect" the
clash detection and don't create a conflicting desktop, there won't be a
problem.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-09  0:51                           ` Davis Herring
@ 2007-06-09 21:31                             ` Juri Linkov
  2007-06-10 23:28                               ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Juri Linkov @ 2007-06-09 21:31 UTC (permalink / raw)
  To: herring; +Cc: Juanma Barranquero, emacs-devel

>> I have in .emacs
>>     (run-at-time 3600 3600 'desktop-save "~")
>> so desktop-save silently saves the desktop every hour.
>>
>> Does you patch cause a problem by asking questions about file locks
>> inside such a timer?
>
> Er, I'm guessing it does... it certainly doesn't check to see if it's
> being run in a less than interactive fashion.  (How does one even do that?
>  Either of the standard interactive checks?)  But the real question is
> what would you want it to do there instead of ask?
>
>  - Is this sort of call supposed to automatically get priority and steal
> locks and such?  If so, what happens when two Emacs instances run this
> timer (as in interleaved, not even simultaneously)?

Overwriting the desktop of another Emacs instance is not a good thing to do.

>  - Alternatively, is it supposed to always fail if a clash is detected?

Not writing the desktop would be acceptable if it displayed a message
about this failure.

>  - Or should there be entirely different heuristics...?

Another alternative is to write the desktop file with a different name.

> I guess I should note (partly just to give this message more than one
> declarative sentence) that if you don't save the desktop from another
> Emacs (even if you start one and re-use this autosaved desktop), it won't
> prompt the next time the timer runs.  So if you actually "respect" the
> clash detection and don't create a conflicting desktop, there won't be a
> problem.

All on all, we could leave this to the user's discretion.  The user should be
careful about not creating a configuration where two Emacs instances
automatically write to the same file.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-09 21:31                             ` Juri Linkov
@ 2007-06-10 23:28                               ` Juanma Barranquero
  2007-06-11 20:54                                 ` Juri Linkov
  0 siblings, 1 reply; 72+ messages in thread
From: Juanma Barranquero @ 2007-06-10 23:28 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

On 6/9/07, Juri Linkov <juri@jurta.org> wrote:

> Overwriting the desktop of another Emacs instance is not a good thing to do.

Well, that's exactly what happens without this patch.

> Not writing the desktop would be acceptable if it displayed a message
> about this failure.

What is the exact use case?

> Another alternative is to write the desktop file with a different name.

You can already do that, with or without the patch. The patch offers
you the alternative of detecting the conflict when you run the second
Emacs instance, so you chose not to load the desktop, and then
manually set another name for it or create it in another directory.

> All on all, we could leave this to the user's discretion.  The user should be
> careful about not creating a configuration where two Emacs instances
> automatically write to the same file.

I'm not sure what this means: are you proposing not installing the
patch? Because the point (to me anyway) is not having a configuration
where two instances write to the same file, but detecting the case
when that happens by accident.

The patch is very useful and works quite well (though I've added it an
option to configure whether the second instance should automatically
overwrite a conflicting desktop file, automatically skip loading it,
or ask the user, instead of always asking as Davis' original patch
does).

I propose installing it and seeing what other people thinks of it.

             Juanma

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-10 23:28                               ` Juanma Barranquero
@ 2007-06-11 20:54                                 ` Juri Linkov
  2007-06-12 11:21                                   ` Juanma Barranquero
  0 siblings, 1 reply; 72+ messages in thread
From: Juri Linkov @ 2007-06-11 20:54 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: emacs-devel

>> Overwriting the desktop of another Emacs instance is not a good thing to do.
>
> Well, that's exactly what happens without this patch.
>
>> Not writing the desktop would be acceptable if it displayed a message
>> about this failure.
>
> What is the exact use case?

Something like a message saying "Can't write the desktop because it is
locked by another Emacs instance".  Not a good solution either.

>> Another alternative is to write the desktop file with a different name.
>
> You can already do that, with or without the patch. The patch offers
> you the alternative of detecting the conflict when you run the second
> Emacs instance, so you chose not to load the desktop, and then
> manually set another name for it or create it in another directory.

But this requires complicate configuration on the user's part.

>> All on all, we could leave this to the user's discretion.  The user
>> should be careful about not creating a configuration where two Emacs
>> instances automatically write to the same file.
>
> I'm not sure what this means: are you proposing not installing the
> patch? Because the point (to me anyway) is not having a configuration
> where two instances write to the same file, but detecting the case
> when that happens by accident.

No, I propose installing this patch.  I had only doubts how it would
behave with my configuration.  But with the functions Davis implemented
in his patch, it is easy to write a configuration which won't fail, e.g.:

    (unless (desktop-owner)
      (run-at-time 3600 3600 'desktop-save "~"))

that starts automatic saving only when the desktop is not locked in
another Emacs session.

> The patch is very useful and works quite well (though I've added it an
> option to configure whether the second instance should automatically
> overwrite a conflicting desktop file, automatically skip loading it,
> or ask the user, instead of always asking as Davis' original patch
> does).

Such an option would be useful.

> I propose installing it and seeing what other people thinks of it.

I agree.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: A few questions about desktop.el
  2007-06-11 20:54                                 ` Juri Linkov
@ 2007-06-12 11:21                                   ` Juanma Barranquero
  0 siblings, 0 replies; 72+ messages in thread
From: Juanma Barranquero @ 2007-06-12 11:21 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

On 6/11/07, Juri Linkov <juri@jurta.org> wrote:

> No, I propose installing this patch.  I had only doubts how it would
> behave with my configuration.  But with the functions Davis implemented
> in his patch, it is easy to write a configuration which won't fail  [...]

OK, I've installed Davis' patch and my patch with the new
`desktop-load-locked-desktop' option (name's irrelevant, better
suggestions welcome).

The only nitpick I have now is that when the desktop is not loaded,
the message to the user is barely visible.

Perhaps it'd be good to define a function like:

(defun desktop-warn-desktop-not-loaded ()
   (display-warning 'desktop "Desktop file not loaded" :warning))

and add it as another option for `desktop-not-loaded-hook'.

             Juanma

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2007-06-12 11:21 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-22  2:42 A few questions about desktop.el Juanma Barranquero
2005-07-22 10:53 ` Juanma Barranquero
2005-07-22 22:52   ` Richard M. Stallman
2005-07-26  8:56     ` Juanma Barranquero
2005-07-27 14:03       ` Richard M. Stallman
2005-07-27 14:28         ` Juanma Barranquero
2005-07-28  3:20           ` Richard M. Stallman
2005-07-28  7:34             ` David Kastrup
2005-07-28 12:51               ` Juanma Barranquero
2005-07-29  0:11               ` Richard M. Stallman
2005-07-28  3:20           ` Richard M. Stallman
2005-07-29  0:37             ` Juanma Barranquero
2005-07-28  4:24           ` Masatake YAMATO
2006-04-27 23:05           ` Stuart D. Herring
2006-04-28 14:56             ` Juanma Barranquero
2006-04-29  4:57               ` Stuart D. Herring
2006-04-30  1:16                 ` Juanma Barranquero
2006-05-02 15:06                   ` Stuart D. Herring
2006-05-02 15:14                     ` Juanma Barranquero
2006-05-02 15:42                       ` Stuart D. Herring
2006-05-02 17:57                         ` Stuart D. Herring
2006-04-28 15:44             ` Richard Stallman
2006-04-29  5:02               ` Stuart D. Herring
2006-04-30  3:03                 ` Richard Stallman
2006-05-03 12:48               ` Juri Linkov
2006-05-03 14:37                 ` Lars Hansen
2006-05-03 20:43                   ` Richard Stallman
2006-05-04 16:27                   ` Stuart D. Herring
2006-05-05  6:44                     ` Lars Hansen
2007-06-05  9:24                     ` Juanma Barranquero
2007-06-08 21:17                       ` Davis Herring
2007-06-08 21:29                         ` Juanma Barranquero
2007-06-08 22:05                           ` Davis Herring
2007-06-08 22:14                         ` Juri Linkov
2007-06-09  0:51                           ` Davis Herring
2007-06-09 21:31                             ` Juri Linkov
2007-06-10 23:28                               ` Juanma Barranquero
2007-06-11 20:54                                 ` Juri Linkov
2007-06-12 11:21                                   ` Juanma Barranquero
2006-05-04 16:17                 ` Stuart D. Herring
2005-08-08 15:02   ` Lars Hansen
2005-07-22 13:50 ` Juanma Barranquero
2005-07-22 14:36   ` Juanma Barranquero
2005-07-26  8:27     ` Juanma Barranquero
2005-08-08 15:04     ` Lars Hansen
2005-07-22 19:11 ` Lars Hansen
2005-07-22 21:24   ` Juanma Barranquero
2005-07-22 22:50 ` Richard M. Stallman
2005-07-26  9:11   ` Juanma Barranquero
2005-07-27 14:04     ` Richard M. Stallman
2005-07-27 14:16       ` Juanma Barranquero
2005-07-28  3:20         ` Richard M. Stallman
2005-07-29  0:44           ` Juanma Barranquero
2005-08-10  9:50         ` Lars Hansen
2005-08-10 11:24           ` Juanma Barranquero
2006-02-09 16:30             ` Juanma Barranquero
2006-02-09 20:00               ` Lars Hansen
2006-02-09 21:11               ` Lars Hansen
2006-02-09 23:46                 ` Juanma Barranquero
2005-08-10 22:05           ` Luc Teirlinck
2005-08-10 23:45             ` Luc Teirlinck
2005-08-11  1:12               ` Luc Teirlinck
2005-08-11  1:36                 ` Luc Teirlinck
2005-08-11  3:01                 ` Luc Teirlinck
2005-08-11  6:12                   ` Lars Hansen
2005-08-08 14:51 ` Lars Hansen
2005-08-08 18:35   ` Juanma Barranquero
2005-08-09  7:12     ` Lars Hansen
2005-08-09  7:36       ` Lars Hansen
2005-08-09  8:49       ` Juanma Barranquero
2005-08-09  9:31         ` David Kastrup
2005-08-09  9:59           ` Juanma Barranquero

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).