aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLute Kamstra2005-04-13 08:55:01 +0000
committerLute Kamstra2005-04-13 08:55:01 +0000
commit9aade6c6f258cf40faaf0c2e7a50adb649c98a70 (patch)
tree6f05e69da28a8313f78a8f19c912cf8e5bcbf924
parentbe7d14945760d1926fbf7f3f50bc2e042446c307 (diff)
downloademacs-9aade6c6f258cf40faaf0c2e7a50adb649c98a70.tar.gz
emacs-9aade6c6f258cf40faaf0c2e7a50adb649c98a70.zip
Move here from parent dir.
-rw-r--r--lisp/emacs-lisp/generic.el345
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'.
110Do not add entries to this list directly; use `define-generic-mode'
111instead (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
124MODE is the name of the command for the generic mode; it need not
125be quoted. The optional DOCSTRING is the documentation for the
126mode command. If you do not supply it, a default documentation
127string will be used instead.
128
129COMMENT-LIST is a list, whose entries are either a single
130character, a one or two character string or a cons pair. If the
131entry is a character or a string, it is added to the mode's
132syntax table with `comment-start' syntax. If the entry is a cons
133pair, the elements of the pair are considered to be
134`comment-start' and `comment-end' respectively. (The latter
135should be nil if you want comments to end at end of line.) Note
136that Emacs has limitations regarding comment characters.
137
138KEYWORD-LIST is a list of keywords to highlight with
139`font-lock-keyword-face'. Each keyword should be a string.
140
141FONT-LOCK-LIST is a list of additional expressions to highlight.
142Each entry in the list should have the same form as an entry in
143`font-lock-keywords'.
144
145AUTO-MODE-LIST is a list of regular expressions to add to
146`auto-mode-alist'. These regexps are added to `auto-mode-alist'
147as soon as `define-generic-mode' is called.
148
149FUNCTION-LIST is a list of functions to call to do some
150additional setup.
151
152The optional CUSTOM-KEYWORD-ARGS are pairs of keywords and
153values. They will be passed to the generated `defcustom' form of
154the mode hook variable MODE-hook. Defaults to MODE without the
155possible trailing \"-mode\". (This default may not be a valid
156customization group defined with `defgroup'. Make sure it is.)
157You can specify keyword arguments without specifying a docstring.
158
159See 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
240Generic modes provide basic comment and font-lock functionality
241for \"generic\" files. (Files which are too small to warrant their
242own mode, but have comment characters, keywords, and the like.)
243
244To define a generic-mode, use the function `define-generic-mode'.
245Some 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.
327KEYWORD-LIST is a list of keyword strings that should be
328highlighted with face FACE. This function calculates a regular
329expression that matches these keywords and concatenates it with
330PREFIX and SUFFIX. Then it returns a construct based on this
331regular 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