aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2000-03-10 01:17:04 +0000
committerStefan Monnier2000-03-10 01:17:04 +0000
commit5a7a545cc5e6d09cb39bb1aaf87b48ac10d1f91e (patch)
treefb92b99261cdd4b2da3818a5a1608f153168d93c
parent445b0666d6143c345042155a086c6157156abaef (diff)
downloademacs-5a7a545cc5e6d09cb39bb1aaf87b48ac10d1f91e.tar.gz
emacs-5a7a545cc5e6d09cb39bb1aaf87b48ac10d1f91e.zip
(easy-mmode-define-keymap): Extend to allow more flexibility.
(easy-mmode-set-keymap-parents, easy-mmode-define-syntax): New functions. (easy-mmode-defmap, easy-mmode-defsyntax, easy-mmode-define-derived-mode): New macros.
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/emacs-lisp/easy-mmode.el193
2 files changed, 187 insertions, 14 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 6512731114f..36a12c6c28f 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
12000-03-09 Stefan Monnier <monnier@cs.yale.edu>
2
3 * emacs-lisp/easy-mmode.el (easy-mmode-define-keymap): Extend to allow
4 more flexibility.
5 (easy-mmode-set-keymap-parents, easy-mmode-define-syntax): New functions.
6 (easy-mmode-defmap, easy-mmode-defsyntax, easy-mmode-define-derived-mode):
7 New macros.
8
12000-09-01 Didier Verna <didier@xemacs.org> 92000-09-01 Didier Verna <didier@xemacs.org>
2 10
3 * rect.el (replace-rectangle): New function. 11 * rect.el (replace-rectangle): New function.
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index c39e6b96424..98ee96bdac9 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -1,4 +1,4 @@
1;;; easy-mmode.el --- easy definition of minor modes. 1;;; easy-mmode.el --- easy definition for major and minor modes.
2 2
3;; Copyright (C) 1997 Free Software Foundation, Inc. 3;; Copyright (C) 1997 Free Software Foundation, Inc.
4 4
@@ -46,20 +46,10 @@
46;; installed. Perhaps there should be a feature to let you specify 46;; installed. Perhaps there should be a feature to let you specify
47;; orderings. 47;; orderings.
48 48
49;;; Code: 49;; Additionally to `define-minor-mode', the package provides convenient
50;; ways to define keymaps, and other helper functions for major and minor modes.
50 51
51(defun easy-mmode-define-keymap (keymap-alist &optional menu-name) 52;;; Code:
52 "Return a keymap built from KEYMAP-ALIST.
53KEYMAP-ALIST must be a list of (KEYBINDING . BINDING) where
54KEYBINDING and BINDINGS are suited as for define-key.
55optional MENU-NAME is passed to `make-sparse-keymap'."
56 (let ((keymap (make-sparse-keymap menu-name)))
57 (mapcar
58 (function (lambda (bind)
59 (define-key keymap
60 (car bind) (cdr bind))))
61 keymap-alist)
62 keymap))
63 53
64(defmacro easy-mmode-define-toggle (mode &optional doc &rest body) 54(defmacro easy-mmode-define-toggle (mode &optional doc &rest body)
65 "Define a one arg toggle mode MODE function and associated hooks. 55 "Define a one arg toggle mode MODE function and associated hooks.
@@ -161,6 +151,181 @@ Use the function `%s' to change this variable." mode-name))
161 (setcdr (assq ',mode minor-mode-map-alist) 151 (setcdr (assq ',mode minor-mode-map-alist)
162 ,keymap-sym)) )) 152 ,keymap-sym)) ))
163 153
154
155;;;
156;;; easy-mmode-defmap
157;;;
158
159(if (fboundp 'set-keymap-parents)
160 (defalias 'easy-mmode-set-keymap-parents 'set-keymap-parents)
161 (defun easy-mmode-set-keymap-parents (m parents)
162 (set-keymap-parent
163 m
164 (cond
165 ((not (consp parents)) parents)
166 ((not (cdr parents)) (car parents))
167 (t (let ((m (copy-keymap (pop parents))))
168 (easy-mmode-set-keymap-parents m parents)
169 m))))))
170
171(defun easy-mmode-define-keymap (bs &optional name m args)
172 "Return a keymap built from bindings BS.
173BS must be a list of (KEY . BINDING) where
174KEY and BINDINGS are suited as for define-key.
175optional NAME is passed to `make-sparse-keymap'.
176optional map M can be used to modify an existing map.
177ARGS is a list of additional arguments."
178 (let (inherit dense suppress)
179 (while args
180 (let ((key (pop args))
181 (val (pop args)))
182 (cond
183 ((eq key :dense) (setq dense val))
184 ((eq key :inherit) (setq inherit val))
185 ((eq key :group) )
186 ;;((eq key :suppress) (setq suppress val))
187 (t (message "Unknown argument %s in defmap" key)))))
188 (unless (keymapp m)
189 (setq bs (append m bs))
190 (setq m (if dense (make-keymap name) (make-sparse-keymap name))))
191 (dolist (b bs)
192 (let ((keys (car b))
193 (binding (cdr b)))
194 (dolist (key (if (consp keys) keys (list keys)))
195 (cond
196 ((symbolp key)
197 (substitute-key-definition key binding m global-map))
198 ((null binding)
199 (unless (keymapp (lookup-key m key)) (define-key m key binding)))
200 ((let ((o (lookup-key m key)))
201 (or (null o) (numberp o) (eq o 'undefined)))
202 (define-key m key binding))))))
203 (cond
204 ((keymapp inherit) (set-keymap-parent m inherit))
205 ((consp inherit) (easy-mmode-set-keymap-parents m inherit)))
206 m))
207
208;;;###autoload
209(defmacro easy-mmode-defmap (m bs doc &rest args)
210 `(defconst ,m
211 (easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
212 ,doc))
213
214
215;;;
216;;; easy-mmode-defsyntax
217;;;
218
219(defun easy-mmode-define-syntax (css args)
220 (let ((st (make-syntax-table (cadr (memq :copy args)))))
221 (dolist (cs css)
222 (let ((char (car cs))
223 (syntax (cdr cs)))
224 (if (sequencep char)
225 (mapcar* (lambda (c) (modify-syntax-entry c syntax st)) char)
226 (modify-syntax-entry char syntax st))))
227 st))
228
229;;;###autoload
230(defmacro easy-mmode-defsyntax (st css doc &rest args)
231 `(defconst ,st (custom-create-syntax ,css ,(cons 'list args)) doc))
232
233
234
235;;; A "macro-only" reimplementation of define-derived-mode.
236
237(defmacro easy-mmode-define-derived-mode (child parent name &optional docstring &rest body)
238 "Create a new mode as a variant of an existing mode.
239
240The arguments to this command are as follow:
241
242CHILD: the name of the command for the derived mode.
243PARENT: the name of the command for the parent mode (e.g. `text-mode').
244NAME: a string which will appear in the status line (e.g. \"Hypertext\")
245DOCSTRING: an optional documentation string--if you do not supply one,
246 the function will attempt to invent something useful.
247BODY: forms to execute just before running the
248 hooks for the new mode.
249
250Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode:
251
252 (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\")
253
254You could then make new key bindings for `LaTeX-thesis-mode-map'
255without changing regular LaTeX mode. In this example, BODY is empty,
256and DOCSTRING is generated by default.
257
258On a more complicated level, the following command uses `sgml-mode' as
259the parent, and then sets the variable `case-fold-search' to nil:
260
261 (define-derived-mode article-mode sgml-mode \"Article\"
262 \"Major mode for editing technical articles.\"
263 (setq case-fold-search nil))
264
265Note that if the documentation string had been left out, it would have
266been generated automatically, with a reference to the keymap."
267
268 ; Some trickiness, since what
269 ; appears to be the docstring
270 ; may really be the first
271 ; element of the body.
272 (if (and docstring (not (stringp docstring)))
273 (progn (setq body (cons docstring body))
274 (setq docstring nil)))
275 (let* ((child-name (symbol-name child))
276 (map (intern (concat child-name "-map")))
277 (syntax (intern (concat child-name "-syntax-table")))
278 (abbrev (intern (concat child-name "-abbrev-table")))
279 (hook (intern (concat child-name "-hook"))))
280
281 `(progn
282 (defvar ,map (make-sparse-keymap))
283 (defvar ,syntax (make-char-table 'syntax-table nil))
284 (defvar ,abbrev (progn (define-abbrev-table ',abbrev nil) ,abbrev))
285
286 (defun ,child ()
287 ,(or docstring
288 (format "Major mode derived from `%s' by `define-derived-mode'.
289Inherits all of the parent's attributes, but has its own keymap,
290abbrev table and syntax table:
291
292 `%s', `%s' and `%s'
293
294which more-or-less shadow %s's corresponding tables.
295It also runs its own `%s' after its parent's.
296
297\\{%s}" parent map syntax abbrev parent hook map))
298 (interactive)
299 ; Run the parent.
300 (,parent)
301 ; Identify special modes.
302 (put ',child 'special (get ',parent 'special))
303 ; Identify the child mode.
304 (setq major-mode ',child)
305 (setq mode-name ,name)
306 ; Set up maps and tables.
307 (unless (keymap-parent ,map)
308 (set-keymap-parent ,map (current-local-map)))
309 (let ((parent (char-table-parent ,syntax)))
310 (unless (and parent (not (eq parent (standard-syntax-table))))
311 (set-char-table-parent ,syntax (syntax-table))))
312 (when local-abbrev-table
313 (mapatoms
314 (lambda (symbol)
315 (or (intern-soft (symbol-name symbol) ,abbrev)
316 (define-abbrev ,abbrev (symbol-name symbol)
317 (symbol-value symbol) (symbol-function symbol))))
318 local-abbrev-table))
319
320 (use-local-map ,map)
321 (set-syntax-table ,syntax)
322 (setq local-abbrev-table ,abbrev)
323 ; Splice in the body (if any).
324 ,@body
325 ; Run the hooks, if any.
326 (run-hooks ',hook)))))
327
328
164(provide 'easy-mmode) 329(provide 'easy-mmode)
165 330
166;;; easy-mmode.el ends here 331;;; easy-mmode.el ends here