all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* mode-line-format - local variableness
@ 2009-04-05 22:18 Drew Adams
  2009-04-05 22:50 ` Johan Bockgård
  2009-04-06  1:37 ` Stefan Monnier
  0 siblings, 2 replies; 11+ messages in thread
From: Drew Adams @ 2009-04-05 22:18 UTC (permalink / raw)
  To: emacs-devel

(defun foo (text &optional buffer)
  "Display TEXT in BUFFER's mode line for 2 sec."
  (with-current-buffer (or buffer (current-buffer))
    (let ((mode-line-format  text))
      (force-mode-line-update) (sit-for 2))
    (force-mode-line-update)))

M-: (foo "JJJJJ" "*scratch*")

In Emacs 20, JJJJJ is displayed in the mode-line of buffer *scratch* only. The
mode lines of other buffers are unaffected.

In Emacs 21 and later, *each* buffer's mode-line shows JJJJJ.

What am I missing? `mode-line-format' is a buffer-local variable. That makes me
think the Emacs 20 behavior is correct and the behavior since then is incorrect.
I assume I must be missing something here. Can someone please clue me in? Thx.





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

* Re: mode-line-format - local variableness
  2009-04-05 22:18 mode-line-format - local variableness Drew Adams
@ 2009-04-05 22:50 ` Johan Bockgård
  2009-04-05 23:24   ` Miles Bader
  2009-04-05 23:29   ` Drew Adams
  2009-04-06  1:37 ` Stefan Monnier
  1 sibling, 2 replies; 11+ messages in thread
From: Johan Bockgård @ 2009-04-05 22:50 UTC (permalink / raw)
  To: emacs-devel

"Drew Adams" <drew.adams@oracle.com> writes:

> What am I missing? `mode-line-format' is a buffer-local variable.

No, it isn't.

