unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Gulshan Singh <gsingh2011@gmail.com>
Cc: acm@muc.de, Lars Ingebrigtsen <larsi@gnus.org>, 21409@debbugs.gnu.org
Subject: bug#21409: 24.5; Wrong syntactic information for two line statement in an arglist
Date: Sun, 13 Mar 2022 13:43:11 +0000	[thread overview]
Message-ID: <Yi3078jTItyPRzNt@ACM> (raw)
In-Reply-To: <YiyE4jK9zIVMK/SX@ACM>

Hello again, Gulshan.

On Sat, Mar 12, 2022 at 11:32:50 +0000, Alan Mackenzie wrote:

> Sorry I missed your bug report back in 2015.

> On Fri, Mar 11, 2022 at 17:52:38 -0800, Gulshan Singh wrote:
> > On Thu, Dec 3, 2020 at 3:07 AM Lars Ingebrigtsen <larsi@gnus.org> wrote:

> > > Gulshan Singh <gsingh2011@gmail.com> writes:

> > > > In c-mode (and all derivatives), the following code has the wrong
> > > > syntactic information (at least, in my opinion):

> > > > foo(bar
> > > >     .baz()
> > > >     .qux());

[ .... ]

> I think the best solution to the problem would be to write a new Line-Up
> function for this particular scenario, and to make it available to users
> to insert into the c-offsets-alist entry for arglist-cont-nonempty.  The
> page "Customizing Indentation" in the CC Mode manual is pertinent here.

> But first, we need to firm up the specification.  What, precisely, will
> trigger this new Line-Up function?

I've come up with an answer to that question.  On _any_ argument
continued onto the next line, we indent it c-basic-offset from the
_first_ argument.  This is easy to implement, since it's a minor
variation on c-lineup-arglist.  See the following patch for an example
of what that does.

[ .... ]

> > It's definitely reasonable, but it's not what I'd prefer, which would be
> > this:

> > foo(bar
> >       .baz()
> >       .qux());

> > `.baz()` and `.qux()` are indented two spaces (my value for
> > `c-basic-offset`) from the start of `bar`, as opposed to aligned with
> > `bar`. This matches what happens if the call to `foo` isn't there:

> > bar
> >   .baz()
> >   .qux();

I've hacked up the following patch, which introduces the new Line-Up
function c-lineup-arglist-+.  To use it (temporarily) do C-c C-o RET on
the .baz() line, and change the setting for arglist-cont-nonempty from

    (c-lineup-gcc-asm-reg c-lineup-arglist)

to

    (c-lineup-gcc-asm-reg c-lineup-arglist-+ c-lineup-arglist)

..  Note that c-lineup-arglist-+ is a function which returns nil to mean
"not appropriate here", so it must be in a list, not in the last
position.  This is all better explained in the CC Mode manual on page
"c-offsets-alist".

If this patch does what you want, you can then incorporate the new
Line-Up function into your CC Mode style, or however else you set up
your indentation.  If you want any help with this, feel free to ask on
this list, or on bug-cc-mode@gnu.org.

Here's the patch.  It should apply to either the latest version of
stand-alone CC Mode, or the version in the Emacs master branch.  Please
apply the patch, byte compile the changed file (or all of CC Mode), and
make the amendment to your indentation setup noted above.  (If you want
any help with any of this, feel free to send me private email).  Then
please let us know if this patch does the Right Thing.  Thanks!



diff -r 1a0681da2be1 cc-align.el
--- a/cc-align.el	Thu Feb 10 16:46:58 2022 +0000
+++ b/cc-align.el	Sun Mar 13 13:35:56 2022 +0000
@@ -207,6 +207,58 @@
 	  (vector (current-column)))))))
 
 ;; Contributed by Kevin Ryde <user42@zip.com.au>.
