* Misc Line-Up::
-Customizing Macros
+Custom Macros
* Macro Backslashes::
* Macros with ;::
* Noise Macros::
+* Indenting Directives::
@end detailmenu
@end menu
@code{cpp-macro-cont}.
@end defopt
+Sometimes you may want to indent particular directives
+(e.g. @code{#pragma}) as though they were statements. To do this, see
+@ref{Indenting Directives}.
+
Because a macro can expand into anything at all, near where one is
invoked @ccmode{} can only indent and fontify code heuristically.
Sometimes it gets it wrong. Usually you should try to design your
* Macro Backslashes::
* Macros with ;::
* Noise Macros::
+* Indenting Directives::
@end menu
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@end defun
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-@node Noise Macros, , Macros with ;, Custom Macros
+@node Noise Macros, Indenting Directives, Macros with ;, Custom Macros
@comment node-name, next, previous, up
@section Noise Macros
@cindex noise macros
after the mode hooks have run.
@end defun
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@node Indenting Directives, , Noise Macros, Custom Macros
+@comment node-name, next, previous, up
+@section Indenting Directives
+@cindex Indenting Directives
+@cindex Indenting #pragma
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Sometimes you may want to indent particular preprocessor directives
+(e.g. @code{#pragma}) as though they were statements. To do this,
+first set up @code{c-cpp-indent-to-body-directives} to include the
+directive name(s), then enable the ``indent to body'' feature with
+@code{c-toggle-cpp-indent-to-body}.
+
+@defopt c-cpp-indent-to-body-directives
+@vindex cpp-indent-to-body-directives (c-)
+This variable is a list of names of CPP directives (not including the
+introducing @samp{#}) which will be indented as though statements.
+Each element is a string, and must be a valid identifier. The default
+value is @code{("pragma")}.
+
+If you add more directives to this variable, or remove directives from
+it, whilst ``indent to body'' is active, you need to re-enable the
+feature by calling @code{c-toggle-cpp-indent-to-body} for these
+changes to take effect@footnote{Note that the removal of directives
+doesn't work satisfactorally on XEmacs or on very old versions of
+Emacs}.
+@end defopt
+
+@defun c-toggle-cpp-indent-to-body
+@findex toggle-cpp-indent-to-body (c-)
+With @kbd{M-x c-toggle-cpp-indent-to-body}, you enable or disable the
+``indent to body'' feature. When called programmatically, it takes an
+optional numerical argument. A positive value will enable the
+feature, a zero or negative value will disable it.
+
+You should set up @code{c-cpp-indent-to-body-directives} before
+calling this function, since the function sets internal state which
+depends on that variable.
+@end defun
+
+
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@node Odds and Ends, Sample Init File, Custom Macros, Top
@comment node-name, next, previous, up
(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)
(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)
+ (and
+ (looking-at (concat c-opt-cpp-symbol "[ \t]*\\([a-zA-Z0-9_]+\\)"))
+ (member (match-string-no-properties 1)
+ c-cpp-indent-to-body-directives))))
+ (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)))
+ (condition-case nil
+ (define-abbrev local-abbrev-table d d 'c-electric-pragma 0 t)
+ (wrong-number-of-arguments
+ (define-abbrev local-abbrev-table d d 'c-electric-pragma)))))
+
+(defun c-clear-stale-indent-to-body-abbrevs ()
+ ;; Fill in this comment. FIXME!!!
+ (when (fboundp 'abbrev-get)
+ (mapatoms (lambda (a)
+ (when (and (abbrev-get a ':system) ; Preserve a user's abbrev!
+ (not (member (symbol-name a) c-std-abbrev-keywords))
+ (not (member (symbol-name a)
+ c-cpp-indent-to-body-directives)))
+ (unintern a local-abbrev-table)))
+ local-abbrev-table)))
+
+(defun c-toggle-cpp-indent-to-body (&optional arg)
+ "Toggle the C preprocessor indent-to-body feature.
+When enabled, preprocessor directives which are words in
+`c-indent-to-body-directives' are indented as if they were statements.
+
+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
+ (c-clear-stale-indent-to-body-abbrevs)
+ (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))
+ (message "c-cpp-indent-to-body %sabled"
+ (if c-cpp-indent-to-body-flag "en" "dis")))
+
\f
(declare-function subword-forward "subword" (&optional arg))
;; can start a declaration.)
"entity" "process" "service" "session" "storage"))
-\f
+(c-lang-defconst c-std-abbrev-keywords
+ "List of keywords which may need to cause electric indentation."
+ t '("else" "while")
+ c++ (append (c-lang-const c-std-abbrev-keywords) '("catch"))
+ java (append (c-lang-const c-std-abbrev-keywords) '("catch" "finally"))
+ idl nil)
+(c-lang-defvar c-std-abbrev-keywords (c-lang-const c-std-abbrev-keywords))
+
;;; Constants built from keywords.
;; Note: No `*-kwds' language constants may be defined below this point.
(setq defs (cdr defs)))))
(put 'c-define-abbrev-table 'lisp-indent-function 1)
+(defun c-populate-abbrev-table ()
+ ;; Insert the standard keywords which may need electric indentation into the
+ ;; current mode's abbreviation table.
+ (let ((table (intern (concat (symbol-name major-mode) "-abbrev-table")))
+ (defs c-std-abbrev-keywords)
+ )
+ (unless (and (boundp table)
+ (abbrev-table-p (symbol-value table)))
+ (define-abbrev-table table nil))
+ (setq local-abbrev-table (symbol-value table))
+ (while defs
+ (unless (intern-soft (car defs) local-abbrev-table) ; Don't overwrite the
+ ; abbrev's use count.
+ (condition-case nil
+ (define-abbrev (symbol-value table)
+ (car defs) (car defs)
+ 'c-electric-continued-statement 0 t)
+ (wrong-number-of-arguments
+ (define-abbrev (symbol-value table)
+ (car defs) (car defs)
+ 'c-electric-continued-statement 0))))
+ (setq defs (cdr defs)))))
+
(defun c-bind-special-erase-keys ()
;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace>
;; to the proper keys depending on `normal-erase-is-backspace'.
(setq c-buffer-is-cc-mode mode)
+ (c-populate-abbrev-table)
+
;; these variables should always be buffer local; they do not affect
;; indentation style.
(make-local-variable 'comment-start)
(funcall (c-lang-const c-make-mode-syntax-table c))
"Syntax table used in c-mode buffers.")
-(c-define-abbrev-table 'c-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0))
- "Abbreviation table used in c-mode buffers.")
-
(defvar c-mode-map
(let ((map (c-make-inherited-keymap)))
map)
(funcall (c-lang-const c-make-mode-syntax-table c++))
"Syntax table used in c++-mode buffers.")
-(c-define-abbrev-table 'c++-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0)
- ("catch" "catch" c-electric-continued-statement 0))
- "Abbreviation table used in c++-mode buffers.")
-
(defvar c++-mode-map
(let ((map (c-make-inherited-keymap)))
map)
(funcall (c-lang-const c-make-mode-syntax-table objc))
"Syntax table used in objc-mode buffers.")
-(c-define-abbrev-table 'objc-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0))
- "Abbreviation table used in objc-mode buffers.")
-
(defvar objc-mode-map
(let ((map (c-make-inherited-keymap)))
map)
(funcall (c-lang-const c-make-mode-syntax-table java))
"Syntax table used in java-mode buffers.")
-(c-define-abbrev-table 'java-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0)
- ("catch" "catch" c-electric-continued-statement 0)
- ("finally" "finally" c-electric-continued-statement 0))
- "Abbreviation table used in java-mode buffers.")
-
(defvar java-mode-map
(let ((map (c-make-inherited-keymap)))
map)
(funcall (c-lang-const c-make-mode-syntax-table idl))
"Syntax table used in idl-mode buffers.")
-(c-define-abbrev-table 'idl-mode-abbrev-table nil
- "Abbreviation table used in idl-mode buffers.")
-
(defvar idl-mode-map
(let ((map (c-make-inherited-keymap)))
map)
(funcall (c-lang-const c-make-mode-syntax-table pike))
"Syntax table used in pike-mode buffers.")
-(c-define-abbrev-table 'pike-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0))
- "Abbreviation table used in pike-mode buffers.")
-
(defvar pike-mode-map
(let ((map (c-make-inherited-keymap)))
map)
;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode))
;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode))
-(c-define-abbrev-table 'awk-mode-abbrev-table
- '(("else" "else" c-electric-continued-statement 0)
- ("while" "while" c-electric-continued-statement 0))
- "Abbreviation table used in awk-mode buffers.")
-
(defvar awk-mode-map
(let ((map (c-make-inherited-keymap)))
map)
: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)