diff options
| author | Lute Kamstra | 2005-04-13 08:55:01 +0000 |
|---|---|---|
| committer | Lute Kamstra | 2005-04-13 08:55:01 +0000 |
| commit | 9aade6c6f258cf40faaf0c2e7a50adb649c98a70 (patch) | |
| tree | 6f05e69da28a8313f78a8f19c912cf8e5bcbf924 | |
| parent | be7d14945760d1926fbf7f3f50bc2e042446c307 (diff) | |
| download | emacs-9aade6c6f258cf40faaf0c2e7a50adb649c98a70.tar.gz emacs-9aade6c6f258cf40faaf0c2e7a50adb649c98a70.zip | |
Move here from parent dir.
| -rw-r--r-- | lisp/emacs-lisp/generic.el | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/generic.el b/lisp/emacs-lisp/generic.el new file mode 100644 index 00000000000..1bfa598a7c7 --- /dev/null +++ b/lisp/emacs-lisp/generic.el | |||
| @@ -0,0 +1,345 @@ | |||
| 1 | ;;; generic.el --- defining simple major modes with comment and font-lock | ||
| 2 | ;; | ||
| 3 | ;; Copyright (C) 1997, 1999, 2004, 2005 Free Software Foundation, Inc. | ||
| 4 | ;; | ||
| 5 | ;; Author: Peter Breton <pbreton@cs.umb.edu> | ||
| 6 | ;; Created: Fri Sep 27 1996 | ||
| 7 | ;; Keywords: generic, comment, font-lock | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 24 | ;; Boston, MA 02111-1307, USA. | ||
| 25 | |||
| 26 | ;;; Commentary: | ||
| 27 | |||
| 28 | ;; INTRODUCTION: | ||
| 29 | ;; | ||
| 30 | ;; The macro `define-generic-mode' can be used to define small modes | ||
| 31 | ;; which provide basic comment and font-lock support. These modes are | ||
| 32 | ;; intended for the many configuration files and such which are too | ||
| 33 | ;; small for a "real" mode, but still have a regular syntax, comment | ||
| 34 | ;; characters and the like. | ||
| 35 | ;; | ||
| 36 | ;; Each generic mode can define the following: | ||
| 37 | ;; | ||
| 38 | ;; * List of comment-characters. The entries in this list should be | ||
| 39 | ;; either a character, a one or two character string or a cons pair. | ||
| 40 | ;; If the entry is a character or a string, it is added to the | ||
| 41 | ;; mode's syntax table with `comment-start' syntax. If the entry is | ||
| 42 | ;; a cons pair, the elements of the pair are considered to be | ||
| 43 | ;; `comment-start' and `comment-end' respectively. (The latter | ||
| 44 | ;; should be nil if you want comments to end at end of line.) | ||
| 45 | ;; LIMITATIONS: Emacs does not support comment strings of more than | ||
| 46 | ;; two characters in length. | ||
| 47 | ;; | ||
| 48 | ;; * List of keywords to font-lock. Each keyword should be a string. | ||
| 49 | ;; If you have additional keywords which should be highlighted in a | ||
| 50 | ;; face different from `font-lock-keyword-face', you can use the | ||
| 51 | ;; convenience function `generic-make-keywords-list' (which see), | ||
| 52 | ;; and add the result to the following list: | ||
| 53 | ;; | ||
| 54 | ;; * Additional expressions to font-lock. This should be a list of | ||
| 55 | ;; expressions, each of which should be of the same form as those in | ||
| 56 | ;; `font-lock-keywords'. | ||
| 57 | ;; | ||
| 58 | ;; * List of regular expressions to be placed in auto-mode-alist. | ||
| 59 | ;; | ||
| 60 | ;; * List of functions to call to do some additional setup | ||
| 61 | ;; | ||
| 62 | ;; This should pretty much cover basic functionality; if you need much | ||
| 63 | ;; more than this, or you find yourself writing extensive customizations, | ||
| 64 | ;; perhaps you should be writing a major mode instead! | ||
| 65 | ;; | ||
| 66 | ;; EXAMPLE: | ||
| 67 | ;; | ||
| 68 | ;; You can use `define-generic-mode' like this: | ||
| 69 | ;; | ||
| 70 | ;; (define-generic-mode 'foo-generic-mode | ||
| 71 | ;; (list ?%) | ||
| 72 | ;; (list "keyword") | ||
| 73 | ;; nil | ||
| 74 | ;; (list "\\.FOO\\'") | ||
| 75 | ;; (list 'foo-setup-function)) | ||
| 76 | ;; | ||
| 77 | ;; to define a new generic-mode `foo-generic-mode', which has '%' as a | ||
| 78 | ;; comment character, and "keyword" as a keyword. When files which | ||
| 79 | ;; end in '.FOO' are loaded, Emacs will go into foo-generic-mode and | ||
| 80 | ;; call foo-setup-function. You can also use the function | ||
| 81 | ;; `foo-generic-mode' (which is interactive) to put a buffer into | ||
| 82 | ;; foo-generic-mode. | ||
| 83 | ;; | ||
| 84 | ;; GOTCHAS: | ||
| 85 | ;; | ||
| 86 | ;; Be careful that your font-lock definitions are correct. Getting | ||
| 87 | ;; them wrong can cause Emacs to continually attempt to fontify! This | ||
| 88 | ;; problem is not specific to generic-mode. | ||
| 89 | |||
| 90 | ;; Credit for suggestions, brainstorming, help with debugging: | ||
| 91 | ;; ACorreir@pervasive-sw.com (Alfred Correira) | ||
| 92 | ;; Extensive cleanup by: | ||
| 93 | ;; Stefan Monnier (monnier+gnu/emacs@flint.cs.yale.edu) | ||
| 94 | |||
| 95 | ;;; Code: | ||
| 96 | |||
| 97 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 98 | ;; Internal Variables | ||
| 99 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 100 | |||
| 101 | (defvar generic-font-lock-keywords nil | ||
| 102 | "Keywords for `font-lock-defaults' in a generic mode.") | ||
| 103 | (make-variable-buffer-local 'generic-font-lock-keywords) | ||
| 104 | (defvaralias 'generic-font-lock-defaults 'generic-font-lock-keywords) | ||
| 105 | (make-obsolete-variable 'generic-font-lock-defaults 'generic-font-lock-keywords "22.1") | ||
| 106 | |||
| 107 | ;;;###autoload | ||
| 108 | (defvar generic-mode-list nil | ||
| 109 | "A list of mode names for `generic-mode'. | ||
| 110 | Do not add entries to this list directly; use `define-generic-mode' | ||
| 111 | instead (which see).") | ||
| 112 | |||
| 113 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 114 | ;; Functions | ||
| 115 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 116 | |||
| 117 | ;;;###autoload | ||
| 118 | (defmacro define-generic-mode (mode comment-list keyword-list | ||
| 119 | font-lock-list auto-mode-list | ||
| 120 | function-list &optional docstring | ||
| 121 | &rest custom-keyword-args) | ||
| 122 | "Create a new generic mode MODE. | ||
| 123 | |||
| 124 | MODE is the name of the command for the generic mode; it need not | ||
| 125 | be quoted. The optional DOCSTRING is the documentation for the | ||
| 126 | mode command. If you do not supply it, a default documentation | ||
| 127 | string will be used instead. | ||
| 128 | |||
| 129 | COMMENT-LIST is a list, whose entries are either a single | ||
| 130 | character, a one or two character string or a cons pair. If the | ||
| 131 | entry is a character or a string, it is added to the mode's | ||
| 132 | syntax table with `comment-start' syntax. If the entry is a cons | ||
| 133 | pair, the elements of the pair are considered to be | ||
| 134 | `comment-start' and `comment-end' respectively. (The latter | ||
| 135 | should be nil if you want comments to end at end of line.) Note | ||
| 136 | that Emacs has limitations regarding comment characters. | ||
| 137 | |||
| 138 | KEYWORD-LIST is a list of keywords to highlight with | ||
| 139 | `font-lock-keyword-face'. Each keyword should be a string. | ||
| 140 | |||
| 141 | FONT-LOCK-LIST is a list of additional expressions to highlight. | ||
| 142 | Each entry in the list should have the same form as an entry in | ||
| 143 | `font-lock-keywords'. | ||
| 144 | |||
| 145 | AUTO-MODE-LIST is a list of regular expressions to add to | ||
| 146 | `auto-mode-alist'. These regexps are added to `auto-mode-alist' | ||
| 147 | as soon as `define-generic-mode' is called. | ||
| 148 | |||
| 149 | FUNCTION-LIST is a list of functions to call to do some | ||
| 150 | additional setup. | ||
| 151 | |||
| 152 | The optional CUSTOM-KEYWORD-ARGS are pairs of keywords and | ||
| 153 | values. They will be passed to the generated `defcustom' form of | ||
| 154 | the mode hook variable MODE-hook. Defaults to MODE without the | ||
| 155 | possible trailing \"-mode\". (This default may not be a valid | ||
| 156 | customization group defined with `defgroup'. Make sure it is.) | ||
| 157 | You can specify keyword arguments without specifying a docstring. | ||
| 158 | |||
| 159 | See the file generic-x.el for some examples of `define-generic-mode'." | ||
| 160 | (declare (debug (sexp def-form def-form def-form form def-form | ||
| 161 | [&optional stringp] &rest [keywordp form])) | ||
| 162 | (indent 1)) | ||
| 163 | |||
| 164 | ;; Backward compatibility. | ||
| 165 | (when (eq (car-safe mode) 'quote) | ||
| 166 | (setq mode (eval mode))) | ||
| 167 | |||
| 168 | (when (and docstring (not (stringp docstring))) | ||
| 169 | ;; DOCSTRING is not a string so we assume that it's actually the | ||
| 170 | ;; first keyword of CUSTOM-KEYWORD-ARGS. | ||
| 171 | (push docstring custom-keyword-args) | ||
| 172 | (setq docstring nil)) | ||
| 173 | |||
| 174 | (let* ((name (symbol-name mode)) | ||
| 175 | (pretty-name (capitalize (replace-regexp-in-string | ||
| 176 | "-mode\\'" "" name))) | ||
| 177 | (mode-hook (intern (concat name "-hook")))) | ||
| 178 | |||
| 179 | (unless (plist-get custom-keyword-args :group) | ||
| 180 | (setq custom-keyword-args | ||
| 181 | (plist-put custom-keyword-args | ||
| 182 | :group `',(intern (replace-regexp-in-string | ||
| 183 | "-mode\\'" "" name))))) | ||
| 184 | |||
| 185 | `(progn | ||
| 186 | ;; Add a new entry. | ||
| 187 | (add-to-list 'generic-mode-list ,name) | ||
| 188 | |||
| 189 | ;; Add it to auto-mode-alist | ||
| 190 | (dolist (re ,auto-mode-list) | ||
| 191 | (add-to-list 'auto-mode-alist (cons re ',mode))) | ||
| 192 | |||
| 193 | (defcustom ,mode-hook nil | ||
| 194 | ,(concat "Hook run when entering " pretty-name " mode.") | ||
| 195 | :type 'hook | ||
| 196 | ,@custom-keyword-args) | ||
| 197 | |||
| 198 | (defun ,mode () | ||
| 199 | ,(or docstring | ||
| 200 | (concat pretty-name " mode.\n" | ||
| 201 | "This a generic mode defined with `define-generic-mode'.")) | ||
| 202 | (interactive) | ||
| 203 | (generic-mode-internal ',mode ,comment-list ,keyword-list | ||
| 204 | ,font-lock-list ,function-list))))) | ||
| 205 | |||
| 206 | ;;;###autoload | ||
| 207 | (defun generic-mode-internal (mode comment-list keyword-list | ||
| 208 | font-lock-list function-list) | ||
| 209 | "Go into the generic mode MODE." | ||
| 210 | (let* ((name (symbol-name mode)) | ||
| 211 | (pretty-name (capitalize (replace-regexp-in-string | ||
| 212 | "-mode\\'" "" name))) | ||
| 213 | (mode-hook (intern (concat name "-hook")))) | ||
| 214 | |||
| 215 | (kill-all-local-variables) | ||
| 216 | |||
| 217 | (setq major-mode mode | ||
| 218 | mode-name pretty-name) | ||
| 219 | |||
| 220 | (generic-mode-set-comments comment-list) | ||
| 221 | |||
| 222 | ;; Font-lock functionality. | ||
| 223 | ;; Font-lock-defaults is always set even if there are no keywords | ||
| 224 | ;; or font-lock expressions, so comments can be highlighted. | ||
| 225 | (setq generic-font-lock-keywords font-lock-list) | ||
| 226 | (when keyword-list | ||
| 227 | (push (concat "\\_<" (regexp-opt keyword-list t) "\\_>") | ||
| 228 | generic-font-lock-keywords)) | ||
| 229 | (setq font-lock-defaults '(generic-font-lock-keywords nil)) | ||
| 230 | |||
| 231 | ;; Call a list of functions | ||
| 232 | (mapcar 'funcall function-list) | ||
| 233 | |||
| 234 | (run-mode-hooks mode-hook))) | ||
| 235 | |||
| 236 | ;;;###autoload | ||
| 237 | (defun generic-mode (mode) | ||
| 238 | "Enter generic mode MODE. | ||
| 239 | |||
| 240 | Generic modes provide basic comment and font-lock functionality | ||
| 241 | for \"generic\" files. (Files which are too small to warrant their | ||
| 242 | own mode, but have comment characters, keywords, and the like.) | ||
| 243 | |||
| 244 | To define a generic-mode, use the function `define-generic-mode'. | ||
| 245 | Some generic modes are defined in `generic-x.el'." | ||
| 246 | (interactive | ||
| 247 | (list (completing-read "Generic mode: " generic-mode-list nil t))) | ||
| 248 | (funcall (intern mode))) | ||
| 249 | |||
| 250 | ;;; Comment Functionality | ||
| 251 | (defun generic-mode-set-comments (comment-list) | ||
| 252 | "Set up comment functionality for generic mode." | ||
| 253 | (let ((st (make-syntax-table)) | ||
| 254 | (chars nil) | ||
| 255 | (comstyles)) | ||
| 256 | (make-local-variable 'comment-start) | ||
| 257 | (make-local-variable 'comment-start-skip) | ||
| 258 | (make-local-variable 'comment-end) | ||
| 259 | |||
| 260 | ;; Go through all the comments | ||
| 261 | (dolist (start comment-list) | ||
| 262 | (let (end (comstyle "")) | ||
| 263 | ;; Normalize | ||
| 264 | (when (consp start) | ||
| 265 | (setq end (cdr start)) | ||
| 266 | (setq start (car start))) | ||
| 267 | (when (char-valid-p start) (setq start (char-to-string start))) | ||
| 268 | (cond | ||
| 269 | ((char-valid-p end) (setq end (char-to-string end))) | ||
| 270 | ((zerop (length end)) (setq end "\n"))) | ||
| 271 | |||
| 272 | ;; Setup the vars for `comment-region' | ||
| 273 | (if comment-start | ||
| 274 | ;; We have already setup a comment-style, so use style b | ||
| 275 | (progn | ||
| 276 | (setq comstyle "b") | ||
| 277 | (setq comment-start-skip | ||
| 278 | (concat comment-start-skip "\\|" (regexp-quote start) "+\\s-*"))) | ||
| 279 | ;; First comment-style | ||
| 280 | (setq comment-start start) | ||
| 281 | (setq comment-end (if (string-equal end "\n") "" end)) | ||
| 282 | (setq comment-start-skip (concat (regexp-quote start) "+\\s-*"))) | ||
| 283 | |||
| 284 | ;; Reuse comstyles if necessary | ||
| 285 | (setq comstyle | ||
| 286 | (or (cdr (assoc start comstyles)) | ||
| 287 | (cdr (assoc end comstyles)) | ||
| 288 | comstyle)) | ||
| 289 | (push (cons start comstyle) comstyles) | ||
| 290 | (push (cons end comstyle) comstyles) | ||
| 291 | |||
| 292 | ;; Setup the syntax table | ||
| 293 | (if (= (length start) 1) | ||
| 294 | (modify-syntax-entry (string-to-char start) | ||
| 295 | (concat "< " comstyle) st) | ||
| 296 | (let ((c0 (elt start 0)) (c1 (elt start 1))) | ||
| 297 | ;; Store the relevant info but don't update yet | ||
| 298 | (push (cons c0 (concat (cdr (assoc c0 chars)) "1")) chars) | ||
| 299 | (push (cons c1 (concat (cdr (assoc c1 chars)) | ||
| 300 | (concat "2" comstyle))) chars))) | ||
| 301 | (if (= (length end) 1) | ||
| 302 | (modify-syntax-entry (string-to-char end) | ||
| 303 | (concat ">" comstyle) st) | ||
| 304 | (let ((c0 (elt end 0)) (c1 (elt end 1))) | ||
| 305 | ;; Store the relevant info but don't update yet | ||
| 306 | (push (cons c0 (concat (cdr (assoc c0 chars)) | ||
| 307 | (concat "3" comstyle))) chars) | ||
| 308 | (push (cons c1 (concat (cdr (assoc c1 chars)) "4")) chars))))) | ||
| 309 | |||
| 310 | ;; Process the chars that were part of a 2-char comment marker | ||
| 311 | (dolist (cs (nreverse chars)) | ||
| 312 | (modify-syntax-entry (car cs) | ||
| 313 | (concat (char-to-string (char-syntax (car cs))) | ||
| 314 | " " (cdr cs)) | ||
| 315 | st)) | ||
| 316 | (set-syntax-table st))) | ||
| 317 | |||
| 318 | (defun generic-bracket-support () | ||
| 319 | "Imenu support for [KEYWORD] constructs found in INF, INI and Samba files." | ||
| 320 | (setq imenu-generic-expression | ||
| 321 | '((nil "^\\[\\(.*\\)\\]" 1)) | ||
| 322 | imenu-case-fold-search t)) | ||
| 323 | |||
| 324 | ;;;###autoload | ||
| 325 | (defun generic-make-keywords-list (keyword-list face &optional prefix suffix) | ||
| 326 | "Return a `font-lock-keywords' construct that highlights KEYWORD-LIST. | ||
| 327 | KEYWORD-LIST is a list of keyword strings that should be | ||
| 328 | highlighted with face FACE. This function calculates a regular | ||
| 329 | expression that matches these keywords and concatenates it with | ||
| 330 | PREFIX and SUFFIX. Then it returns a construct based on this | ||
| 331 | regular expression that can be used as an element of | ||
| 332 | `font-lock-keywords'." | ||
| 333 | (unless (listp keyword-list) | ||
| 334 | (error "Keywords argument must be a list of strings")) | ||
| 335 | (list (concat prefix "\\_<" | ||
| 336 | ;; Use an optimized regexp. | ||
| 337 | (regexp-opt keyword-list t) | ||
| 338 | "\\_>" suffix) | ||
| 339 | 1 | ||
| 340 | face)) | ||
| 341 | |||
| 342 | (provide 'generic) | ||
| 343 | |||
| 344 | ;; arch-tag: 239c1fc4-1303-48d9-9ac0-657d655669ea | ||
| 345 | ;;; generic.el ends here | ||