+(defun c-lineup-argcont-1 (elem)
+  ;; Move to the start of the current arg and return non-nil, otherwise
+  ;; return nil.
+  (beginning-of-line)
+
+  (when (eq (car elem) 'arglist-cont-nonempty)
+    ;; Our argument list might not be the innermost one.  If it
+    ;; isn't, go back to the last position in it.  We do this by
+    ;; stepping back over open parens until we get to the open paren
+    ;; of our argument list.
+    (let ((open-paren (c-langelem-2nd-pos c-syntactic-element))
+	  (paren-state (c-parse-state)))
+      (while (not (eq (car paren-state) open-paren))
+	(unless (consp (car paren-state)) ;; ignore matched braces
+	  (goto-char (car paren-state)))
+	(setq paren-state (cdr paren-state)))))
+
+  (let ((start (point)) c)
+
+    (when (bolp)
+      ;; Previous line ending in a comma means we're the start of an
+      ;; argument.  This should quickly catch most cases not for us.
+      ;; This case is only applicable if we're the innermost arglist.
+      (c-backward-syntactic-ws)
+      (setq c (char-before)))
+
+    (unless (eq c ?,)
+      ;; In a gcc asm, ":" on the previous line means the start of an
+      ;; argument.  And lines starting with ":" are not for us, don't
+      ;; want them to indent to the preceding operand.
+      (let ((gcc-asm (save-excursion
+		       (goto-char start)
+		       (c-in-gcc-asm-p))))
+	(unless (and gcc-asm
+		     (or (eq c ?:)
+			 (save-excursion
+			   (goto-char start)
+			   (looking-at "[ \t]*:"))))
+
+	  (c-lineup-argcont-scan (if gcc-asm ?:))
+	  t)))))
+
+(defun c-lineup-argcont-scan (&optional other-match)
+  ;; Find the start of an argument, for `c-lineup-argcont'.
+  (when (zerop (c-backward-token-2 1 t))
+    (let ((c (char-after)))
+      (if (or (eq c ?,) (eq c other-match))
+	  (progn
+	    (forward-char)
+	    (c-forward-syntactic-ws))
+	(c-lineup-argcont-scan other-match)))))
+
 (defun c-lineup-argcont (elem)
   "Line up a continued argument.
 
@@ -221,56 +273,28 @@
 for the operands.
 
 Works with: arglist-cont, arglist-cont-nonempty."
-
   (save-excursion
-    (beginning-of-line)
+    (when (c-lineup-argcont-1 elem)
+      (vector (current-column)))))
 
-    (when (eq (car elem) 'arglist-cont-nonempty)
-      ;; Our argument list might not be the innermost one.  If it
-      ;; isn't, go back to the last position in it.  We do this by
-      ;; stepping back over open parens until we get to the open paren
-      ;; of our argument list.
-      (let ((open-paren (c-langelem-2nd-pos c-syntactic-element))
-	    (paren-state (c-parse-state)))
-	(while (not (eq (car paren-state) open-paren))
-	  (unless (consp (car paren-state)) ;; ignore matched braces
-	    (goto-char (car paren-state)))
-	  (setq paren-state (cdr paren-state)))))
+(defun c-lineup-argcont-+ (langelem)
+  "Indent an argument continuation `c-basic-offset' in from the first argument.
 
-    (let ((start (point)) c)
-
-      (when (bolp)
-	;; Previous line ending in a comma means we're the start of an
-	;; argument.  This should quickly catch most cases not for us.
-	;; This case is only applicable if we're the innermost arglist.
-	(c-backward-syntactic-ws)
-	(setq c (char-before)))
+foo (xyz, uvw, aaa + bbb + ccc
+         + ddd + eee + fff);    <- c-lineup-argcont-+
+     <-->                          c-basic-offset
 
-      (unless (eq c ?,)
-	;; In a gcc asm, ":" on the previous line means the start of an
-	;; argument.  And lines starting with ":" are not for us, don't
-	;; want them to indent to the preceding operand.
-	(let ((gcc-asm (save-excursion
-			 (goto-char start)
-			 (c-in-gcc-asm-p))))
-	  (unless (and gcc-asm
-		       (or (eq c ?:)
-			   (save-excursion
-			     (goto-char start)
-			     (looking-at "[ \t]*:"))))
+Only continuation lines like this are touhced, nil being returned
+on lines which are the start of an argument.
 
-	    (c-lineup-argcont-scan (if gcc-asm ?:))
-	    (vector (current-column))))))))
-
-(defun c-lineup-argcont-scan (&optional other-match)
-  ;; Find the start of an argument, for `c-lineup-argcont'.
-  (when (zerop (c-backward-token-2 1 t))
-    (let ((c (char-after)))
-      (if (or (eq c ?,) (eq c other-match))
-	  (progn
-	    (forward-char)
-	    (c-forward-syntactic-ws))
-	(c-lineup-argcont-scan other-match)))))
+Works with: arglist-cont, arglist-cont-nonempty."
+  (save-excursion
+    (when (c-lineup-argcont-1 langelem)	; Check we've got a continued argument...
+      ;; ... but ignore the position found.
+      (goto-char (c-langelem-2nd-pos c-syntactic-element))
+      (forward-char)
+      (c-forward-syntactic-ws)
+      (vector (+ (current-column) c-basic-offset)))))
 
 (defun c-lineup-arglist-intro-after-paren (_langelem)
   "Line up a line to just after the open paren of the surrounding paren


-- 
Alan Mackenzie (Nuremberg, Germany).





  parent reply	other threads:[~2022-03-13 13:43 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-04  5:50 bug#21409: 24.5; Wrong syntactic information for two line statement in an arglist Gulshan Singh
2020-12-03 11:07 ` Lars Ingebrigtsen
2022-03-12  1:52   ` Gulshan Singh
2022-03-12 11:32     ` Alan Mackenzie
     [not found]     ` <YiyE4jK9zIVMK/SX@ACM>
2022-03-13 13:43       ` Alan Mackenzie [this message]
2022-04-09 21:43         ` Gulshan Singh
2022-04-23 14:23           ` Alan Mackenzie
2022-04-23 20:10           ` Alan Mackenzie

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

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Yi3078jTItyPRzNt@ACM \
    --to=acm@muc.de \
    --cc=21409@debbugs.gnu.org \
    --cc=gsingh2011@gmail.com \
    --cc=larsi@gnus.org \
    /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 public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).