(local-variable-p 'mode-line-format)         => nil
(local-variable-if-set-p 'mode-line-format)  => t





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

* Re: mode-line-format - local variableness
  2009-04-05 22:50 ` Johan Bockgård
@ 2009-04-05 23:24   ` Miles Bader
  2009-04-05 23:29   ` Drew Adams
  1 sibling, 0 replies; 11+ messages in thread
From: Miles Bader @ 2009-04-05 23:24 UTC (permalink / raw)
  To: emacs-devel

bojohan+news@dd.chalmers.se (Johan Bockgård) writes:
>> What am I missing? `mode-line-format' is a buffer-local variable.
>
> No, it isn't.
>
> (local-variable-p 'mode-line-format)         => nil
> (local-variable-if-set-p 'mode-line-format)  => t

My impression is that let-binding of variables isn't generally so
well-defined in association with "magic" emacs features like
buffer-localness...

-Miles

-- 
Politeness, n. The most acceptable hypocrisy.





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

* RE: mode-line-format - local variableness
  2009-04-05 22:50 ` Johan Bockgård
  2009-04-05 23:24   ` Miles Bader
@ 2009-04-05 23:29   ` Drew Adams
  2009-04-05 23:37     ` Drew Adams
  1 sibling, 1 reply; 11+ messages in thread
From: Drew Adams @ 2009-04-05 23:29 UTC (permalink / raw)
  To: 'Johan "Bockgård"', emacs-devel

> From: Johan "Bockgård" Sent: Sunday, April 05, 2009 3:50 PM
> > What am I missing? `mode-line-format' is a buffer-local variable.
> 
> No, it isn't.
> (local-variable-p 'mode-line-format)         => nil
> (local-variable-if-set-p 'mode-line-format)  => t

Then there seems to be a bug (either Emacs behavior or doc). `C-h v
mode-line-format' seems to say that it is buffer-local:

"Automatically becomes buffer-local when set in any fashion."
And "Each buffer has its own value of this variable."

And exactly the same thing is said after you do M-: (make-variable-buffer-local
'mode-line-format). To me, that doc is saying that the variable is buffer-local
in all buffers: setting it in a buffer affects only the mode-line of that
buffer.

Looking at some of the Emacs source code, things are not too clear. hideshow.el
(why hideshow.el?), for instance, calls `make-variable-buffer-local' for it. I
don't see where it is made buffer-local generally (hide-show.el is not loaded by
default, AFAIK), but the doc string does seem to indicate that it is. (Maybe
it's done in C code.)

To me, the behavior from the code snippet I sent seems like a product bug, not a
doc bug. But Emacs has been this way apparently since Emacs 21 (not 20).
 
Wrt the code I sent (which uses `let', not `setq'), this, from Elisp manual node
Creating Buffer-Local, seems to be part of the explanation:

"A peculiar wrinkle of this feature is that binding the variable
(with `let' or other binding constructs) does not create a
buffer-local binding for it.  Only setting the variable (with
`set' or `setq'), while the variable does not have a `let'-style
binding that was made in the current buffer, does so."

That text was not present in Emacs 20, where the code works (only the mode-line
of the given buffer is affected).

I guess the bottom line is that I will need to use `setq' for the code to work
beyond Emacs 20. Presumably (hopefully), the change that introduced "this
feature" (whatever the undisclosed feature might be) did improve something, even
at the cost of breaking this. Further elucidations/advice is welcome.






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

* RE: mode-line-format - local variableness
  2009-04-05 23:29   ` Drew Adams
@ 2009-04-05 23:37     ` Drew Adams
  2009-04-06  0:50       ` Miles Bader
  0 siblings, 1 reply; 11+ messages in thread
From: Drew Adams @ 2009-04-05 23:37 UTC (permalink / raw)
  To: 'Johan "Bockgård"', emacs-devel

Summary (with no understanding of why, beyond the catechismic
don't-use-let-use-setq):

This will not work:

(defun foo (text &optional buffer)
  (with-current-buffer (or buffer (current-buffer))
    (let ((mode-line-format  text))
      (force-mode-line-update) (sit-for 2))
    (force-mode-line-update)))

This works (ugh!):

(defun foo (text &optional buffer)
  (with-current-buffer (or buffer (current-buffer))
    (let ((old-mode-line-format  mode-line-format))
      (setq mode-line-format  text)
      (force-mode-line-update) (sit-for 2)
      (setq mode-line-format  old-mode-line-format))
    (force-mode-line-update)))

Don't `let'-bind `mode-line-format', but you can `let'-bind something to its
value and then restore that later. Ugh!






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

* Re: mode-line-format - local variableness
  2009-04-05 23:37     ` Drew Adams
@ 2009-04-06  0:50       ` Miles Bader
  2009-04-06  3:05         ` Drew Adams
  0 siblings, 1 reply; 11+ messages in thread
From: Miles Bader @ 2009-04-06  0:50 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel, Johan Bockgård

"Drew Adams" <drew.adams@oracle.com> writes:
> Don't `let'-bind `mode-line-format', but you can `let'-bind something to its
> value and then restore that later. Ugh!

The issue is that things like buffer-local variables are (useful but)
weird, and there's a certain amount of hair involved in their
implementation.  They work pretty well when used as intended, but beyond
that, all bets are off.

[BTW, if you're gonna use setq, you should of course use unwind-protect.]

-Miles

-- 
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over.  --Ian Wolff




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

* Re: mode-line-format - local variableness
  2009-04-05 22:18 mode-line-format - local variableness Drew Adams
  2009-04-05 22:50 ` Johan Bockgård
@ 2009-04-06  1:37 ` Stefan Monnier
  2009-04-06  3:19   ` Drew Adams
  1 sibling, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2009-04-06  1:37 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel

>   (with-current-buffer (or buffer (current-buffer))
>     (let ((mode-line-format  text))
>       (force-mode-line-update) (sit-for 2))
>     (force-mode-line-update)))

Combining let-binding and buffer-local values is a difficult exercise.
The behavior of the above depends on whether mode-line-format is
currently buffer-local in the current buffer.  Some Elisp variables are
never buffer-local (e.g. the ones that are frame-local), others (most)
are by default global can be made buffer-local to a particular buffer by
calling `make-local-variable', others are buffer-local by default, which
means that they become buffer-local as soon as you use `setq' on them
(but not `let'), and finally yet others are simply always buffer-local
(e.g. default-directory).

It seems that mode-line-format was "always buffer-local" in Emacs-20 and
changed to "buffer-local by default" in Emacs-21.  I don't know what was
the reason for it, but in any case an explicit call to
`make-local-variable' before the let will clear up any ambiguity.


        Stefan




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

* RE: mode-line-format - local variableness
  2009-04-06  0:50       ` Miles Bader
@ 2009-04-06  3:05         ` Drew Adams
  0 siblings, 0 replies; 11+ messages in thread
From: Drew Adams @ 2009-04-06  3:05 UTC (permalink / raw)
  To: 'Miles Bader'; +Cc: emacs-devel, 'Johan Bockgård'

> [BTW, if you're gonna use setq, you should of course use 
> unwind-protect.]

Yes, I did that in my code. I left it off here, to keep it simple.





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

* RE: mode-line-format - local variableness
  2009-04-06  1:37 ` Stefan Monnier
@ 2009-04-06  3:19   ` Drew Adams
  2009-04-06 13:30     ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Drew Adams @ 2009-04-06  3:19 UTC (permalink / raw)
  To: 'Stefan Monnier'; +Cc: emacs-devel

> It seems that mode-line-format was "always buffer-local" in 
> Emacs-20 and changed to "buffer-local by default" in Emacs-21.
> I don't know what was the reason for it, but in any case an
> explicit call to `make-local-variable' before the let will
> clear up any ambiguity.

Oh, I thought it _was_ always buffer-local, even in recent Emacs. And I thought
the manual was advising not to use `let' with buffer-local variables. 

That text is not too clear to me. Is it trying to say instead to not use `let'
with a variable that _will be_ buffer-local but is not yet so? But it's OK to
use `let' with a variable that is already buffer-local? Not too clear, IMO.

Yes, it's simpler and looks cleaner to do what you mention than to monkey around
with setq and unwind-protect. From the doc, I didn't get the impression that
that would help, but it seems to work fine.

(defun foo (text &optional buffer)
  (with-current-buffer (or buffer (current-buffer))
    (make-local-variable 'mode-line-format)
    (let ((mode-line-format  text))
      (force-mode-line-update) (sit-for 10))
    (force-mode-line-update)))

Whether or not that is actually cleaner, I don't know, but it certainly looks
so. I admit that I don't understand the problem with `let' and
buffer-local-to-be-but-not-yet vars.





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

* Re: mode-line-format - local variableness
  2009-04-06  3:19   ` Drew Adams
@ 2009-04-06 13:30     ` Stefan Monnier
  2009-04-06 21:37       ` Miles Bader
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2009-04-06 13:30 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel

> Oh, I thought it _was_ always buffer-local, even in recent Emacs.
> And I thought the manual was advising not to use `let' with
> buffer-local variables. 

"Always buffer-local" is used for variables for which a "global value"
basically doesn't make any sense.  `buffer-file-name' for example.
mode-line-format, OTOH has a default global value shared by most
buffers.  Ideally it probably shouldn't even be made buffer-loal by
`setq' but only by `make-local-variable'.

> That text is not too clear to me. Is it trying to say instead to not
> use `let' with a variable that _will be_ buffer-local but is not yet
> so? But it's OK to use `let' with a variable that is already
> buffer-local? Not too clear, IMO.

In general it's better to avoid mixing let and buffer-local.  If you
have to, then try to make sure that during the let, the variable's
buffer-localness is not changed.
In older versions of Emacs (<21 IIRC) you alsa had to try and avoid
switching into another buffer during the let (or at least revert back to
the same buffer before finishing the let).

> Whether or not that is actually cleaner, I don't know, but it
> certainly looks so.  I admit that I don't understand the problem with
> `let' and buffer-local-to-be-but-not-yet vars.

(let ((x e1)) e2) is more or less equivalent to

   (let ((old-x x))
     (unwind-protect
         (progn (setq x e1) e2)
       (setq x old-x)))

So if the buffer-localness of x is changed in `e2' we have a problem: if
old-x was read from the global part of `x', should (setq x old-x) assign
to the new buffer-local part of `x' or to the global part of `x'
or both?  If OTOH `old-x' was read from the buffer-local part of `x' but
`x' was kill-local-variable'd, should (setq x old-x) "reset" the global
part of `x' or do nothing?

There are reasonable choices for these questions, but no matter what you
choose, you will sooner or later find a situation where it doesn't
actually do what was intended, and furthermore, the implementation tends
to be painful and costly, which is a bummer since it's supposed to be
a *very* rare case that's fairly easy to avoid, yet you'll end up paying
for it all the time.


        Stefan




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

* Re: mode-line-format - local variableness
  2009-04-06 13:30     ` Stefan Monnier
@ 2009-04-06 21:37       ` Miles Bader
  0 siblings, 0 replies; 11+ messages in thread
From: Miles Bader @ 2009-04-06 21:37 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:
> There are reasonable choices for these questions, but no matter what you
> choose, you will sooner or later find a situation where it doesn't
> actually do what was intended, and furthermore, the implementation tends
> to be painful and costly, which is a bummer since it's supposed to be
> a *very* rare case that's fairly easy to avoid, yet you'll end up paying
> for it all the time.

... and any guarantees we make now may come back to haunt us if we want
to change the way the internal mechanisms work later.

-Miles

-- 
Accord, n. Harmony.





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

end of thread, other threads:[~2009-04-06 21:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-05 22:18 mode-line-format - local variableness Drew Adams
2009-04-05 22:50 ` Johan Bockgård
2009-04-05 23:24   ` Miles Bader
2009-04-05 23:29   ` Drew Adams
2009-04-05 23:37     ` Drew Adams
2009-04-06  0:50       ` Miles Bader
2009-04-06  3:05         ` Drew Adams
2009-04-06  1:37 ` Stefan Monnier
2009-04-06  3:19   ` Drew Adams
2009-04-06 13:30     ` Stefan Monnier
2009-04-06 21:37       ` Miles Bader

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.