unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* c-mode pragma and preproc
       [not found] <20191219140738.q5zdmily5ubwnmg3.ref@Ergus>
@ 2019-12-19 14:07 ` Ergus
  2020-01-11 11:44   ` Alan Mackenzie
  0 siblings, 1 reply; 8+ messages in thread
From: Ergus @ 2019-12-19 14:07 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

Hi Alan:

Recently I have been noticing that many "modern" programming models
(Open-MP, OmpSs, OpenACC, programming for Intel Xeon Phi) use
extensively the #pragma sentence.

But in general, while the pre-processor sentences are usually in column
zero ([0]), the #pragma, on the other hand, are preferred to be aligned
with text (0). They are more readable that way.

Is it possible to add a syntactic symbol to distinguish pragmas from
other preprocessor symbols? (actually pragmas are not pre-processor
sentences in general)

I think that the rest of the rules will not change but probably we need
analogs for: cpp-macro and cpp-macro-cont.

In general (AFAIK) the pragmas do not create regions inside like a
define... so we don't need that either.

Thanks in advance,
Ergus



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

* Re: c-mode pragma and preproc
  2019-12-19 14:07 ` c-mode pragma and preproc Ergus
@ 2020-01-11 11:44   ` Alan Mackenzie
  2020-01-14 14:01     ` Ergus
  0 siblings, 1 reply; 8+ messages in thread
From: Alan Mackenzie @ 2020-01-11 11:44 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

Hello, Ergus.

Happy New Year!

On Thu, Dec 19, 2019 at 15:07:38 +0100, Ergus wrote:
> Hi Alan:

> Recently I have been noticing that many "modern" programming models
> (Open-MP, OmpSs, OpenACC, programming for Intel Xeon Phi) use
> extensively the #pragma sentence.

> But in general, while the pre-processor sentences are usually in column
> zero ([0]), the #pragma, on the other hand, are preferred to be aligned
> with text (0). They are more readable that way.

OK, here's a few thoughts on this.

Just how unusual is this?  I mean, is this indentation only for #pragma,
or are there other directives which might want to be indented thus?

> Is it possible to add a syntactic symbol to distinguish pragmas from
> other preprocessor symbols? (actually pragmas are not pre-processor
> sentences in general)

I don't think the syntactic symbol is the way to go.  It seems to be too
heavy a mechanism for a relatively minor requirement.

The engine part of a solution seems straightforward: we write a function
to be placed on the hook c-special-indent-hook that will run as the last
thing in indentation.  This function will detect #pragma (with or
without spaces) and reindent it.  Also it will use the abbrev mechanism
used by e.g. "else" to get electric indentation after typing a space
after pragma.  This bit is not difficult, and I've got some preliminary
working code.

But what is the interface with the user to look like?  This indentation
clearly has to be optional - but another "minor mode" (like
c-electric-flag, toggled by C-c C-l) doesn't feel right.  Maybe a
function called something like c-toggle-indent-cpp-to-body would be
best.  But do we want a list of directives which get this indentation,
or is it just for #pragma?

> I think that the rest of the rules will not change but probably we need
> analogs for: cpp-macro and cpp-macro-cont.

There may be a need to indent all lines of a multiline #pragma as
cpp-macro-cont.  Normally, multiline macros (usually #define) just get
indented like ordinary code.  Maybe this is a bit more complicated.  :-(

> In general (AFAIK) the pragmas do not create regions inside like a
> define... so we don't need that either.

Yes.  We need to exclude it, though.

> Thanks in advance,
> Ergus

-- 
Alan Mackenzie (Nuremberg, Germany).



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

* Re: c-mode pragma and preproc
  2020-01-11 11:44   ` Alan Mackenzie
@ 2020-01-14 14:01     ` Ergus
  2020-01-19 17:26       ` Alan Mackenzie
  0 siblings, 1 reply; 8+ messages in thread
From: Ergus @ 2020-01-14 14:01 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

On Sat, Jan 11, 2020 at 11:44:02AM +0000, Alan Mackenzie wrote:
Hi Alan:

>Hello, Ergus.
>
>Happy New Year!
>
Same for you!!

