all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
@ 2020-05-03 20:30 Michal Nazarewicz
  2020-05-04  3:15 ` Richard Stallman
       [not found] ` <mailman.1983.1588537924.3066.bug-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 4+ messages in thread
From: Michal Nazarewicz @ 2020-05-03 20:30 UTC (permalink / raw)
  To: 41061

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 +))
+
 \f
 * 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






^ permalink raw reply related	[flat|nested] 4+ messages in thread

* bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
  2020-05-03 20:30 bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’ Michal Nazarewicz
@ 2020-05-04  3:15 ` Richard Stallman
  2020-05-04 20:00   ` bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’ Michał Nazarewicz
       [not found] ` <mailman.1983.1588537924.3066.bug-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 4+ messages in thread
From: Richard Stallman @ 2020-05-04  3:15 UTC (permalink / raw)
  To: Michal Nazarewicz; +Cc: 41061

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







^ permalink raw reply	[flat|nested] 4+ messages in thread

* bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
  2020-05-04  3:15 ` Richard Stallman
@ 2020-05-04 20:00   ` Michał Nazarewicz
  0 siblings, 0 replies; 4+ messages in thread
From: Michał Nazarewicz @ 2020-05-04 20:00 UTC (permalink / raw)
  To: rms; +Cc: 41061

On Mon, 4 May 2020 at 04:17, Richard Stallman <rms@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»





^ permalink raw reply	[flat|nested] 4+ messages in thread

* bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’
       [not found] ` <mailman.1983.1588537924.3066.bug-gnu-emacs@gnu.org>
@ 2020-06-01 17:27   ` Alan Mackenzie
  0 siblings, 0 replies; 4+ messages in thread
From: Alan Mackenzie @ 2020-06-01 17:27 UTC (permalink / raw)
  To: Michal Nazarewicz; +Cc: 41061

Hello, Michal.

In article <mailman.1983.1588537924.3066.bug-gnu-emacs@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).






^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-06-01 17:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-03 20:30 bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’ Michal Nazarewicz
2020-05-04  3:15 ` Richard Stallman
2020-05-04 20:00   ` bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’ Michał Nazarewicz
     [not found] ` <mailman.1983.1588537924.3066.bug-gnu-emacs@gnu.org>
2020-06-01 17:27   ` bug#41061: [PATCH] cc-mode: add ‘c-lineup-ternary-bodies’ Alan Mackenzie

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.