[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#18158: D Mode: Getting rid of the ugly advice on looking-at.
From: |
Alan Mackenzie |
Subject: |
bug#18158: D Mode: Getting rid of the ugly advice on looking-at. |
Date: |
Sun, 2 Feb 2020 11:56:41 +0000 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
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).
- bug#18158: D Mode: Getting rid of the ugly advice on looking-at.,
Alan Mackenzie <=