aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorAlan Mackenzie2020-03-08 16:21:15 +0000
committerAlan Mackenzie2020-03-08 16:21:15 +0000
commit35a13fca32c3371ca25d87f7447b4bd4f65de710 (patch)
treea6d40a7e845b45f43421fb8378eaaf5281fe86f9 /lisp
parent66bc47d12aba72ff738a9f5575e0b93eefc641ba (diff)
downloademacs-35a13fca32c3371ca25d87f7447b4bd4f65de710.tar.gz
emacs-35a13fca32c3371ca25d87f7447b4bd4f65de710.zip
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.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/progmodes/cc-cmds.el93
-rw-r--r--lisp/progmodes/cc-langs.el9
-rw-r--r--lisp/progmodes/cc-mode.el61
-rw-r--r--lisp/progmodes/cc-vars.el9
4 files changed, 135 insertions, 37 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index a60812230b8..1b557c41a5d 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -48,6 +48,7 @@
48(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge 48(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge
49 ; which looks at this. 49 ; which looks at this.
50(cc-bytecomp-defun electric-pair-post-self-insert-function) 50(cc-bytecomp-defun electric-pair-post-self-insert-function)
51(cc-bytecomp-defvar c-indent-to-body-directives)
51 52
52;; Indentation / Display syntax functions 53;; Indentation / Display syntax functions
53(defvar c-fix-backslashes t) 54(defvar c-fix-backslashes t)
@@ -1441,6 +1442,98 @@ keyword on the line, the keyword is not inserted inside a literal, and
1441 (indent-according-to-mode) 1442 (indent-according-to-mode)
1442 (delete-char -2))))) 1443 (delete-char -2)))))
1443 1444
1445(defun c-align-cpp-indent-to-body ()
1446 "Align a \"#pragma\" line under the previous line.
1447This function is intented for use as a member of `c-special-indent-hook'."
1448 (when (assq 'cpp-macro c-syntactic-context)
1449 (when
1450 (save-excursion
1451 (save-match-data
1452 (back-to-indentation)
1453 (and
1454 (looking-at (concat c-opt-cpp-symbol "[ \t]*\\([a-zA-Z0-9_]+\\)"))
1455 (member (match-string-no-properties 1)
1456 c-cpp-indent-to-body-directives))))
1457 (c-indent-line (delete '(cpp-macro) c-syntactic-context)))))
1458
1459(defvar c-cpp-indent-to-body-flag nil)
1460;; Non-nil when CPP directives such as "#pragma" should be indented to under
1461;; the preceding statement.
1462(make-variable-buffer-local 'c-cpp-indent-to-body-flag)
1463
1464(defun c-electric-pragma ()
1465 "Reindent the current line if appropriate.
1466
1467This function is used to reindent a preprocessor line when the
1468symbol for the directive, typically \"pragma\", triggers this
1469function as a hook function of an abbreviation.
1470
1471The \"#\" of the preprocessor construct is aligned under the
1472first anchor point of the line's syntactic context.
1473
1474The line is reindented if the construct is not in a string or
1475comment, there is exactly one \"#\" contained in optional
1476whitespace before it on the current line, and `c-electric-flag'
1477and `c-syntactic-indentation' are both non-nil."
1478 (save-excursion
1479 (save-match-data
1480 (when
1481 (and
1482 c-cpp-indent-to-body-flag
1483 c-electric-flag
1484 c-syntactic-indentation
1485 last-abbrev-location
1486 c-opt-cpp-symbol ; "#" or nil.
1487 (progn (back-to-indentation)
1488 (looking-at (concat c-opt-cpp-symbol "[ \t]*")))
1489 (>= (match-end 0) last-abbrev-location)
1490 (not (c-literal-limits)))
1491 (c-indent-line (delete '(cpp-macro) (c-guess-basic-syntax)))))))
1492
1493(defun c-add-indent-to-body-to-abbrev-table (d)
1494 ;; Create an abbreviation table entry for the directive D, and add it to the
1495 ;; current abbreviation table. Existing abbreviation (e.g. for "else") do
1496 ;; not get overwritten.
1497 (when (and c-buffer-is-cc-mode
1498 local-abbrev-table
1499 (not (abbrev-symbol d local-abbrev-table)))
1500 (condition-case nil
1501 (define-abbrev local-abbrev-table d d 'c-electric-pragma 0 t)
1502 (wrong-number-of-arguments
1503 (define-abbrev local-abbrev-table d d 'c-electric-pragma)))))
1504
1505(defun c-clear-stale-indent-to-body-abbrevs ()
1506 ;; Fill in this comment. FIXME!!!
1507 (when (fboundp 'abbrev-get)
1508 (mapatoms (lambda (a)
1509 (when (and (abbrev-get a ':system) ; Preserve a user's abbrev!
1510 (not (member (symbol-name a) c-std-abbrev-keywords))
1511 (not (member (symbol-name a)
1512 c-cpp-indent-to-body-directives)))
1513 (unintern a local-abbrev-table)))
1514 local-abbrev-table)))
1515
1516(defun c-toggle-cpp-indent-to-body (&optional arg)
1517 "Toggle the C preprocessor indent-to-body feature.
1518When enabled, preprocessor directives which are words in
1519`c-indent-to-body-directives' are indented as if they were statements.
1520
1521Optional numeric ARG, if supplied, turns on the feature when positive,
1522turns it off when negative, and just toggles it when zero or
1523left out."
1524 (interactive "P")
1525 (setq c-cpp-indent-to-body-flag
1526 (c-calculate-state arg c-cpp-indent-to-body-flag))
1527 (if c-cpp-indent-to-body-flag
1528 (progn
1529 (c-clear-stale-indent-to-body-abbrevs)
1530 (mapc 'c-add-indent-to-body-to-abbrev-table
1531 c-cpp-indent-to-body-directives)
1532 (add-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body nil t))
1533 (remove-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body t))
1534 (message "c-cpp-indent-to-body %sabled"
1535 (if c-cpp-indent-to-body-flag "en" "dis")))
1536
1444 1537
1445 1538
1446(declare-function subword-forward "subword" (&optional arg)) 1539(declare-function subword-forward "subword" (&optional arg))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index e7e7cfd4b09..1e72352f719 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3030,7 +3030,14 @@ Note that Java specific rules are currently applied to tell this from
3030 ;; can start a declaration.) 3030 ;; can start a declaration.)
3031 "entity" "process" "service" "session" "storage")) 3031 "entity" "process" "service" "session" "storage"))
3032 3032
3033 3033(c-lang-defconst c-std-abbrev-keywords
3034 "List of keywords which may need to cause electric indentation."
3035 t '("else" "while")
3036 c++ (append (c-lang-const c-std-abbrev-keywords) '("catch"))
3037 java (append (c-lang-const c-std-abbrev-keywords) '("catch" "finally"))
3038 idl nil)
3039(c-lang-defvar c-std-abbrev-keywords (c-lang-const c-std-abbrev-keywords))
3040
3034;;; Constants built from keywords. 3041;;; Constants built from keywords.
3035 3042
3036;; Note: No `*-kwds' language constants may be defined below this point. 3043;; Note: No `*-kwds' language constants may be defined below this point.
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index a39c50e4138..f92d3efdeb7 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -278,6 +278,29 @@ control). See \"cc-mode.el\" for more info."
278 (setq defs (cdr defs))))) 278 (setq defs (cdr defs)))))
279(put 'c-define-abbrev-table 'lisp-indent-function 1) 279(put 'c-define-abbrev-table 'lisp-indent-function 1)
280 280
281(defun c-populate-abbrev-table ()
282 ;; Insert the standard keywords which may need electric indentation into the
283 ;; current mode's abbreviation table.
284 (let ((table (intern (concat (symbol-name major-mode) "-abbrev-table")))
285 (defs c-std-abbrev-keywords)
286 )
287 (unless (and (boundp table)
288 (abbrev-table-p (symbol-value table)))
289 (define-abbrev-table table nil))
290 (setq local-abbrev-table (symbol-value table))
291 (while defs
292 (unless (intern-soft (car defs) local-abbrev-table) ; Don't overwrite the
293 ; abbrev's use count.
294 (condition-case nil
295 (define-abbrev (symbol-value table)
296 (car defs) (car defs)
297 'c-electric-continued-statement 0 t)
298 (wrong-number-of-arguments
299 (define-abbrev (symbol-value table)
300 (car defs) (car defs)
301 'c-electric-continued-statement 0))))
302 (setq defs (cdr defs)))))
303
281(defun c-bind-special-erase-keys () 304(defun c-bind-special-erase-keys ()
282 ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace> 305 ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace>
283 ;; to the proper keys depending on `normal-erase-is-backspace'. 306 ;; to the proper keys depending on `normal-erase-is-backspace'.
@@ -550,6 +573,8 @@ that requires a literal mode spec at compile time."
550 573
551 (setq c-buffer-is-cc-mode mode) 574 (setq c-buffer-is-cc-mode mode)
552 575
576 (c-populate-abbrev-table)
577
553 ;; these variables should always be buffer local; they do not affect 578 ;; these variables should always be buffer local; they do not affect
554 ;; indentation style. 579 ;; indentation style.
555 (make-local-variable 'comment-start) 580 (make-local-variable 'comment-start)
@@ -2444,11 +2469,6 @@ opening \" and the next unescaped end of line."
2444 (funcall (c-lang-const c-make-mode-syntax-table c)) 2469 (funcall (c-lang-const c-make-mode-syntax-table c))
2445 "Syntax table used in c-mode buffers.") 2470 "Syntax table used in c-mode buffers.")
2446 2471
2447(c-define-abbrev-table 'c-mode-abbrev-table
2448 '(("else" "else" c-electric-continued-statement 0)
2449 ("while" "while" c-electric-continued-statement 0))
2450 "Abbreviation table used in c-mode buffers.")
2451
2452(defvar c-mode-map 2472(defvar c-mode-map
2453 (let ((map (c-make-inherited-keymap))) 2473 (let ((map (c-make-inherited-keymap)))
2454 map) 2474 map)
@@ -2560,12 +2580,6 @@ the code is C or C++ and based on that chooses whether to enable
2560 (funcall (c-lang-const c-make-mode-syntax-table c++)) 2580 (funcall (c-lang-const c-make-mode-syntax-table c++))
2561 "Syntax table used in c++-mode buffers.") 2581 "Syntax table used in c++-mode buffers.")
2562 2582
2563(c-define-abbrev-table 'c++-mode-abbrev-table
2564 '(("else" "else" c-electric-continued-statement 0)
2565 ("while" "while" c-electric-continued-statement 0)
2566 ("catch" "catch" c-electric-continued-statement 0))
2567 "Abbreviation table used in c++-mode buffers.")
2568
2569(defvar c++-mode-map 2583(defvar c++-mode-map
2570 (let ((map (c-make-inherited-keymap))) 2584 (let ((map (c-make-inherited-keymap)))
2571 map) 2585 map)
@@ -2614,11 +2628,6 @@ Key bindings:
2614 (funcall (c-lang-const c-make-mode-syntax-table objc)) 2628 (funcall (c-lang-const c-make-mode-syntax-table objc))
2615 "Syntax table used in objc-mode buffers.") 2629 "Syntax table used in objc-mode buffers.")
2616 2630
2617(c-define-abbrev-table 'objc-mode-abbrev-table
2618 '(("else" "else" c-electric-continued-statement 0)
2619 ("while" "while" c-electric-continued-statement 0))
2620 "Abbreviation table used in objc-mode buffers.")
2621
2622(defvar objc-mode-map 2631(defvar objc-mode-map
2623 (let ((map (c-make-inherited-keymap))) 2632 (let ((map (c-make-inherited-keymap)))
2624 map) 2633 map)
@@ -2665,13 +2674,6 @@ Key bindings:
2665 (funcall (c-lang-const c-make-mode-syntax-table java)) 2674 (funcall (c-lang-const c-make-mode-syntax-table java))
2666 "Syntax table used in java-mode buffers.") 2675 "Syntax table used in java-mode buffers.")
2667 2676
2668(c-define-abbrev-table 'java-mode-abbrev-table
2669 '(("else" "else" c-electric-continued-statement 0)
2670 ("while" "while" c-electric-continued-statement 0)
2671 ("catch" "catch" c-electric-continued-statement 0)
2672 ("finally" "finally" c-electric-continued-statement 0))
2673 "Abbreviation table used in java-mode buffers.")
2674
2675(defvar java-mode-map 2677(defvar java-mode-map
2676 (let ((map (c-make-inherited-keymap))) 2678 (let ((map (c-make-inherited-keymap)))
2677 map) 2679 map)
@@ -2722,9 +2724,6 @@ Key bindings:
2722 (funcall (c-lang-const c-make-mode-syntax-table idl)) 2724 (funcall (c-lang-const c-make-mode-syntax-table idl))
2723 "Syntax table used in idl-mode buffers.") 2725 "Syntax table used in idl-mode buffers.")
2724 2726
2725(c-define-abbrev-table 'idl-mode-abbrev-table nil
2726 "Abbreviation table used in idl-mode buffers.")
2727
2728(defvar idl-mode-map 2727(defvar idl-mode-map
2729 (let ((map (c-make-inherited-keymap))) 2728 (let ((map (c-make-inherited-keymap)))
2730 map) 2729 map)
@@ -2767,11 +2766,6 @@ Key bindings:
2767 (funcall (c-lang-const c-make-mode-syntax-table pike)) 2766 (funcall (c-lang-const c-make-mode-syntax-table pike))
2768 "Syntax table used in pike-mode buffers.") 2767 "Syntax table used in pike-mode buffers.")
2769 2768
2770(c-define-abbrev-table 'pike-mode-abbrev-table
2771 '(("else" "else" c-electric-continued-statement 0)
2772 ("while" "while" c-electric-continued-statement 0))
2773 "Abbreviation table used in pike-mode buffers.")
2774
2775(defvar pike-mode-map 2769(defvar pike-mode-map
2776 (let ((map (c-make-inherited-keymap))) 2770 (let ((map (c-make-inherited-keymap)))
2777 map) 2771 map)
@@ -2819,11 +2813,6 @@ Key bindings:
2819;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) 2813;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode))
2820;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) 2814;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode))
2821 2815
2822(c-define-abbrev-table 'awk-mode-abbrev-table
2823 '(("else" "else" c-electric-continued-statement 0)
2824 ("while" "while" c-electric-continued-statement 0))
2825 "Abbreviation table used in awk-mode buffers.")
2826
2827(defvar awk-mode-map 2816(defvar awk-mode-map
2828 (let ((map (c-make-inherited-keymap))) 2817 (let ((map (c-make-inherited-keymap)))
2829 map) 2818 map)
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 556ff6059f1..3995b211854 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1649,6 +1649,15 @@ white space either before or after the operator, but not both."
1649 :type 'boolean 1649 :type 'boolean
1650 :group 'c) 1650 :group 'c)
1651 1651
1652(defcustom c-cpp-indent-to-body-directives '("pragma")
1653 "Preprocessor directives which will be indented as statements.
1654
1655A list of Preprocessor directives which when reindented, or newly
1656typed in, will cause the \"#\" introducing the directive to be
1657indented as a statement."
1658 :type '(repeat string)
1659 :group 'c)
1660
1652;; Initialize the next two to a regexp which never matches. 1661;; Initialize the next two to a regexp which never matches.
1653(defvar c-noise-macro-with-parens-name-re regexp-unmatchable) 1662(defvar c-noise-macro-with-parens-name-re regexp-unmatchable)
1654(make-variable-buffer-local 'c-noise-macro-with-parens-name-re) 1663(make-variable-buffer-local 'c-noise-macro-with-parens-name-re)