From: Alan Mackenzie <acm@muc.de>
To: Ergus <spacibba@aol.com>
Cc: emacs-devel@gnu.org
Subject: Re: c-mode pragma and preproc
Date: Sun, 19 Jan 2020 17:26:47 +0000 [thread overview]
Message-ID: <20200119172647.GB9172@ACM> (raw)
In-Reply-To: <20200114140110.hrfqmrfkffwsknse@Ergus>
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).
next prev parent reply other threads:[~2020-01-19 17:26 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 [this message]
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.
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=20200119172647.GB9172@ACM \
--to=acm@muc.de \
--cc=emacs-devel@gnu.org \
--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).