From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs Subject: bug#18158: D Mode: Getting rid of the ugly advice on looking-at. Date: Sun, 2 Feb 2020 11:56:41 +0000 Message-ID: <20200202115641.GA5547@ACM> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="35826"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mutt/1.10.1 (2018-07-13) Cc: 18158@debbugs.gnu.org, stefan@marxist.se, liranz@gmail.com To: Russel Winder , Vladimir Panteleev Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Feb 02 12:57:13 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1iyDsH-0009AS-9G for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 02 Feb 2020 12:57:13 +0100 Original-Received: from localhost ([::1]:55330 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iyDsG-0005Qr-8d for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 02 Feb 2020 06:57:12 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:60473) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iyDs8-0005Qj-7s for bug-gnu-emacs@gnu.org; Sun, 02 Feb 2020 06:57:05 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iyDs6-0000NT-Mh for bug-gnu-emacs@gnu.org; Sun, 02 Feb 2020 06:57:04 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:33585) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iyDs6-0000NK-I2; Sun, 02 Feb 2020 06:57:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iyDs6-0005AI-Gr; Sun, 02 Feb 2020 06:57:02 -0500 X-Loop: help-debbugs@gnu.org In-Reply-To: Resent-From: Alan Mackenzie Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org, bug-cc-mode@gnu.org Resent-Date: Sun, 02 Feb 2020 11:57:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 18158 X-GNU-PR-Package: emacs,cc-mode X-GNU-PR-Keywords: moreinfo X-Debbugs-Original-Cc: bug-cc-mode@gnu.org, 18158@debbugs.gnu.org, Stefan Kangas , Liran Zvibel Original-Received: via spool by 18158-submit@debbugs.gnu.org id=B18158.158064461419840 (code B ref 18158); Sun, 02 Feb 2020 11:57:02 +0000 Original-Received: (at 18158) by debbugs.gnu.org; 2 Feb 2020 11:56:54 +0000 Original-Received: from localhost ([127.0.0.1]:39558 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iyDry-00059w-25 for submit@debbugs.gnu.org; Sun, 02 Feb 2020 06:56:54 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:45610 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1iyDro-00059Z-7i for 18158@debbugs.gnu.org; Sun, 02 Feb 2020 06:56:52 -0500 Original-Received: (qmail 46037 invoked by uid 3782); 2 Feb 2020 11:56:42 -0000 Original-Received: from acm.muc.de (p2E5D58E7.dip0.t-ipconnect.de [46.93.88.231]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sun, 02 Feb 2020 12:56:41 +0100 Original-Received: (qmail 5944 invoked by uid 1000); 2 Feb 2020 11:56:41 -0000 Content-Disposition: inline X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:175578 Archived-At: Hello, Russel and Vladimir. I am the maintainer of the CC Mode project at Sourceforge, and also CC Mode within Emacs. I hope you don't mind too much me writing to your personal Email addresses - the submission of bug reports to Github is restricted to those with a Github account, and I don't have and don't want a Github account. In the newest released d-mode.el (version 201812050604) at around line 698, advice is added to the function looking-at, such that (looking-at ""if\\>[^_]") will also return t on "static if" (and a couple of other things, too). This was done because of a lack of a needed feature in the base CC Mode. This advice is not ideal. If nothing else, it will be inconvenient should the regexp "if\\>[^_]" ever change to, say, "if\\_>". I am intending to make a change like this throughout CC Mode sometime, since "\\_<" and "\\_>" have existed in Emacs's regexp engine for at least 10 years, now. So, why not add suitable features to CC Mode so that this advice in d-mode.el is not needed any more? In the patches below, I have introduced two new c-lang-defconsts, c-post-else-if-prefix-kwds (which should take the value '("static") in D Mode) and c-post-else-no-indent-kwds (with value '("if" "debug" "version") in D Mode). c-add-stmt-syntax in cc-engine.el has been modified to use (c-lang-defvars derived from) these variables in place of the hard coded "if\\>[^_]". I suggest an amendment to d-mode.el along the lines of my patch below. It is intended to work with both the new CC Mode, and existing CC Mode versions, using a compile time test. At some time in the future, it should be possible to get rid of the old advice mechanism entirely. I propose to commit the patch for CC Mode, below. I would be grateful indeed if either of you could find the time to review it, first. Just a quick tip, though you probably don't need it: when compiling the new d-mode.el, be sure that the new cc-langs.elc has been loaded into your Emacs. So, here is the suggested patch for d-mode.el: --- d-mode.201812050604.el 2018-12-05 06:07:51.000000000 +0000 +++ d-mode.el 2020-02-02 11:31:41.724734790 +0000 @@ -334,6 +334,21 @@ d '("for" "if" "switch" "while" "catch" "synchronized" "scope" "foreach" "foreach_reverse" "with" "unittest")) +(cc-eval-when-compile + (when (c-safe (c-lang-const c-post-else-no-indent-kwds java)) + + (c-lang-defconst c-post-else-if-prefix-kwds + ;; Keywords which can come between "else" and "if" (or some other member + ;; of `c-post-else-no-indent-kwds') without giving the substatement being + ;; introduced extra indentation." + d '("static")) + + (c-lang-defconst c-post-else-no-indent-kwds + ;; Keywords which when following an "else" (possibly with intervening + ;; members of `c-post-else-if-prefix-kwds') do not cause extra + ;; indentation of the substatement being introduced. + d '("if" "debug" "version")))) + (c-lang-defconst c-simple-stmt-kwds ;; Statement keywords followed by an expression or nothing. d '("break" "continue" "goto" "return" "throw")) @@ -695,32 +710,35 @@ ;;---------------------------------------------------------------------------- ;;; Workaround for special case of 'else static if' not being handled properly -(defun d-special-case-looking-at (orig-fun &rest args) - ;; checkdoc-params: (orig-fun args) - "Advice function for fixing cc-mode indentation in certain D constructs." - (let ((rxp (car args))) - (if (and (stringp rxp) (string= rxp "if\\>[^_]")) - (or (apply orig-fun '("static\\>\\s-+if\\>[^_]")) - (apply orig-fun '("version\\>[^_]")) - (apply orig-fun '("debug\\>[^_]")) - (apply orig-fun args)) - (apply orig-fun args)))) - -(defun d-around--c-add-stmt-syntax (orig-fun &rest args) - ;; checkdoc-params: (orig-fun args) - "Advice function for fixing cc-mode indentation in certain D constructs." - (if (not (string= major-mode "d-mode")) - (apply orig-fun args) - (progn - (add-function :around (symbol-function 'looking-at) - #'d-special-case-looking-at) - (unwind-protect - (apply orig-fun args) - (remove-function (symbol-function 'looking-at) - #'d-special-case-looking-at))))) +(cc-eval-when-compile + (unless (c-safe (c-lang-const c-post-else-no-indent-kwds java)) + + (defun d-special-case-looking-at (orig-fun &rest args) + ;; checkdoc-params: (orig-fun args) + "Advice function for fixing cc-mode indentation in certain D constructs." + (let ((rxp (car args))) + (if (and (stringp rxp) (string= rxp "if\\>[^_]")) + (or (apply orig-fun '("static\\>\\s-+if\\>[^_]")) + (apply orig-fun '("version\\>[^_]")) + (apply orig-fun '("debug\\>[^_]")) + (apply orig-fun args)) + (apply orig-fun args)))) + + (defun d-around--c-add-stmt-syntax (orig-fun &rest args) + ;; checkdoc-params: (orig-fun args) + "Advice function for fixing cc-mode indentation in certain D constructs." + (if (not (string= major-mode "d-mode")) + (apply orig-fun args) + (progn + (add-function :around (symbol-function 'looking-at) + #'d-special-case-looking-at) + (unwind-protect + (apply orig-fun args) + (remove-function (symbol-function 'looking-at) + #'d-special-case-looking-at))))) -(when (version<= "24.4" emacs-version) - (advice-add 'c-add-stmt-syntax :around #'d-around--c-add-stmt-syntax)) + (when (version<= "24.4" emacs-version) + (advice-add 'c-add-stmt-syntax :around #'d-around--c-add-stmt-syntax)))) ;;---------------------------------------------------------------------------- ;;;###autoload , and my proposed patch for CC Mode. This patch applies cleanly to the Emacs 26.3 sources, and all later versions in the Emacs savannah repository: diff -r 6a0c16f6ef37 cc-engine.el --- a/cc-engine.el Mon Jan 27 17:50:19 2020 +0000 +++ b/cc-engine.el Sun Feb 02 11:36:01 2020 +0000 @@ -12275,7 +12275,10 @@ (looking-at "else\\>[^_]") (save-excursion (goto-char old-pos) - (looking-at "if\\>[^_]"))) + (while (looking-at c-post-else-if-prefix-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + (looking-at c-post-else-no-indent-key))) ; e.g. "if" ;; Special case to avoid deeper and deeper indentation ;; of "else if" clauses. ) diff -r 6a0c16f6ef37 cc-langs.el --- a/cc-langs.el Mon Jan 27 17:50:19 2020 +0000 +++ b/cc-langs.el Sun Feb 02 11:36:01 2020 +0000 @@ -2802,6 +2802,34 @@ (c-lang-const c-block-stmt-2-kwds))))) (c-lang-defvar c-opt-block-stmt-key (c-lang-const c-opt-block-stmt-key)) +(c-lang-defconst c-post-else-if-prefix-kwds + "Keywords which can come between \"else\" and \"if\" (or some other member of +`c-post-else-no-indent-kwds') without giving the substatement being introduced +extra indentation." + ;; This is used in D Mode. + t nil) + +(c-lang-defconst c-post-else-if-prefix-key + ;; Regexp matching a keyword in `c-post-else-if-prefix-kwds', or matching + ;; nothing. + t (c-make-keywords-re t (c-lang-const c-post-else-if-prefix-kwds))) +(c-lang-defvar c-post-else-if-prefix-key + (c-lang-const c-post-else-if-prefix-key)) + +(c-lang-defconst c-post-else-no-indent-kwds + "Keywords which when following an \"else\" (possibly with intervening members +of `c-post-else-if-prefix-kwds') do not cause extra indentation of the +substatement being introduced." + ;; This is used non-trivially in D Mode. + t '("if")) + +(c-lang-defconst c-post-else-no-indent-key + ;; Regexp matching a keyword in `c-post-else-no-indent-kwds', or matching + ;; nothing. + t (c-make-keywords-re t (c-lang-const c-post-else-no-indent-kwds))) +(c-lang-defvar c-post-else-no-indent-key + (c-lang-const c-post-else-no-indent-key)) + (c-lang-defconst c-simple-stmt-kwds "Statement keywords followed by an expression or nothing." t '("break" "continue" "goto" "return") -- Alan Mackenzie (Nuremberg, Germany).