>On Thu, Dec 19, 2019 at 15:07:38 +0100, Ergus wrote:
>> Hi Alan:
>
>> Recently I have been noticing that many "modern" programming models
>> (Open-MP, OmpSs, OpenACC, programming for Intel Xeon Phi) use
>> extensively the #pragma sentence.
>
>> But in general, while the pre-processor sentences are usually in column
>> zero ([0]), the #pragma, on the other hand, are preferred to be aligned
>> with text (0). They are more readable that way.
>
>OK, here's a few thoughts on this.
>
>Just how unusual is this?  I mean, is this indentation only for #pragma,
>or are there other directives which might want to be indented thus?
>
AFAIK only #pragma.

>> Is it possible to add a syntactic symbol to distinguish pragmas from
>> other preprocessor symbols? (actually pragmas are not pre-processor
>> sentences in general)
>
>I don't think the syntactic symbol is the way to go.  It seems to be too
>heavy a mechanism for a relatively minor requirement.
>
>The engine part of a solution seems straightforward: we write a function
>to be placed on the hook c-special-indent-hook that will run as the last
>thing in indentation.  This function will detect #pragma (with or
>without spaces) and reindent it.  Also it will use the abbrev mechanism
>used by e.g. "else" to get electric indentation after typing a space
>after pragma.  This bit is not difficult, and I've got some preliminary
>working code.
>
>But what is the interface with the user to look like?  This indentation
>clearly has to be optional - but another "minor mode" (like
>c-electric-flag, toggled by C-c C-l) doesn't feel right.  Maybe a
>function called something like c-toggle-indent-cpp-to-body would be
>best.  But do we want a list of directives which get this indentation,
>or is it just for #pragma?
>
I am in favour of the simplest possible solution. I think that syntactic
symbol is actually the simplest one for the final user but you know
c-mode better than me.

In general as I said before it is only #pragma and I don't understand
why it needs to be different from any other syntactic symbol.

