bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#12867: 24.3.50; easy-to-repro crash involving mode line


From: Drew Adams
Subject: bug#12867: 24.3.50; easy-to-repro crash involving mode line
Date: Mon, 12 Nov 2012 09:09:43 -0800

> > I want to use the fact that a %l construct in the mode line 
> > enables you to do something dynamic when the cursor moves to
> > another line.
>
> May I inquire why you don't use the (:eval FORM) construct?  IIUC,
> this does exactly what you want and is supported since Emacs 21.1.

I do use (:eval FORM), including in connection with this particular code.  I
have so far not seen how to use it to do what %l does wrt cursor movement among
lines.

That is, %l triggers redisplay when the current line changes.  It is that
triggering that I miss otherwise; it is not evaluating to produce the right
display (e.g. using :eval), once redisplay is triggered.

The code I use is here, if you are interested - see functions
`bmkp-bmenu-mode-line' and `bmkp-bmenu-mode-line-string' (they are both short -
I can include them in the bug thread, if you prefer):
http://www.emacswiki.org/emacs-en/download/bookmark%2b-bmu.el

I will be glad to find a way to simplify the code and remove this ugly little
hack.  Suggestions welcome.

Yes, I could instead use, say, `post-command-hook' and `force-mode-line-update'
if the line changes.  But %l triggers mode-line redisplay on line changes, and
it seems to me better to let it do the triggering than to call `count-lines' in
a Lisp function on `post-command-hook'.

I don't have a problem using either approach, but for now I prefer the %l
approach.  With the workaround I use it does the job fine.  I just wish there
were a way to get its line-change triggering of redisplay without its attendant
line-number display.

> > 1. The %l construct must be present in the `mode-line-format'.
> > 2. Its resulting line-number text must not have property 
> > `invisible'.
> 
> The need to redisplay the mode line on every move of point is a killer
> of many redisplay optimizations.  It is also potentially expensive by
> itself, because it requires Emacs to count lines, something that is
> not an easy operation in Emacs, which sees the buffer text as a linear
> array of characters, not a series of lines.  So the display engine
> tries very hard to avoid redisplaying the mode line if it decides that
> the line number does not need to appear.

I understand.  But somehow it DTRT, for %l, at least.

What I am missing (in my current knowledge) is how to make the display engine
redisplay the mode line when the current line changes, without my using %l.  

(I mean just using `mode-line-format', not calling `force-mode-line-update'
explicitly, from, say, `post-command-hook'.)

%l takes care of that redisplay triggering, but it also shows the line number.
I want the redisplay triggering without also showing the line number (I show
other info instead).

> This is probably the explanation for what you see.  Still, it is not
> entirely clear to me what "must" means in this context, so please show
> the mode-line spec you tried and tell what didn't work when 1 or 2
> above was not true.  Maybe there's something else involved.

Not entirely sure I remember all that I tried.  Trying the following now shows
that the " (line)" part of the text is made invisible but the line number itself
is not:

(defun foo ()
  (set (make-local-variable 'mode-line-position)
       '(:propertize "%l (line)" invisible t))
  (set (make-local-variable 'mode-line-format)
       '(("" mode-name mode-line-position))))

I thought that something I tried earlier using text property `invisible' made
all of the text invisible, including the line #, but also broke the dynamic
update wrt current line.  Perhaps I was mistaken about that - perhaps the code I
was testing just led to an error that somehow prevented the %l formatted text
from being used at all.  Dunno.

(The symptom was that the line number did not appear in the mode line, and the
mode line was not updated wrt current-line changes.  And I did not get the
*invalid* mode-line-format display that typically indicates a mode-line
display/formatting error.)

But at any rate, trying the code above you can see that it does not make the
line number itself disappear.  Shouldn't it?  Or perhaps I am missing something
and there is a simple way to make that text invisible?

> > Besides fixing the crash, it would be great if I did not 
> > have to resort to such an ugly hack in the first place.
> >  
> > Presumably, this feature of dynamic line-sensitive updating 
> > is buried in the bowels of Emacs C code, so not available to
> > Lisp users to tweak.  Must this feature really be tied to an
> > actual display of the line number?  If so, can't we at least
> > make that text invisible?
> 
> If :eval doesn't fit the bill, please tell why.

I have no idea why.

> If there's need to make changes in the display engine to support
> the feature you want to implement, I'd prefer to invest the energy
> in providing a clean solution, rather than making mode-line-position
> serve as a back door for such ugly hacks.

Fine by me.

> > Regardless, it would also be good if this feature (line-sensitive
> > updating) were documented.  I could find nothing that even 
> > hinted at it.
> 
> Sorry, I don't understand: what is undocumented?  If you are talking
> about refreshing mode-line-position, then shouldn't it be obvious that
> it's refreshed on every move of point?

The %l spec is documented.  It is clear enough that if you move the cursor to
another line then the line # shown in the mode line gets updated automatically
(from %l, by the redisplay code).  So far, so good.

What is not so obvious is that you can automatically update anything at all in
the mode line when the cursor changes line, as long as you include %l somewhere
in the `mode-line-format'.  IOW, %l triggers mode-line redisplay when you change
lines, and your mode-line code can take advantage of that.  (But you must show
the line number as well.)

I don't know an easier way to get that redisplay-on-line-change triggering
behavior.  You mentioned using :eval, but AFAICT that is not enough (or perhaps
is not so simple/obvious).

I do use :eval to format the mode-line info dynamically, but line-sensitive
redisplay is not _triggered_ unless I also add %l.  Once I add that, then the
:eval I have DTRT, showing the right info that is pertinent to the current line.

I would be pleased to learn that I am just missing something simple.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]