From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: end-of-defun is fubsr. Date: Tue, 3 Feb 2009 18:58:12 +0000 Message-ID: <20090203185812.GH1396@muc.de> References: <20090202202703.GB11077@muc.de> <20090203105035.GB1396@muc.de> <20090203122906.GC1396@muc.de> <20090203130028.GD1396@muc.de> <20090203160941.GE1396@muc.de> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1233686405 14142 80.91.229.12 (3 Feb 2009 18:40:05 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 3 Feb 2009 18:40:05 +0000 (UTC) Cc: Miles Bader , emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Feb 03 19:41:19 2009 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1LUQCl-00080N-8F for ged-emacs-devel@m.gmane.org; Tue, 03 Feb 2009 19:41:03 +0100 Original-Received: from localhost ([127.0.0.1]:58937 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LUQBS-0007PC-FO for ged-emacs-devel@m.gmane.org; Tue, 03 Feb 2009 13:39:42 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LUQAT-0006aL-GD for emacs-devel@gnu.org; Tue, 03 Feb 2009 13:38:41 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LUQAR-0006Z1-TZ for emacs-devel@gnu.org; Tue, 03 Feb 2009 13:38:40 -0500 Original-Received: from [199.232.76.173] (port=41957 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LUQAR-0006Yk-9y for emacs-devel@gnu.org; Tue, 03 Feb 2009 13:38:39 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:2555 helo=mail.muc.de) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LUQAQ-0004y3-8i for emacs-devel@gnu.org; Tue, 03 Feb 2009 13:38:38 -0500 Original-Received: (qmail 95541 invoked by uid 3782); 3 Feb 2009 18:38:32 -0000 Original-Received: from acm.muc.de (pD9E51F3C.dip.t-dialin.net [217.229.31.60]) by colin2.muc.de (tmda-ofmipd) with ESMTP; Tue, 03 Feb 2009 19:38:30 +0100 Original-Received: (qmail 26693 invoked by uid 1000); 3 Feb 2009 18:58:12 -0000 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.9i X-Delivery-Agent: TMDA/1.1.5 (Fettercairn) X-Primary-Address: acm@muc.de X-detected-operating-system: by monty-python.gnu.org: FreeBSD 4.6-4.9 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:108700 Archived-At: 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).