From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: c-mode pragma and preproc Date: Tue, 11 Feb 2020 20:00:18 +0000 Message-ID: <20200211200018.GA5902@ACM> References: <20191219140738.q5zdmily5ubwnmg3.ref@Ergus> <20191219140738.q5zdmily5ubwnmg3@Ergus> <20200111114402.GA6005@ACM> <20200114140110.hrfqmrfkffwsknse@Ergus> <20200119172647.GB9172@ACM> <20200120021538.wxtxv3vbsorksqdg@Ergus> <20200120212702.GB4348@ACM> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="125610"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mutt/1.10.1 (2018-07-13) Cc: emacs-devel@gnu.org To: Ergus Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Tue Feb 11 21:01:23 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1j1bil-000Wb8-HP for ged-emacs-devel@m.gmane-mx.org; Tue, 11 Feb 2020 21:01:23 +0100 Original-Received: from localhost ([::1]:56660 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j1bik-00023O-H4 for ged-emacs-devel@m.gmane-mx.org; Tue, 11 Feb 2020 15:01:22 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:35744) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j1bht-0001Sr-5X for emacs-devel@gnu.org; Tue, 11 Feb 2020 15:00:30 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j1bhr-0007gH-8R for emacs-devel@gnu.org; Tue, 11 Feb 2020 15:00:28 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:45535 helo=mail.muc.de) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1j1bho-0007Xo-Sv for emacs-devel@gnu.org; Tue, 11 Feb 2020 15:00:27 -0500 Original-Received: (qmail 40790 invoked by uid 3782); 11 Feb 2020 20:00:22 -0000 Original-Received: from acm.muc.de (p4FE15B78.dip0.t-ipconnect.de [79.225.91.120]) by colin.muc.de (tmda-ofmipd) with ESMTP; Tue, 11 Feb 2020 21:00:21 +0100 Original-Received: (qmail 6632 invoked by uid 1000); 11 Feb 2020 20:00:18 -0000 Content-Disposition: inline In-Reply-To: <20200120212702.GB4348@ACM> X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 193.149.48.1 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:244913 Archived-At: Hello again, Ergus. Just a quick ping! I've now written the requisite documentation for the CC Mode manual. Are you otherwise happy (or, at least, happy enough) with the state of the code for me to commit it? -- Alan Mackenzie (Nuremberg, Germany). On Mon, Jan 20, 2020 at 21:27:02 +0000, Alan Mackenzie wrote: > On Mon, Jan 20, 2020 at 03:15:38 +0100, Ergus via Emacs development discussions. wrote: > > Hi Alan: > > I just tried the patch and it seems to work as expected. > Thanks! > > I just have 3 observations/suggestions/questions: > > 1) When I stay in column 0 like > > |#pragma bla bla > > and I press tab (to indent the line's) I get: > > | #pragma bla bla > > instead of: > > |#pragma bla bla > > as it happens with other lines (where | is the cursor position). Is this > > intended? > Whoops! That sort of thing is why I normally ask bug reporters to check > the patch before I commit it. It's difficult to see when one is fixing a > bug, but stands out like a sore thumb to somebody trying it out. > What happened was I called c-indent-line from inside a save-excursion. > c-indent-line placed point correctly, but emerging from the > save-excursion put it back to column 0. To fix this, either substitute > this new version of c-align-cpp-indent-to-body for the old one, or > reapply the patch below from scratch (whichever you prefer): > (defun c-align-cpp-indent-to-body () > "Align a \"#pragma\" line under the previous line. > This function is intented for use as a member of `c-special-indent-hook'." > (when (assq 'cpp-macro c-syntactic-context) > (when > (save-excursion > (save-match-data > (back-to-indentation) > (looking-at "#[ \t]*pragma\\([^[:alnum:]_$]\\|$\\)"))) > (c-indent-line (delete '(cpp-macro) c-syntactic-context))))) > . > > 2) This new implementation breaks the "normal" way to configure the > > indentation in c-mode because C-c C-o still returns cpp-macro (as > > expected) while the indentation is not behaving as specified for > > cpp-macros. So it seems to be confusing for the user and somehow a bit > > inconsistent with the rest of cc-mode indentation. > It does a bit, yes. This is an inevitable downside of using > c-special-indent-hook which counterbalances to some extent the ability to > add lightweight, yet effective, solutions to otherwise awkward > indentation problems. The other standard c-special-indent-hook function > is c-gnu-impose-minimum, which in gnu style ensures that source code > within functions has a minimum indentation. That also suffers from the > inability to use C-c C-o with it. > > Why not just add an extra syntactic symbol for pragmas? Isn't it more > > consistent that way? > There's no "just" about a new syntactic symbol. It would be more work to > back it, more likely to interact with other features, and more likely to > increase the complexity of CC Mode more than needed. Consider that, in > reality, #pragma _is_ a cpp-macro, not something new. > > Otherwise the user will get false information from C-c C-o and looses > > somehow a bit of flexibility. > This is true. > > Maybe we just need a variable that when not specified indent pragmas as > > macros else indent pragmas as it specifies...? > Are you thinking of c-cpp-indent-to-body-flag? ;-) > > 3) Why the new function is called c-toggle-cpp-indent*? pragmas are part > > of C too. Actually in HPC we usually use more C (and Fortran) than C++. > cpp for "C PreProcessor". :-) I don't think there are any instances of > cpp meaning C++ in CC Mode, but I agree it's an unfortunate collision of > abbreviations. :-( > I still haven't amended the CC Mode manual, but I will. > > In any case the only real "issue" in my opinion is 1). But so far it > > works pretty fine. > OK, here's the replacement patch: > diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el > index 1071191775..56e3421ba2 100644 > --- a/lisp/progmodes/cc-cmds.el > +++ b/lisp/progmodes/cc-cmds.el > @@ -48,6 +48,7 @@ > (cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge > ; which looks at this. > (cc-bytecomp-defun electric-pair-post-self-insert-function) > +(cc-bytecomp-defvar c-indent-to-body-directives) > ;; Indentation / Display syntax functions > (defvar c-fix-backslashes t) > @@ -1441,6 +1442,79 @@ c-electric-continued-statement > (indent-according-to-mode) > (delete-char -2))))) > +(defun c-align-cpp-indent-to-body () > + "Align a \"#pragma\" line under the previous line. > +This function is intented for use as a member of `c-special-indent-hook'." > + (when (assq 'cpp-macro c-syntactic-context) > + (when > + (save-excursion > + (save-match-data > + (back-to-indentation) > + (looking-at "#[ \t]*pragma\\([^[:alnum:]_$]\\|$\\)"))) > + (c-indent-line (delete '(cpp-macro) c-syntactic-context))))) > + > +(defvar c-cpp-indent-to-body-flag nil) > +;; Non-nil when CPP directives such as "#pragma" should be indented to under > +;; the preceding statement. > +(make-variable-buffer-local 'c-cpp-indent-to-body-flag) > + > +(defun c-electric-pragma () > + "Reindent the current line if appropriate. > + > +This function is used to reindent a preprocessor line when the > +symbol for the directive, typically \"pragma\", triggers this > +function as a hook function of an abbreviation. > + > +The \"#\" of the preprocessor construct is aligned under the > +first anchor point of the line's syntactic context. > + > +The line is reindented if the construct is not in a string or > +comment, there is exactly one \"#\" contained in optional > +whitespace before it on the current line, and `c-electric-flag' > +and `c-syntactic-indentation' are both non-nil." > + (save-excursion > + (save-match-data > + (when > + (and > + c-cpp-indent-to-body-flag > + c-electric-flag > + c-syntactic-indentation > + last-abbrev-location > + c-opt-cpp-symbol ; "#" or nil. > + (progn (back-to-indentation) > + (looking-at (concat c-opt-cpp-symbol "[ \t]*"))) > + (>= (match-end 0) last-abbrev-location) > + (not (c-literal-limits))) > + (c-indent-line (delete '(cpp-macro) (c-guess-basic-syntax))))))) > + > +(defun c-add-indent-to-body-to-abbrev-table (d) > + ;; Create an abbreviation table entry for the directive D, and add it to the > + ;; current abbreviation table. Existing abbreviation (e.g. for "else") do > + ;; not get overwritten. > + (when (and c-buffer-is-cc-mode > + local-abbrev-table > + (not (abbrev-symbol d local-abbrev-table))) > + (define-abbrev local-abbrev-table d d 'c-electric-pragma))) > + > +(defun c-toggle-cpp-indent-to-body (&optional arg) > + "Toggle the cpp indent-to-body feature. > +When enabled, when CPP directives which are words in > +`c-indent-to-body-directives', the are indented such that the > +initial \"#\" appears below the previous statement. > + > +Optional numeric ARG, if supplied, turns on the feature when positive, > +turns it off when negative, and just toggles it when zero or > +left out." > + (interactive "P") > + (setq c-cpp-indent-to-body-flag > + (c-calculate-state arg c-cpp-indent-to-body-flag)) > + (if c-cpp-indent-to-body-flag > + (progn > + (mapc 'c-add-indent-to-body-to-abbrev-table > + c-cpp-indent-to-body-directives) > + (add-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body nil t)) > + (remove-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body t))) > + > (declare-function subword-forward "subword" (&optional arg)) > diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el > index 861872486c..0391cdccfd 100644 > --- a/lisp/progmodes/cc-vars.el > +++ b/lisp/progmodes/cc-vars.el > @@ -1649,6 +1649,15 @@ c-asymmetry-fontification-flag > :type 'boolean > :group 'c) > +(defcustom c-cpp-indent-to-body-directives '("pragma") > + "Preprocessor directives which will be indented as statements. > + > +A list of Preprocessor directives which when reindented, or newly > +typed in, will cause the \"#\" introducing the directive to be > +indented as a statement." > + :type '(repeat string) > + :group 'c) > + > ;; Initialize the next two to a regexp which never matches. > (defvar c-noise-macro-with-parens-name-re regexp-unmatchable) > (make-variable-buffer-local 'c-noise-macro-with-parens-name-re) > > Very thanks, > > Ergus. > -- > Alan Mackenzie (Nuremberg, Germany).