unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Ergus via "Emacs development discussions." <emacs-devel@gnu.org>
To: Alan Mackenzie <acm@muc.de>
Cc: emacs-devel@gnu.org
Subject: Re: c-mode pragma and preproc
Date: Mon, 20 Jan 2020 03:15:38 +0100	[thread overview]
Message-ID: <20200120021538.wxtxv3vbsorksqdg@Ergus> (raw)
In-Reply-To: <20200119172647.GB9172@ACM>

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



  reply	other threads:[~2020-01-20  2:15 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [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. [this message]
2020-01-20 21:27           ` Alan Mackenzie
2020-02-11 20:00             ` Alan Mackenzie
2020-02-12 10:19               ` Ergus via Emacs development discussions.

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=20200120021538.wxtxv3vbsorksqdg@Ergus \
    --to=emacs-devel@gnu.org \
    --cc=acm@muc.de \
    --cc=spacibba@aol.com \
    /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).