From: Alan Mackenzie <acm@muc.de>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: Miles Bader <miles@gnu.org>, emacs-devel@gnu.org
Subject: Re: end-of-defun is fubsr.
Date: Tue, 3 Feb 2009 18:58:12 +0000 [thread overview]
Message-ID: <20090203185812.GH1396@muc.de> (raw)
In-Reply-To: <jwvocxjsbpm.fsf-monnier+emacs@gnu.org>
Hi, Stefan!
On Tue, Feb 03, 2009 at 12:13:19PM -0500, Stefan Monnier wrote:
> > end-of-defun (in .../lisp/emacs-lisp/lisp.el) is buggy, at least when an
> > end-of-defun-function has been defined:
> > (i) After calling end-of-defun-function, e-o-d takes it upon itself
> > to advance an arbitrary amount of whitespace/comments. This is what
> > you (Miles) were complaining about.
> It should only move from "right after the closing }" to BOL 7.
> Not "an arbitrary amount of whitespace". Of course, there might be
Sorry, yes, I was wrong. It moves at most one line forward.
> a bug, but my guess is that your end-of-defun-function jumpts to BOL
> 7 rather than right after the brace. So the problem is a disagreement
> between the two.
Exactly. There is no documentation which says whether a [BE]OD-function
should adjust for WS/Comments or not. I think it should, because the
variable name doesn't end in "-raw-function", and the major mode knows
better than the Emacs core where the best finishing point is.
How about:
(defvar beginning-of-defun-function ....
"If non-nil, function for `beginning-of-defun-raw' to call.
This is used to move to the beginning of the defun instead of using the
normal recipe (see `beginning-of-defun'). Major modes can define this
if defining `defun-prompt-regexp' is not sufficient to handle the
mode's needs.
The function takes one optional arg, the number of defuns to go back.
It should leave point at a sensible place just before the defun starts,
e.g. at the start of the line, or before a block comment preceding it.
It should return non-nil on success, or nil on failure.
> > (ii) When point is BETWEEN two C functions (more precisely JUST AFTER
> > the end of the previous function), C-M-e doesn't move over the next
> > function. This is because it gets its knickers in a twist, first
> > calling BOD-raw, then EOD-function, trying to check if its succeeded
> > yet, etc. ......... This is crazy!
> This might be linked to the above problem. For Elisp it seems to
> work correctly.
The problem is that end-of-defun calls beginning-of-defun-raw at each
iteration (over ARG). It thus discards the information as to whether
point began in a defun or between 2 defuns.
> > This mechanism is entirely unsuited to CC Mode.
> > c-\(beginning\|end\)-of-defun have a very high setup (determining
> > whether point is within a function's block, or header, etc.) and tear
> > down (locating the start of a function's header) time, but is lightening
> > fast zipping through brace blocks in between. This high setup/teardown
> > time has been the cause of several "it's too slow" bugs (e.g. for C-x 4
> > a) in the last few years.
> > The current implementation of end-of-defun is essentially calling
> > c-end-of-defun AND c-beginning-of-defun in a loop, sometimes calling
> > them twice in each iteration. This is slow for large ARG. It's crazy!
> > To see this, go into buffer.c, and do
> > C-u 106 C-M-e
> > . On my box, this takes 20s. By contrast, C-u 106 C-M-a takes about
> > 0.5s.
> I don't consider "C-u 106 C-M-e" as a common operation.
No, but when a simple operation takes 20s on a faster machine than a
12 MHz 386SX, something's less than optimal. And when there are enough
top-level declarations without braces, this time will extend to several
minutes. There are enough CC Mode users that quite a few will be calling
C-M-e with repeat counts.
What's bugging the Hades out of me is that I've put a LOT of effort into
optimising c-\(beginning\|end\)-of-defun, and that's being rendered
completely useless, at least for C-M-e, by an inept way of calling these
functions. Several bug reports which made this work necessary came
directly from Emacs Developers (for example, C-x 4 a taking a minute to
run, or hassle with potential K&R regions taking just as long).
I foresee that immediately after the release of Emacs 23 there will be at
least one complaint about the sluggishness of C-M-e, and my reply will be
to agree, to apologise for it, and to tell the complainer just to bind
C-M-[ae] in c-mode-base-map. Chance are, there will be several. Hello,
lots of unrewarding repetitive and uncreative drudge work.
Having come this far, why can't we just do the job right? Or, failing
that, at least bind C-M-[ae] in c-mode-base-map in Emacs-23?
Surely there's nobody here who isn't sick and fed up with this defun
movement business? Surely to goodness, after 25 years, we should be able
to do major-mode specific defun movement as a matter of course?
> > Also, the semantics of end-of-defun-function have been completely
> > changed (specifically, in lisp.el v1.82, 2007-11-26) so that it now
> > has only a coincidental connection with what its name suggests.
> Huh? It hasn't completely changed. Some details have changed to make
> it easier to implement a simple end-of-defun-function, while making
> sure that end-of-defun behaves consistently.
It's changed from "move to next end of function" to "move to the end of
the function at whose beginning we now are", and its default value is
`forward-sexp'. `c-end-of-defun' was a good fit for the variable as it
formerly was, but is now severely suboptimal.
> It was mostly a matter of fixing end-of-defun which was completely
> broken when passed negative arguments.
Surely we have two cases: if the major mode supplies a EOD-function (old
semantics), e-o-d should simply invoke it. Otherwise (e.g. Elisp), why
not just do (scan-lists -1 1) (on the last iteration) to locate the
pertinent ")"?
> > 1/- end-of-defun-function should be restored to its prior semantics, and
> > additionally be passed the ARG argument in the same way as BOD-function.
> Not sure about restoring the previous semantics. But I could agree to
> the additional ARG argument, which could even let it "take over" (so
> beginning-of-defun-raw is not called in that case).
:-) Let's do it!
> > 3/- end-of-defun should be restructured along the lines of
> > beginning-of-defun.
> I don't think that's a good idea. The main reason is to deal with
> languages that allow nested functions.
Don't follow - In the upcoming CC Mode 5.32 code (in the CVS repository
at SourceForge), C-M-[ae] works just fine for C++ defuns nested inside
classes/namespaces and so on. The mechanism is entirely within CC Mode.
> Stefan
--
Alan Mackenzie (Nuremberg, Germany).
next prev parent reply other threads:[~2009-02-03 18:58 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-02 8:13 end-of-defun acts weirdly in c-mode; also, mark-defun in c-mode Miles Bader
2009-02-02 20:27 ` Alan Mackenzie
2009-02-02 22:46 ` Stefan Monnier
2009-02-03 9:17 ` Miles Bader
2009-02-03 10:50 ` Alan Mackenzie
2009-02-03 11:23 ` Miles Bader
2009-02-03 11:35 ` Miles Bader
2009-02-03 12:29 ` Alan Mackenzie
2009-02-03 13:00 ` Alan Mackenzie
2009-02-03 16:09 ` end-of-defun is fubsr. [Was: end-of-defun acts weirdly in c-mode] Alan Mackenzie
2009-02-03 15:56 ` Juanma Barranquero
2009-02-03 16:34 ` end-of-defun is fubsr Chong Yidong
2009-02-03 17:18 ` Andreas Roehler
2009-02-04 11:33 ` Alan Mackenzie
2009-02-04 14:54 ` Andreas Roehler
2009-02-03 16:40 ` end-of-defun is fubsr. [Was: end-of-defun acts weirdly in c-mode] Alan Mackenzie
2009-02-03 17:13 ` end-of-defun is fubsr Stefan Monnier
2009-02-03 18:58 ` Alan Mackenzie [this message]
2009-02-03 20:50 ` Stefan Monnier
2009-02-04 0:14 ` Alan Mackenzie
2009-02-04 2:21 ` Stefan Monnier
2009-02-04 13:37 ` Alan Mackenzie
2009-02-04 14:29 ` Stefan Monnier
2009-02-04 15:44 ` Alan Mackenzie
2009-02-05 10:37 ` Andreas Roehler
2009-02-12 21:35 ` Stefan Monnier
2009-02-13 11:08 ` Alan Mackenzie
2009-02-13 14:31 ` Stefan Monnier
2009-02-13 16:42 ` Alan Mackenzie
2009-02-13 17:06 ` Stefan Monnier
2009-02-13 18:57 ` Alan Mackenzie
2009-02-14 4:22 ` Stefan Monnier
2009-02-14 18:00 ` Alan Mackenzie
2009-02-14 21:16 ` Stefan Monnier
2009-02-14 23:25 ` Alan Mackenzie
2009-02-15 0:57 ` Miles Bader
2009-02-15 19:26 ` Stefan Monnier
2009-02-15 22:00 ` Alan Mackenzie
2009-02-05 11:44 ` Problems C Mode has with src/regex.c [was: end-of-defun is fubsr.] Alan Mackenzie
2009-02-05 21:50 ` end-of-defun acts weirdly in c-mode Alan Mackenzie
2009-02-06 1:03 ` Glenn Morris
2009-02-06 12:23 ` Alan Mackenzie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090203185812.GH1396@muc.de \
--to=acm@muc.de \
--cc=emacs-devel@gnu.org \
--cc=miles@gnu.org \
--cc=monnier@IRO.UMontreal.CA \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.