>> I think that the rest of the rules will not change but probably we need
>> analogs for: cpp-macro and cpp-macro-cont.
>
>There may be a need to indent all lines of a multiline #pragma as
>cpp-macro-cont.  Normally, multiline macros (usually #define) just get
>indented like ordinary code.  Maybe this is a bit more complicated.  :-(
>
We can make it as complex as we want. But in general the rest is just
the same as with normal macros. Because as the different models will
have different keywords we don't need more complexity to be general
enough.

For example the most general example so far is:

#pragma omp parallel shared(salaries1, salaries2)
{
     #pragma omp for reduction(+: salaries1)
     for (int employee = 0; employee < 25000; employee++)
     {
         salaries1 += fetchTheSalary(employee, Co::Company1);
     }

     #pragma omp single
     {
         std::cout << "Salaries1: " << salaries1 << std::endl;
     }

     #pragma omp for reduction(+: salaries1)
     for (int employee = 0; employee < 25000; employee++)
     {
         salaries2 += fetchTheSalary(employee, Co::Company2);
     }

     #pragma omp barrier
}

>> In general (AFAIK) the pragmas do not create regions inside like a
>> define... so we don't need that either.
>
>Yes.  We need to exclude it, though.
>
>> Thanks in advance,
>> Ergus
>
>-- 
>Alan Mackenzie (Nuremberg, Germany).
>
Best,
Ergus



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

* Re: c-mode pragma and preproc
  2020-01-14 14:01     ` Ergus
@ 2020-01-19 17:26       ` Alan Mackenzie
  2020-01-20  2:15         ` Ergus via Emacs development discussions.
  0 siblings, 1 reply; 8+ messages in thread
From: Alan Mackenzie @ 2020-01-19 17:26 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

Hello again, Ergus.

On Tue, Jan 14, 2020 at 15:01:10 +0100, Ergus wrote:
> On Sat, Jan 11, 2020 at 11:44:02AM +0000, Alan Mackenzie wrote:
> Hi Alan:
> >On Thu, Dec 19, 2019 at 15:07:38 +0100, Ergus wrote:
> >> Hi Alan:

> >> Recently I have been noticing that many "modern" programming models
> >> (Open-MP, OmpSs, OpenACC, programming for Intel Xeon Phi) use
> >> extensively the #pragma sentence.

> >> But in general, while the pre-processor sentences are usually in column
> >> zero ([0]), the #pragma, on the other hand, are preferred to be aligned
> >> with text (0). They are more readable that way.

OK, I have an experimental implementation of M-x
c-toggle-cpp-indent-to-body (see patch below).  This can be customised by
changing c-cpp-indent-to-body-directives, the list of directives which
should be indented as statements.  It's default value is ("pragma").
(Yes, I know you said that it would only be needed for "pragma", but it
seemed a bit restrictive so to restrict it.).

The indentation takes place either on typing <tab> (or any other action
which causes indentation) or on typing a space after "# pragma".

[ .... ]

> For example the most general example so far is:

> #pragma omp parallel shared(salaries1, salaries2)
> {
>      #pragma omp for reduction(+: salaries1)
>      for (int employee = 0; employee < 25000; employee++)
>      {
>          salaries1 += fetchTheSalary(employee, Co::Company1);
>      }

>      #pragma omp single
>      {
>          std::cout << "Salaries1: " << salaries1 << std::endl;
>      }

>      #pragma omp for reduction(+: salaries1)
>      for (int employee = 0; employee < 25000; employee++)
>      {
>          salaries2 += fetchTheSalary(employee, Co::Company2);
>      }

>      #pragma omp barrier
> }

Thanks.  This example was helpful.

Just one thing - I haven't yet amended the CC Mode manual.

Would you please try the patch out, and let me know how well it satisfies
your needs.  The patch should apply cleanly to the master branch.

Thanks!

[ .... ]




diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 1071191775..223266177a 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)
 \f
 ;; Indentation / Display syntax functions
 (defvar c-fix-backslashes t)
@@ -1441,6 +1442,78 @@ 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)
+    (save-excursion
+      (save-match-data
+	(back-to-indentation)
+	(when (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)))
+
 \f
 
 (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)


> Best,
> Ergus

-- 
Alan Mackenzie (Nuremberg, Germany).



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

* Re: c-mode pragma and preproc
  2020-01-19 17:26       ` Alan Mackenzie
@ 2020-01-20  2:15         ` Ergus via Emacs development discussions.
  2020-01-20 21:27           ` Alan Mackenzie
  0 siblings, 1 reply; 8+ messages in thread
From: Ergus via Emacs development discussions. @ 2020-01-20  2:15 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

Hi Alan:

I just tried the patch and it seems to work as expected.

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?

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. Why not just add an
extra syntactic symbol for pragmas? Isn't it more consistent that way?
Otherwise the user will get false information from C-c C-o and looses
somehow a bit of flexibility.
Maybe we just need a variable that when not specified indent pragmas as
macros else indent pragmas as it specifies...?

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++.

In any case the only real "issue" in my opinion is 1). But so far it
works pretty fine.

Very thanks,
Ergus.

On Sun, Jan 19, 2020 at 05:26:47PM +0000, Alan Mackenzie wrote:
>Hello again, Ergus.
>
>On Tue, Jan 14, 2020 at 15:01:10 +0100, Ergus wrote:
>> On Sat, Jan 11, 2020 at 11:44:02AM +0000, Alan Mackenzie wrote:
>> Hi Alan:
>> >On Thu, Dec 19, 2019 at 15:07:38 +0100, Ergus wrote:
>> >> Hi Alan:
>
>> >> Recently I have been noticing that many "modern" programming models
>> >> (Open-MP, OmpSs, OpenACC, programming for Intel Xeon Phi) use
>> >> extensively the #pragma sentence.
>
>> >> But in general, while the pre-processor sentences are usually in column
>> >> zero ([0]), the #pragma, on the other hand, are preferred to be aligned
>> >> with text (0). They are more readable that way.
>
>OK, I have an experimental implementation of M-x
>c-toggle-cpp-indent-to-body (see patch below).  This can be customised by
>changing c-cpp-indent-to-body-directives, the list of directives which
>should be indented as statements.  It's default value is ("pragma").
>(Yes, I know you said that it would only be needed for "pragma", but it
>seemed a bit restrictive so to restrict it.).
>
>The indentation takes place either on typing <tab> (or any other action
>which causes indentation) or on typing a space after "# pragma".
>
>[ .... ]
>
>> For example the most general example so far is:
>
>> #pragma omp parallel shared(salaries1, salaries2)
>> {
>>      #pragma omp for reduction(+: salaries1)
>>      for (int employee = 0; employee < 25000; employee++)
>>      {
>>          salaries1 += fetchTheSalary(employee, Co::Company1);
>>      }
>
>>      #pragma omp single
>>      {
>>          std::cout << "Salaries1: " << salaries1 << std::endl;
>>      }
>
>>      #pragma omp for reduction(+: salaries1)
>>      for (int employee = 0; employee < 25000; employee++)
>>      {
>>          salaries2 += fetchTheSalary(employee, Co::Company2);
>>      }
>
>>      #pragma omp barrier
>> }
>
>Thanks.  This example was helpful.
>
>Just one thing - I haven't yet amended the CC Mode manual.
>
>Would you please try the patch out, and let me know how well it satisfies
>your needs.  The patch should apply cleanly to the master branch.
>
>Thanks!
>
>[ .... ]
>
>
>
>
>diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
>index 1071191775..223266177a 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)
> \f
> ;; Indentation / Display syntax functions
> (defvar c-fix-backslashes t)
>@@ -1441,6 +1442,78 @@ 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)
>+    (save-excursion
>+      (save-match-data
>+	(back-to-indentation)
>+	(when (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)))
>+
> \f
>
> (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)
>
>
>> Best,
>> Ergus
>
>-- 
>Alan Mackenzie (Nuremberg, Germany).
>



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

* Re: c-mode pragma and preproc
  2020-01-20  2:15         ` Ergus via Emacs development discussions.
@ 2020-01-20 21:27           ` Alan Mackenzie
  2020-02-11 20:00             ` Alan Mackenzie
  0 siblings, 1 reply; 8+ messages in thread
From: Alan Mackenzie @ 2020-01-20 21:27 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

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)
 \f
 ;; 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)))
+
 \f
 
 (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).



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

* Re: c-mode pragma and preproc
  2020-01-20 21:27           ` Alan Mackenzie
@ 2020-02-11 20:00             ` Alan Mackenzie
  2020-02-12 10:19               ` Ergus via Emacs development discussions.
  0 siblings, 1 reply; 8+ messages in thread
From: Alan Mackenzie @ 2020-02-11 20:00 UTC (permalink / raw)
  To: Ergus; +Cc: emacs-devel

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)
 \f
