all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Russel Winder <russel@winder.org.uk>,
	Vladimir Panteleev <vladimir@thecybershadow.net>
Cc: 18158@debbugs.gnu.org, stefan@marxist.se, liranz@gmail.com
Subject: bug#18158: D Mode: Getting rid of the ugly advice on looking-at.
Date: Sun, 2 Feb 2020 11:56:41 +0000	[thread overview]
Message-ID: <20200202115641.GA5547@ACM> (raw)
In-Reply-To: <etPan.53da61c8.70a64e2a.16175@engine.local>

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).





  parent reply	other threads:[~2020-02-02 11:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-31 15:33 bug#18158: Fix extra indent of d-mode "else static if" statements in cc-engine.el Liran Zvibel
2020-01-20 21:18 ` Stefan Kangas
2020-01-26 15:29   ` Alan Mackenzie
2020-01-29  1:26     ` Liran Zvibel
2020-01-31 19:41       ` Alan Mackenzie
2020-02-02 11:56 ` Alan Mackenzie [this message]
2020-02-02 16:59   ` bug#18158: D Mode: Getting rid of the ugly advice on looking-at Vladimir Panteleev
2020-02-07 21:31     ` Alan Mackenzie
     [not found]     ` <20200207213100.GB8591@ACM>
2020-02-13 13:37       ` Vladimir Panteleev

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=20200202115641.GA5547@ACM \
    --to=acm@muc.de \
    --cc=18158@debbugs.gnu.org \
    --cc=liranz@gmail.com \
    --cc=russel@winder.org.uk \
    --cc=stefan@marxist.se \
    --cc=vladimir@thecybershadow.net \
    /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.