GNU bug report logs - #41061
[PATCH] cc-mode: add ‘c-lineup-ternary-bodies’

Previous Next

Package: emacs;

Reported by: Michal Nazarewicz <mina86 <at> mina86.com>

Date: Sun, 3 May 2020 20:32:01 UTC

Severity: wishlist

Tags: patch

Done: Michał Nazarewicz <mina86 <at> mina86.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 41061 in the body.
You can then email your comments to 41061 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#41061; Package emacs. (Sun, 03 May 2020 20:32:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Michal Nazarewicz <mina86 <at> mina86.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sun, 03 May 2020 20:32:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Michal Nazarewicz <mina86 <at> mina86.com>
To: bug-gnu-emacs <at> gnu.org
Subject: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
Date: Sun,  3 May 2020 21:30:47 +0100
Introduce ‘c-lineup-ternary-bodies’ function which, when used as
a c lineup function, aligns question mark and colon of a ternary
operator.  For example:

    return arg % 2 == 0 ? arg / 2
                        : (3 * arg + 1);

* lisp/progmodes/cc-align.el (c-lineup-ternary-bodies): New function.
* doc/misc/cc-mode.texi (Operator Line-Up Functions): Document the
new function.
* test/lisp/progmodes/cc-mode-tests.el (c-lineup-ternary-bodies): New
test case.
---

It’s not perfectly clear to me whether there is a better
implementation of this.  Some sort of function that cc-mode provides
which parses an expression into a syntax tree of some kind perhaps.
The approach I’ve taken does seem to work well enough though.

If there isn’t any opposition to this, I’m gonna push it in a week or
so.

 doc/misc/cc-mode.texi                | 20 +++++++++++++++++
 etc/NEWS                             | 18 ++++++++++++++++
 lisp/progmodes/cc-align.el           | 32 ++++++++++++++++++++++++++++
 test/lisp/progmodes/cc-mode-tests.el | 20 +++++++++++++++++
 4 files changed, 90 insertions(+)

diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index f9c9f5e1830..16eac4828c7 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -6395,6 +6395,26 @@ Operator Line-Up
 
 @comment ------------------------------------------------------------
 
+@defun c-lineup-ternary-bodies
+@findex lineup-ternary-bodies @r{(c-)}
+Line up true and false branches of a ternary operator
+(i.e. @code{?:}).  More precisely, if the line starts with a colon
+which is a part of a said operator it with corresponding question
+mark.  For example:
+
+@example
+@group
+return arg % 2 == 0 ? arg / 2
+                    : (3 * arg + 1);    @hereFn{c-lineup-ternary-bodies}
+@end group
+@end example
+
+@workswith @code{arglist-cont}, @code{arglist-cont-nonempty} and
+@code{statement-cont}.
+@end defun
+
+@comment ------------------------------------------------------------
+
 @defun c-lineup-cascaded-calls
 @findex lineup-cascaded-calls @r{(c-)}
 Line up ``cascaded calls'' under each other.  If the line begins with
diff --git a/etc/NEWS b/etc/NEWS
index 753b7a7fd36..1b805784338 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -302,6 +302,24 @@ use ‘doxygen’ by default one might evaluate:
                     (c++-mode  . doxygen)))
 
 or use it in a custom ‘c-style’.
+
+*** Added support to line up ‘?’ and ‘:’ of a ternary operator.
+The new ‘c-lineup-ternary-bodies’ function can be used as a lineup
+function to align question mark and colon which are part of a ternary
+operator (‘?:’).  For example:
+
+    return arg % 2 == 0 ? arg / 2
+                        : (3 * arg + 1);
+
+To enable, add it to appropriate entries in ‘c-offsets-alist’, e.g.:
+
+    (c-set-offset 'arglist-cont '(c-lineup-ternary-bodies
+                                  c-lineup-gcc-asm-reg))
+    (c-set-offset 'arglist-cont-nonempty '(c-lineup-ternary-bodies
+                                           c-lineup-gcc-asm-reg
+                                           c-lineup-arglist))
+    (c-set-offset 'statement-cont '(c-lineup-ternary-bodies +))
+
 
 * New Modes and Packages in Emacs 28.1
 
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index f30477dc787..a6f3f1f8024 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -790,6 +790,38 @@ c-lineup-math
   (or (c-lineup-assignments langelem)
       c-basic-offset))
 
