commit b76385c05076f0adaf7cf89d0ed95dfe5e8570e0 (HEAD, refs/remotes/origin/master) Author: Alan Mackenzie Date: Wed Jun 15 22:06:14 2016 +0000 Speed up CC Mode's font locking by taking some code out of a hot loop. * lisp/progmodes/cc-fonts.el (c-font-lock-declarations): Remove code which tests for bare declarators. (c-font-lock-cut-off-declarators): New function. (c-complex-decl-matchers): insert c-font-lock-cut-off-declarators. diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index f3f369f..65ec5c3 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1447,48 +1447,7 @@ casts and declarations are fontified. Used on level 2 and higher." (c-backward-over-enum-header))))) (c-forward-token-2) nil) - - (t - ;; Are we at a declarator? Try to go back to the declaration - ;; to check this. If we get there, check whether a "typedef" - ;; is there, then fontify the declarators accordingly. - (let ((decl-search-lim (c-determine-limit 1000)) - paren-state bod-res encl-pos is-typedef - c-recognize-knr-p) ; Strictly speaking, bogus, but it - ; speeds up lisp.h tremendously. - (save-excursion - (if (c-back-over-member-initializers) - t ; Can't be at a declarator - (unless (or (eobp) - (looking-at "\\s(\\|\\s)")) - (forward-char)) - (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim))) - (if (and (eq bod-res 'same) - (save-excursion - (c-backward-syntactic-ws) - (eq (char-before) ?\}))) - (c-beginning-of-decl-1 decl-search-lim)) - - ;; We're now putatively at the declaration. - (setq paren-state (c-parse-state)) - ;; At top level or inside a "{"? - (if (or (not (setq encl-pos - (c-most-enclosing-brace paren-state))) - (eq (char-after encl-pos) ?\{)) - (progn - (when (looking-at c-typedef-key) ; "typedef" - (setq is-typedef t) - (goto-char (match-end 0)) - (c-forward-syntactic-ws)) - ;; At a real declaration? - (if (memq (c-forward-type t) '(t known found decltype)) - (progn - (c-font-lock-declarators (point-max) t is-typedef) - nil) - ;; False alarm. Return t to go on to the next check. - (goto-char start-pos) - t)) - t))))))) + (t t))) ;; It was a false alarm. Check if we're in a label (or other ;; construct with `:' except bitfield) instead. @@ -1545,6 +1504,47 @@ casts and declarations are fontified. Used on level 2 and higher." (c-font-lock-declarators limit t nil))) nil) +(defun c-font-lock-cut-off-declarators (limit) + ;; Fontify any declarators "cut off" from their declaring type at the start + ;; of the region being fontified. + ;; + ;; This function will be called from font-lock- for a region bounded by + ;; POINT and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; fontification". + (let ((decl-search-lim (c-determine-limit 1000)) + paren-state bod-res is-typedef encl-pos + c-recognize-knr-p) ; Strictly speaking, bogus, but it + ; speeds up lisp.h tremendously. + (save-excursion + (when (not (c-back-over-member-initializers)) + (unless (or (eobp) + (looking-at "\\s(\\|\\s)")) + (forward-char)) + (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim))) + (if (and (eq bod-res 'same) + (save-excursion + (c-backward-syntactic-ws) + (eq (char-before) ?\}))) + (c-beginning-of-decl-1 decl-search-lim)) + + ;; We're now putatively at the declaration. + (setq paren-state (c-parse-state)) + ;; At top level or inside a "{"? + (if (or (not (setq encl-pos + (c-most-enclosing-brace paren-state))) + (eq (char-after encl-pos) ?\{)) + (progn + (when (looking-at c-typedef-key) ; "typedef" + (setq is-typedef t) + (goto-char (match-end 0)) + (c-forward-syntactic-ws)) + ;; At a real declaration? + (if (memq (c-forward-type t) '(t known found decltype)) + (c-font-lock-declarators (point-max) t is-typedef))) + nil))))) + (defun c-font-lock-enclosing-decls (limit) ;; Fontify the declarators of (nested) declarations we're in the middle of. ;; This is mainly for when a jit-lock etc. chunk starts inside the brace @@ -1715,6 +1715,10 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." 'c-type 'c-decl-end))) c-font-lock-objc-methods)) + ;; Fontify declarators which have been cut off from their declaring + ;; types at the start of the region. + c-font-lock-cut-off-declarators + ;; Fontify all declarations, casts and normal labels. c-font-lock-declarations commit fd8084aaf925a52754e01f69f4b6c5593be0982d Author: Stefan Monnier Date: Wed Jun 15 13:21:59 2016 -0400 Automatically find vars and functions via definition-prefixes * lisp/help-fns.el (help-definition-prefixes): New var and function. (help--loaded-p, help--load-prefixes, help--symbol-completion-table): New functions. (describe-function, describe-variable): Use them. * lisp/emacs-lisp/radix-tree.el (radix-tree--prefixes) (radix-tree-prefixes, radix-tree-from-map): New functions. diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el index d4b5cd2..8146bb3 100644 --- a/lisp/emacs-lisp/radix-tree.el +++ b/lisp/emacs-lisp/radix-tree.el @@ -103,6 +103,47 @@ (if (integerp val) `(t . ,val) val) i)))) +;; (defun radix-tree--trim (tree string i) +;; (if (= i (length string)) +;; tree +;; (pcase tree +;; (`((,prefix . ,ptree) . ,rtree) +;; (let* ((ni (+ i (length prefix))) +;; (cmp (compare-strings prefix nil nil string i ni)) +;; ;; FIXME: We could compute nrtree more efficiently +;; ;; whenever cmp is not -1 or 1. +;; (nrtree (radix-tree--trim rtree string i))) +;; (if (eq t cmp) +;; (pcase (radix-tree--trim ptree string ni) +;; (`nil nrtree) +;; (`((,pprefix . ,pptree)) +;; `((,(concat prefix pprefix) . ,pptree) . ,nrtree)) +;; (nptree `((,prefix . ,nptree) . ,nrtree))) +;; (let ((n (if (< cmp 0) (- -1 cmp) (- cmp 1)))) +;; (cond +;; ((equal (+ n i) (length string)) +;; `((,prefix . ,ptree) . ,nrtree)) +;; (t nrtree)))))) +;; (val val)))) + +(defun radix-tree--prefixes (tree string i prefixes) + (pcase tree + (`((,prefix . ,ptree) . ,rtree) + (let* ((ni (+ i (length prefix))) + (cmp (compare-strings prefix nil nil string i ni)) + ;; FIXME: We could compute prefixes more efficiently + ;; whenever cmp is not -1 or 1. + (prefixes (radix-tree--prefixes rtree string i prefixes))) + (if (eq t cmp) + (radix-tree--prefixes ptree string ni prefixes) + prefixes))) + (val + (if (null val) + prefixes + (cons (cons (substring string 0 i) + (if (eq (car-safe val) t) (cdr val) val)) + prefixes))))) + (defun radix-tree--subtree (tree string i) (if (equal (length string) i) tree (pcase tree @@ -143,6 +184,16 @@ If not found, return nil." "Return the subtree of TREE rooted at the prefix STRING." (radix-tree--subtree tree string 0)) +;; (defun radix-tree-trim (tree string) +;; "Return a TREE which only holds entries \"related\" to STRING. +;; \"Related\" is here defined as entries where there's a `string-prefix-p' relation +;; between STRING and the key." +;; (radix-tree-trim tree string 0)) + +(defun radix-tree-prefixes (tree string) + "Return an alist of all bindings in TREE for prefixes of STRING." + (radix-tree--prefixes tree string 0 nil)) + (eval-and-compile (pcase-defmacro radix-tree-leaf (vpat) ;; FIXME: We'd like to use a negative pattern (not consp), but pcase @@ -181,8 +232,15 @@ PREFIX is only used internally." (defun radix-tree-count (tree) (let ((i 0)) - (radix-tree-iter-mappings tree (lambda (_ _) (setq i (1+ i)))) + (radix-tree-iter-mappings tree (lambda (_k _v) (setq i (1+ i)))) i)) +(defun radix-tree-from-map (map) + ;; Aka (cl-defmethod map-into (map (type (eql radix-tree)))) ...) + (require 'map) + (let ((rt nil)) + (map-apply (lambda (k v) (setq rt (radix-tree-insert rt k v))) map) + rt)) + (provide 'radix-tree) ;;; radix-tree.el ends here diff --git a/lisp/help-fns.el b/lisp/help-fns.el index f591392..e92019f 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -34,6 +34,7 @@ (require 'cl-lib) (require 'help-mode) +(require 'radix-tree) (defvar help-fns-describe-function-functions nil "List of functions to run in help buffer in `describe-function'. @@ -43,6 +44,61 @@ The functions will receive the function name as argument.") ;; Functions +(defvar help-definition-prefixes nil + ;; FIXME: We keep `definition-prefixes' as a hash-table so as to + ;; avoid pre-loading radix-tree and because it takes slightly less + ;; memory. But when we use this table it's more efficient to + ;; represent it as a radix tree, since the main operation is to do + ;; `radix-tree-prefixes'. Maybe we should just bite the bullet and + ;; use a radix tree for `definition-prefixes' (it's not *that* + ;; costly, really). + "Radix-tree representation replacing `definition-prefixes'.") + +(defun help-definition-prefixes () + "Return the up-to-date radix-tree form of `definition-prefixes'." + (when (> (hash-table-count definition-prefixes) 0) + (maphash (lambda (prefix files) + (let ((old (radix-tree-lookup help-definition-prefixes prefix))) + (setq help-definition-prefixes + (radix-tree-insert help-definition-prefixes + prefix (append old files))))) + definition-prefixes) + (clrhash definition-prefixes)) + help-definition-prefixes) + +(defun help--loaded-p (file) + "Try and figure out if FILE has already been loaded." + (or (let ((feature (intern-soft file))) + (and feature (featurep feature))) + (let* ((re (load-history-regexp file)) + (done nil)) + (dolist (x load-history) + (if (string-match-p re (car x)) (setq done t))) + done))) + +(defun help--load-prefixes (prefixes) + (pcase-dolist (`(,prefix . ,files) prefixes) + (setq help-definition-prefixes + (radix-tree-insert help-definition-prefixes prefix nil)) + (dolist (file files) + ;; FIXME: Should we scan help-definition-prefixes to remove + ;; other prefixes of the same file? + ;; FIXME: this regexp business is not good enough: for file + ;; `toto', it will say `toto' is loaded when in reality it was + ;; just cedet/semantic/toto that has been loaded. + (unless (help--loaded-p file) + (load file 'noerror 'nomessage))))) + +(defun help--symbol-completion-table (string pred action) + (let ((prefixes (radix-tree-prefixes (help-definition-prefixes) string))) + (help--load-prefixes prefixes)) + (let ((prefix-completions + (mapcar #'intern (all-completions string definition-prefixes)))) + (complete-with-action action obarray string + (if pred (lambda (sym) + (or (funcall pred sym) + (memq sym prefix-completions))))))) + (defvar describe-function-orig-buffer nil "Buffer that was current when `describe-function' was invoked. Functions on `help-fns-describe-function-functions' can use this @@ -58,8 +114,9 @@ to get buffer-local values.") (setq val (completing-read (if fn (format "Describe function (default %s): " fn) "Describe function: ") - obarray 'fboundp t nil nil - (and fn (symbol-name fn)))) + #'help--symbol-completion-table + #'fboundp + t nil nil (and fn (symbol-name fn)))) (list (if (equal val "") fn (intern val))))) (or (and function (symbolp function)) @@ -706,7 +763,7 @@ it is displayed along with the global value." (format "Describe variable (default %s): " v) "Describe variable: ") - obarray + #'help--symbol-completion-table (lambda (vv) ;; In case the variable only exists in the buffer ;; the command we switch back to that buffer before commit 40e0ef481160d0a0b2290d47c012cc50021a8a82 Author: Michal Nazarewicz Date: Tue Jun 7 14:05:36 2016 +0200 Automatically detect whether .h file is C or C++ * lisp/progmodes/cc-mode.el (c-or-c++-mode): A new function which analyses contents of the buffer to determine whether it looks like C++ source code and based on that enables c-mode or c++-mode. (c-or-c++-mode--regexp): Regular expression which, when matches a buffer, signals file is C++. diff --git a/etc/NEWS b/etc/NEWS index e2c99a1..d8583cf 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -357,6 +357,13 @@ string is computed dynamically based on 'url-privacy-level'. colorful faces to make it more obvious to the user what the state is. See the 'vc-faces' customization group. +** CC mode + +*** Opening a .h file will turn C or C++ mode depending on language used. +This is done with the help of 'c-or-c++-mode' function which analyses +contents of the buffer to determine whether it's a C or C++ source +file. + * New Modes and Packages in Emacs 25.2 diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 6f32613..dd8d771 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -912,7 +912,7 @@ Note that the style variables are always made local to the buffer." (defun c-extend-region-for-CPP (beg end) ;; Adjust `c-new-BEG', `c-new-END' respectively to the beginning and end of - ;; any preprocessor construct they may be in. + ;; any preprocessor construct they may be in. ;; ;; Point is undefined both before and after this function call; the buffer ;; has already been widened, and match-data saved. The return value is @@ -1477,7 +1477,8 @@ This function is called from `c-common-init', once per mode initialization." ;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode)) -;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\'" . c-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.c\\'" . c-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.h\\'" . c-or-c++-mode)) ;; NB: The following two associate yacc and lex files to C Mode, which ;; is not really suitable for those formats. Anyway, afaik there's @@ -1518,6 +1519,40 @@ Key bindings: (cc-imenu-init cc-imenu-c-generic-expression) (c-run-mode-hooks 'c-mode-common-hook)) +(defconst c-or-c++-mode--regexp + (eval-when-compile + (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")) + (concat "^" ws-maybe "\\(?:" + "using" ws "\\(?:namespace" ws "std;\\|std::\\)" + "\\|" "namespace" "\\(:?" ws id "\\)?" ws-maybe "{" + "\\|" "class" ws id ws-maybe "[:{\n]" + "\\|" "template" ws-maybe "<.*>" + "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>" + "\\)"))) + "A regexp applied to C header files to check if they are really C++.") + +;;;###autoload +(defun c-or-c++-mode () + "Analyse buffer and enable either C or C++ mode. + +Some people and projects use .h extension for C++ header files +which is also the one used for C header files. This makes +matching on file name insufficient for detecting major mode that +should be used. + +This function attempts to use file contents to determine whether +the code is C or C++ and based on that chooses whether to enable +`c-mode' or `c++-mode'." + (if (save-excursion + (save-restriction + (save-match-data + (widen) + (goto-char (point-min)) + (re-search-forward c-or-c++-mode--regexp + (+ (point) c-guess-region-max) t)))) + (c++-mode) + (c-mode))) + ;; Support for C++ diff --git a/test/lisp/progmodes/cc-mode.el b/test/lisp/progmodes/cc-mode.el new file mode 100644 index 0000000..6cd9fa4 --- /dev/null +++ b/test/lisp/progmodes/cc-mode.el @@ -0,0 +1,65 @@ +;;; cc-mode-tests.el --- Test suite for cc-mode. -*- lexical-binning: t -*- + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Michal Nazarewicz +;; Keywords: internal +;; Human-Keywords: internal + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'cc-mode) + +(ert-deftest c-or-c++-mode () + "Test c-or-c++-mode language detection." + (cl-letf* ((mode nil) + (do-test (lambda (content expected) + (delete-region (point-min) (point-max)) + (insert content) + (setq mode nil) + (c-or-c++-mode) + (unless(eq expected mode) + (ert-fail + (format "expected %s but got %s when testing '%s'" + expected mode content))))) + ((symbol-function 'c-mode) (lambda () (setq mode 'c-mode))) + ((symbol-function 'c++-mode) (lambda () (setq mode 'c++-mode)))) + (with-temp-buffer + (mapc (lambda (content) + (funcall do-test content 'c++-mode) + (funcall do-test (concat "// " content) 'c-mode) + (funcall do-test (concat " * " content) 'c-mode)) + '("using \t namespace \t std;" + "using \t std::string;" + "namespace \t {" + "namespace \t foo \t {" + "class \t Blah_42 \t {" + "class \t Blah_42 \t \n" + "class \t _42_Blah:public Foo {" + "template \t < class T >" + "template< class T >" + "#include " + "#include" + "#include \t ")) + + (mapc (lambda (content) (funcall do-test content 'c-mode)) + '("struct \t Blah_42 \t {" + "struct template {" + "#include "))))) commit 3be326e8e50e296ebd6ed116b5e5b7b54267b087 Author: Alan Mackenzie Date: Wed Jun 15 15:57:37 2016 +0000 Parse compound identifiers in C++ member initialization lists. * lisp/progmodes/cc-engine.el (c-back-over-compound-identifier): New function. (c-back-over-member-initializer-braces, c-back-over-list-of-member-inits) (c-back-over-member-initializers): Call c-back-over-compound-identifier rather than c-simple-skip-symbol-backward. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 7c77b70..32eca3e 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -7128,6 +7128,31 @@ comment at the start of cc-engine.el for more info." (prog1 (car ,ps) (setq ,ps (cdr ,ps))))) +(defun c-back-over-compound-identifier () + ;; Point is putatively just after a "compound identifier", i.e. something + ;; looking (in C++) like this "FQN::of::base::Class". Move to the start of + ;; this construct and return t. If the parsing fails, return nil, leaving + ;; point unchanged. + (let ((here (point)) + end + ) + (if (not (c-simple-skip-symbol-backward)) + nil + (while + (progn + (setq end (point)) + (c-backward-syntactic-ws) + (c-backward-token-2) + (and + c-opt-identifier-concat-key + (looking-at c-opt-identifier-concat-key) + (progn + (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)))) + (setq end (point))) + (goto-char end) + t))) + (defun c-back-over-member-initializer-braces () ;; Point is just after a closing brace/parenthesis. Try to parse this as a ;; C++ member initializer list, going back to just after the introducing ":" @@ -7138,7 +7163,7 @@ comment at the start of cc-engine.el for more info." (when (not (c-go-list-backward)) (throw 'done nil)) (c-backward-syntactic-ws) - (when (not (c-simple-skip-symbol-backward)) + (when (not (c-back-over-compound-identifier)) (throw 'done nil)) (c-backward-syntactic-ws) @@ -7150,7 +7175,7 @@ comment at the start of cc-engine.el for more info." (when (not (c-go-list-backward)) (throw 'done nil)) (c-backward-syntactic-ws) - (when (not (c-simple-skip-symbol-backward)) + (when (not (c-back-over-compound-identifier)) (throw 'done nil)) (c-backward-syntactic-ws)) @@ -7174,7 +7199,7 @@ comment at the start of cc-engine.el for more info." (when (not (c-go-list-backward)) (throw 'done nil)) (c-backward-syntactic-ws) - (when (not (c-simple-skip-symbol-backward)) + (when (not (c-back-over-compound-identifier)) (throw 'level nil)) (c-backward-syntactic-ws))) @@ -7196,7 +7221,7 @@ comment at the start of cc-engine.el for more info." (when (not (c-go-list-backward)) (throw 'done nil)) (c-backward-syntactic-ws)) - (when (c-simple-skip-symbol-backward) + (when (c-back-over-compound-identifier) (c-backward-syntactic-ws)) (c-back-over-list-of-member-inits) (and (eq (char-before) ?:) @@ -7212,7 +7237,7 @@ comment at the start of cc-engine.el for more info." (catch 'level (goto-char pos) (c-backward-syntactic-ws) - (when (not (c-simple-skip-symbol-backward)) + (when (not (c-back-over-compound-identifier)) (throw 'level nil)) (c-backward-syntactic-ws) (c-back-over-list-of-member-inits) commit 4a2092efd2ac76fce04a2587b360ed2ca1eac4d7 Author: Stefan Monnier Date: Wed Jun 15 11:36:51 2016 -0400 Advertize set-keymap-parent as replacement for copy-keymap * doc/lispref/keymaps.texi (Creating Keymaps): * src/keymap.c (Fcopy_keymap): Advertize set-keymap-parent as replacement. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 61ac80c..9abbd89 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -341,7 +341,21 @@ lots of bindings; for just a few, the sparse keymap is better. @end defun @defun copy-keymap keymap -This function returns a copy of @var{keymap}. Any keymaps that +This function returns a copy of @var{keymap}. This is almost never +needed. If you want a keymap that's like another yet with a few +changes, you should use map inheritance rather than copying. +I.e., something like: + +@example +@group +(let ((map (make-sparse-keymap))) + (set-keymap-parent map ) + (define-key map ...) + ...) +@end group +@end example + +When performing @code{copy-keymap}, any keymaps that appear directly as bindings in @var{keymap} are also copied recursively, and so on to any number of levels. However, recursive copying does not take place when the definition of a character is a symbol whose function diff --git a/src/keymap.c b/src/keymap.c index 44335ad..b27df1d 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -971,8 +971,18 @@ copy_keymap_1 (Lisp_Object chartable, Lisp_Object idx, Lisp_Object elt) DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, doc: /* Return a copy of the keymap KEYMAP. -The copy starts out with the same definitions of KEYMAP, -but changing either the copy or KEYMAP does not affect the other. + +Note that this is almost never needed. If you want a keymap that's like +another yet with a few changes, you should use map inheritance rather +than copying. I.e. something like: + + (let ((map (make-sparse-keymap))) + (set-keymap-parent map ) + (define-key map ...) + ...) + +After performing `copy-keymap', the copy starts out with the same definitions +of KEYMAP, but changing either the copy or KEYMAP does not affect the other. Any key definitions that are subkeymaps are recursively copied. However, a key definition which is a symbol whose definition is a keymap is not copied. */) commit 090060a72c7245796bffeb14daf9da1b49f339f0 Author: Ted Zlatanov Date: Wed Jun 15 10:18:31 2016 -0400 * generic-x.el (ansible-inventory-generic-mode): Warn if value is missing diff --git a/lisp/generic-x.el b/lisp/generic-x.el index bd0d831..1e3a6e1 100644 --- a/lisp/generic-x.el +++ b/lisp/generic-x.el @@ -655,6 +655,10 @@ like an INI file. You can add this hook to `find-file-hook'." nil '(("^\\s-*\\(\\[.*\\]\\)" 1 font-lock-constant-face) ("^\\s-*\\([^ \n\r]*\\)" 1 font-lock-function-name-face) + ;; Variable assignments must be x=y, so highlight as warning if + ;; the value is missing. + ("\\s-\\([^ =\n\r]+\\)[\n\r ]" 1 font-lock-warning-face) + ;; Variable assignments: x=y ("\\([^ =\n\r]+\\)=\\([^ \n\r]*\\)" (1 font-lock-variable-name-face) (2 font-lock-keyword-face))) commit 299f194aaff664fa60b5fd3d06d555f07755b3ba Author: Tim Chambers Date: Sat Jun 11 23:13:40 2016 -0600 Add new ansible-inventory-generic-mode (Bug#23762) * lisp/generic-x.el (ansible-inventory-generic-mode): Add new mode. Copyright-paperwork-exempt: yes diff --git a/lisp/generic-x.el b/lisp/generic-x.el index 71ba1f7..bd0d831 100644 --- a/lisp/generic-x.el +++ b/lisp/generic-x.el @@ -215,6 +215,7 @@ This hook will be installed if the variable (defconst generic-unix-modes '(alias-generic-mode + ansible-inventory-generic-mode etc-fstab-generic-mode etc-modules-conf-generic-mode etc-passwd-generic-mode @@ -646,6 +647,26 @@ like an INI file. You can add this hook to `find-file-hook'." '((nil "^\\(alias\\|unalias\\)\\s-+\\([-a-zA-Z0-9_]+\\)" 2)))))) "Generic mode for C Shell alias files.")) +;; Ansible inventory files +(when (memq 'ansible-inventory-generic-mode generic-extras-enable-list) + +(define-generic-mode ansible-inventory-generic-mode + '(?#) + nil + '(("^\\s-*\\(\\[.*\\]\\)" 1 font-lock-constant-face) + ("^\\s-*\\([^ \n\r]*\\)" 1 font-lock-function-name-face) + ("\\([^ =\n\r]+\\)=\\([^ \n\r]*\\)" + (1 font-lock-variable-name-face) + (2 font-lock-keyword-face))) + '("inventory") + (list + (function + (lambda () + (setq imenu-generic-expression + '((nil "^\\s-*\\[\\(.*\\)\\]" 1) + ("*Variables*" "\\s-+\\([^ =\n\r]+\\)=" 1)))))) + "Generic mode for Ansible inventory files.")) + ;;; Windows RC files ;; Contributed by ACorreir@pervasive-sw.com (Alfred Correira) (when (memq 'rc-generic-mode generic-extras-enable-list)