>  ;; 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)))
> +
 \f
 
>  (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).



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

* Re: c-mode pragma and preproc
  2020-02-11 20:00             ` Alan Mackenzie
@ 2020-02-12 10:19               ` Ergus via Emacs development discussions.
  0 siblings, 0 replies; 8+ messages in thread
From: Ergus via Emacs development discussions. @ 2020-02-12 10:19 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

Hi Alan:

Sorry for not commenting before the feedback.

Yes it works fine for me. Except for the details I mentioned before
about C-c C-o. But I understand the limitations we have there. So in my
opinion you can commit it.

Very thanks for this,
Ergus

On Tue, Feb 11, 2020 at 08:00:18PM +0000, Alan Mackenzie wrote:
>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)
> \f
>>  ;; 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)))
>> +
> \f
>
>>  (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).



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

end of thread, other threads:[~2020-02-12 10:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20191219140738.q5zdmily5ubwnmg3.ref@Ergus>
2019-12-19 14:07 ` c-mode pragma and preproc Ergus
2020-01-11 11:44   ` Alan Mackenzie
2020-01-14 14:01     ` Ergus
2020-01-19 17:26       ` Alan Mackenzie
2020-01-20  2:15         ` Ergus via Emacs development discussions.
2020-01-20 21:27           ` Alan Mackenzie
2020-02-11 20:00             ` Alan Mackenzie
2020-02-12 10:19               ` Ergus via Emacs development discussions.

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