+(defun c-lineup-ternary-bodies (langelem)
+  "Line up true and false branches of a ternary operator (i.e. ‘?:’).
+More precisely, if the line starts with a colon which is a part of
+a said operator it with corresponding question mark; otherwise return
+nil.  For example:
+
+    return arg % 2 == 0 ? arg / 2
+                        : (3 * arg + 1);    <- c-lineup-ternary-bodies
+
+Works with: arglist-cont, arglist-cont-nonempty and statement-cont.
+"
+  (save-excursion
+    (back-to-indentation)
+    (when (and (eq ?: (char-after))
+               (not (eq ?: (char-after (1+ (point))))))
+      (let ((limit (c-langelem-pos langelem)) (depth 1))
+        (catch 'done
+          (while (c-syntactic-skip-backward "^?:" limit t)
+            (goto-char (1- (point)))
+            (cond ((eq (char-after) ??)
+                   ;; If we’ve found a question mark, decrease depth.  If we’re
+                   ;; reached zero, we’ve found the one we were looking for.
+                   (when (zerop (setq depth (1- depth)))
+                     (throw 'done (vector (current-column)))))
+                  ((or (eq ?: (char-before)) (eq ?? (char-before)))
+                   ;; Step over ‘::’ and ‘?:’ operators.  We don’t have to
+                   ;; handle ‘?:’ here but doing so saves an iteration.
+                   (if (eq (point) limit)
+                       (throw 'done)
+                     (goto-char (1- (point)))))
+                  ((setq depth (1+ depth)))))))))) ; Otherwise increase depth.
+
 (defun c-lineup-cascaded-calls (langelem)
   "Line up \"cascaded calls\" under each other.
 If the line begins with \"->\" or \".\" and the preceding line ends
diff --git a/test/lisp/progmodes/cc-mode-tests.el b/test/lisp/progmodes/cc-mode-tests.el
index 0729841ce6f..cd461f55181 100644
--- a/test/lisp/progmodes/cc-mode-tests.el
+++ b/test/lisp/progmodes/cc-mode-tests.el
@@ -78,4 +78,24 @@ c-mode-macro-comment
       (insert macro-string)
       (c-mode))))
 
+(ert-deftest c-lineup-ternary-bodies ()
+  "Test for c-lineup-ternary-bodies function"
+  (with-temp-buffer
+    (c-mode)
+    (let* ((common-prefix "int value = condition ? ")
+           (expected-column (- (length common-prefix) 2)))
+      (dolist (test '(("a : \n b" . nil)
+                      ("a \n ::b" . nil)
+                      ("a \n : b" . t)
+                      ("::a \n : b" . t)
+                      ("(p ? q : r) \n : b" . t)
+                      ("p ?: q \n : b" . t)
+                      ("p ? : q \n : b" . t)
+                      ("p ? q : r \n : b" . t)))
+        (delete-region (point-min) (point-max))
+        (insert common-prefix (car test))
+        (should (equal
+                 (and (cdr test) (vector expected-column))
+                 (c-lineup-ternary-bodies '(statement-cont . 1))))))))
+
 ;;; cc-mode-tests.el ends here
-- 
2.26.2





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41061; Package emacs. (Mon, 04 May 2020 03:17:01 GMT) Full text and rfc822 format available.

Message #8 received at 41061 <at> debbugs.gnu.org (full text, mbox):

From: Richard Stallman <rms <at> gnu.org>
To: Michal Nazarewicz <mina86 <at> mina86.com>
Cc: 41061 <at> debbugs.gnu.org
Subject: Re: bug#41061: [PATCH] cc-mode: add
 ‘c-lineup-ternary-bodies’
Date: Sun, 03 May 2020 23:15:59 -0400
[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

      > return arg % 2 == 0 ? arg / 2
      >                     : (3 * arg + 1);

You can format the code that way if you like,
but the GNU convention is like this:

      return (arg % 2 == 0
      	      ? arg / 2
              : 3 * arg + 1);

That not only makes the nesting very clear,
it also indents correctly without a special hack.


-- 
Dr Richard Stallman
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41061; Package emacs. (Mon, 04 May 2020 20:01:01 GMT) Full text and rfc822 format available.

Message #11 received at 41061 <at> debbugs.gnu.org (full text, mbox):

From: Michał Nazarewicz <mina86 <at> mina86.com>
To: rms <at> gnu.org
Cc: 41061 <at> debbugs.gnu.org
Subject: Re: bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
Date: Mon, 4 May 2020 21:00:06 +0100
On Mon, 4 May 2020 at 04:17, Richard Stallman <rms <at> gnu.org> wrote:
>       > return arg % 2 == 0 ? arg / 2
>       >                     : (3 * arg + 1);
>
> You can format the code that way if you like,

It’s more that project I’m involved in enforces such style.
It’s one of the alignments clang-format supports so I’m likely
not the only person who needs to conform to this particular
style.

> but the GNU convention is like this:
>
>       return (arg % 2 == 0
>               ? arg / 2
>               : 3 * arg + 1);
>
> That not only makes the nesting very clear,
> it also indents correctly without a special hack.

-- 
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»




Severity set to 'wishlist' from 'normal' Request was from Michał Nazarewicz <mina86 <at> mina86.com> to control <at> debbugs.gnu.org. (Sat, 09 May 2020 10:45:01 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 41061 <at> debbugs.gnu.org and Michal Nazarewicz <mina86 <at> mina86.com> Request was from Michał Nazarewicz <mina86 <at> mina86.com> to control <at> debbugs.gnu.org. (Sat, 09 May 2020 10:45:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41061; Package emacs. (Mon, 01 Jun 2020 17:28:01 GMT) Full text and rfc822 format available.

Message #18 received at 41061 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Michal Nazarewicz <mina86 <at> mina86.com>
Cc: 41061 <at> debbugs.gnu.org
Subject: Re: bug#41061: [PATCH] cc-mode: add
 ‘c-lineup-ternary-bodies’
Date: 1 Jun 2020 17:27:11 -0000
Hello, Michal.

In article <mailman.1983.1588537924.3066.bug-gnu-emacs <at> gnu.org> you wrote:
> Introduce ‘c-lineup-ternary-bodies’ function which, when used as
> a c lineup function, aligns question mark and colon of a ternary
> operator.  For example:

>     return arg % 2 == 0 ? arg / 2
>                         : (3 * arg + 1);

> * lisp/progmodes/cc-align.el (c-lineup-ternary-bodies): New function.
> * doc/misc/cc-mode.texi (Operator Line-Up Functions): Document the
> new function.
> * test/lisp/progmodes/cc-mode-tests.el (c-lineup-ternary-bodies): New
> test case.
> ---

> It’s not perfectly clear to me whether there is a better
> implementation of this.  Some sort of function that cc-mode provides
> which parses an expression into a syntax tree of some kind perhaps.
> The approach I’ve taken does seem to work well enough though.

> If there isn’t any opposition to this, I’m gonna push it in a week or
> so.

Which you did.

This afternoon I tidied up one or two typos, and made a trivial
amendment to the code.

Just one thing: please keep curly quotes right out of the CC Mode
sources.  They make working with the code more difficult (these
characters don't exist on many keyboard layouts) and add nothing of
value.  The same applies to other awkward non-keyboard characters
unless, of course, there's a good reason for using them, such as their
being part of somebody's name.

Thanks!

-- 
Alan Mackenzie (Nuremberg, Germany).





bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 30 Jun 2020 11:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 4 years and 358 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.