mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-08 00:33:13 -08:00
CC Mode: allow specified directives (e.g. pragma) to be indented as statements
* lisp/progmodes/cc-cmds.el (c-align-cpp-indent-to-body) (c-cpp-indent-to-body-flag, c-electric-pragma) (c-add-indent-to-body-to-abbrev-table, c-clear-stale-indent-to-body-abbrevs) (c-toggle-cpp-indent-to-body): New functions and variables. * lisp/progmodes/cc-langs.el (c-std-abbrev-keywords): New lang const/var. * lisp/progmodes/cc-mode.el (c-populate-abbrev-table): New function. (c-basic-common-init): call the c-populate-abbrev-table. (c-mode, c++-mode, objc-mode, java-mode, idl-mode, pike-mode, awk-mode): Remove the setting of MODE-abbrev-table. * lisp/progmodes/cc-vars.el (c-cpp-indent-to-body-directives): New defcustom. * doc/misc/cc-mode.texi (Custom Macros): Introduce and refer to .... (Indenting Directives): New page documenting the new mechanism.
This commit is contained in:
parent
66bc47d12a
commit
35a13fca32
5 changed files with 185 additions and 39 deletions
|
|
@ -350,11 +350,12 @@ Line-Up Functions
|
|||
* Misc Line-Up::
|
||||
|
||||
|
||||
Customizing Macros
|
||||
Custom Macros
|
||||
|
||||
* Macro Backslashes::
|
||||
* Macros with ;::
|
||||
* Noise Macros::
|
||||
* Indenting Directives::
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
|
@ -6949,6 +6950,10 @@ is @code{nil}, all lines inside macro definitions are analyzed as
|
|||
@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
|
||||
|
|
@ -6965,6 +6970,7 @@ Macros}.
|
|||
* Macro Backslashes::
|
||||
* Macros with ;::
|
||||
* Noise Macros::
|
||||
* Indenting Directives::
|
||||
@end menu
|
||||
|
||||
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
|
@ -7074,7 +7080,7 @@ initialization code, after the mode hooks have run.
|
|||
@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
|
||||
|
|
@ -7130,6 +7136,48 @@ has run. This function is called by @ccmode{}'s initialization code,
|
|||
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
|
||||
|
|
|
|||
|
|
@ -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,98 @@ keyword on the line, the keyword is not inserted inside a literal, and
|
|||
(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")))
|
||||
|
||||
|
||||
|
||||
(declare-function subword-forward "subword" (&optional arg))
|
||||
|
|
|
|||
|
|
@ -3030,7 +3030,14 @@ Note that Java specific rules are currently applied to tell this from
|
|||
;; can start a declaration.)
|
||||
"entity" "process" "service" "session" "storage"))
|
||||
|
||||
|
||||
(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.
|
||||
|
|
|
|||
|
|
@ -278,6 +278,29 @@ control). See \"cc-mode.el\" for more info."
|
|||
(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'.
|
||||
|
|
@ -550,6 +573,8 @@ that requires a literal mode spec at compile time."
|
|||
|
||||
(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)
|
||||
|
|
@ -2444,11 +2469,6 @@ opening \" and the next unescaped end of line."
|
|||
(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)
|
||||
|
|
@ -2560,12 +2580,6 @@ the code is C or C++ and based on that chooses whether to enable
|
|||
(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)
|
||||
|
|
@ -2614,11 +2628,6 @@ Key bindings:
|
|||
(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)
|
||||
|
|
@ -2665,13 +2674,6 @@ Key bindings:
|
|||
(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)
|
||||
|
|
@ -2722,9 +2724,6 @@ Key bindings:
|
|||
(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)
|
||||
|
|
@ -2767,11 +2766,6 @@ Key bindings:
|
|||
(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)
|
||||
|
|
@ -2819,11 +2813,6 @@ Key bindings:
|
|||
;;;###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)
|
||||
|
|
|
|||
|
|
@ -1649,6 +1649,15 @@ white space either before or after the operator, but not both."
|
|||
: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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue