comparison lisp/derived.el @ 2135:e6d43c299b9c

[xemacs-hg @ 2004-06-17 03:01:10 by james] Synch with Emacs 21.3 derived.el, plus new stuff in subr.el to support it, as well as some documentation.
author james
date Thu, 17 Jun 2004 03:01:17 +0000
parents e2ddc2a2b794
children 9da6e6c569f7
comparison
equal deleted inserted replaced
2134:ab08d33c34e5 2135:e6d43c299b9c
1 ;;; derived.el --- allow inheritance of major modes. 1 ;;; derived.el --- allow inheritance of major modes
2 2 ;;; (formerly mode-clone.el)
3 ;; Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. 3
4 ;; Copyright (C) 1993, 1994, 1999, 2003 Free Software Foundation, Inc.
4 5
5 ;; Author: David Megginson (dmeggins@aix1.uottawa.ca) 6 ;; Author: David Megginson (dmeggins@aix1.uottawa.ca)
6 ;; Maintainer: XEmacs Development Team 7 ;; Maintainer: XEmacs Development Team
7 ;; Keywords: extensions, dumped 8 ;; Keywords: extensions, dumped
8 9
21 ;; You should have received a copy of the GNU General Public License 22 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free 23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
23 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 ;; 02111-1307, USA. 25 ;; 02111-1307, USA.
25 26
26 ;;; Synched up with: FSF 19.34. 27 ;;; Synched up with: FSF 21.3.
27 28
28 ;;; Commentary: 29 ;;; Commentary:
29 30
30 ;; This file is dumped with XEmacs. 31 ;; This file is dumped with XEmacs.
31 32
72 ;; from the current text-mode-abbrev table 73 ;; from the current text-mode-abbrev table
73 ;; - change the mode line to read "Hypertext" 74 ;; - change the mode line to read "Hypertext"
74 ;; - assign the value 'hypertext-mode' to the 'major-mode' variable 75 ;; - assign the value 'hypertext-mode' to the 'major-mode' variable
75 ;; - run the body of commands provided in the macro -- in this case, 76 ;; - run the body of commands provided in the macro -- in this case,
76 ;; set the local variable `case-fold-search' to nil. 77 ;; set the local variable `case-fold-search' to nil.
77 ;; - **run the command (hypertext-mode-setup), which is empty by
78 ;; default, but may be redefined by the user to contain special
79 ;; commands (ie. setting local variables like 'outline-regexp')
80 ;; **NOTE: do not use this option -- it will soon be obsolete.
81 ;; - run anything assigned to 'hypertext-mode-hooks' (obsolete, but
82 ;; supported for the sake of compatibility).
83 ;; 78 ;;
84 ;; The advantages of this system are threefold. First, text mode is 79 ;; The advantages of this system are threefold. First, text mode is
85 ;; untouched -- if you had added the new keystroke to `text-mode-map,' 80 ;; untouched -- if you had added the new keystroke to `text-mode-map,'
86 ;; possibly using hooks, you would have added it to all text buffers 81 ;; possibly using hooks, you would have added it to all text buffers
87 ;; -- here, it appears only in hypertext buffers, where it makes 82 ;; -- here, it appears only in hypertext buffers, where it makes
88 ;; sense. Second, it is possible to build even further, and make 83 ;; sense. Second, it is possible to build even further, and make
89 ;; a derived mode from a derived mode. The commands 84 ;; a derived mode from a derived mode. The commands
90 ;; 85 ;;
91 ;; (define-derived-mode html-mode hypertext-mode "HTML") 86 ;; (define-derived-mode html-mode hypertext-mode "HTML")
92 ;; [various key definitions] 87 ;; [various key definitions]
93 ;; 88 ;;
94 ;; will add a new major mode for HTML with very little fuss. 89 ;; will add a new major mode for HTML with very little fuss.
95 ;; 90 ;;
96 ;; Note also the function `derived-mode-class,' which returns the non-derived 91 ;; Note also the function `derived-mode-p' which can tell if the current
97 ;; major mode which a derived mode is based on (ie. NOT necessarily the 92 ;; mode derives from another. In a hypertext-mode, buffer, for example,
98 ;; immediate parent). 93 ;; (derived-mode-p 'text-mode) would return non-nil. This should always
99 ;; 94 ;; be used in place of (eq major-mode 'text-mode).
100 ;; (derived-mode-class 'text-mode) ==> text-mode
101 ;; (derived-mode-class 'hypertext-mode) ==> text-mode
102 ;; (derived-mode-class 'html-mode) ==> text-mode
103 95
104 ;;; Code: 96 ;;; Code:
97
98 ;;; PRIVATE: defsubst must be defined before they are first used
99
100 (defsubst derived-mode-hook-name (mode)
101 "Construct the mode hook name based on mode name MODE."
102 (intern (concat (symbol-name mode) "-hook")))
103
104 (defsubst derived-mode-map-name (mode)
105 "Construct a map name based on a MODE name."
106 (intern (concat (symbol-name mode) "-map")))
107
108 (defsubst derived-mode-syntax-table-name (mode)
109 "Construct a syntax-table name based on a MODE name."
110 (intern (concat (symbol-name mode) "-syntax-table")))
111
112 (defsubst derived-mode-abbrev-table-name (mode)
113 "Construct an abbrev-table name based on a MODE name."
114 (intern (concat (symbol-name mode) "-abbrev-table")))
105 115
106 ;; PUBLIC: define a new major mode which inherits from an existing one. 116 ;; PUBLIC: define a new major mode which inherits from an existing one.
107 117
108 ;; XEmacs -- no autoload 118 ;; XEmacs -- no autoload
109 (defmacro define-derived-mode (child parent name &optional docstring &rest body) 119 (defmacro define-derived-mode (child parent name &optional docstring &rest body)
110 "Create a new mode as a variant of an existing mode. 120 "Create a new mode as a variant of an existing mode.
111 121
112 The arguments to this command are as follow: 122 The arguments to this command are as follow:
113 123
114 CHILD: the name of the command for the derived mode. 124 CHILD: the name of the command for the derived mode.
115 PARENT: the name of the command for the parent mode (ie. text-mode). 125 PARENT: the name of the command for the parent mode (e.g. `text-mode')
116 NAME: a string which will appear in the status line (ie. \"Hypertext\") 126 or nil if there is no parent.
127 NAME: a string which will appear in the status line (e.g. \"Hypertext\")
117 DOCSTRING: an optional documentation string--if you do not supply one, 128 DOCSTRING: an optional documentation string--if you do not supply one,
118 the function will attempt to invent something useful. 129 the function will attempt to invent something useful.
119 BODY: forms to execute just before running the 130 BODY: forms to execute just before running the
120 hooks for the new mode. 131 hooks for the new mode. Do not use `interactive' here.
132
133 BODY can start with a bunch of keyword arguments. The following keyword
134 arguments are currently understood:
135 :group GROUP
136 Declare the customization group that corresponds to this mode.
137 :syntax-table TABLE
138 Use TABLE instead of the default.
139 A nil value means to simply use the same syntax-table as the parent.
140 :abbrev-table TABLE
141 Use TABLE instead of the default.
142 A nil value means to simply use the same abbrev-table as the parent.
121 143
122 Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode: 144 Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode:
123 145
124 (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\") 146 (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\")
125 147
126 You could then make new key bindings for `LaTeX-thesis-mode-map' 148 You could then make new key bindings for `LaTeX-thesis-mode-map'
127 without changing regular LaTeX mode. In this example, BODY is empty, 149 without changing regular LaTeX mode. In this example, BODY is empty,
128 and DOCSTRING is generated by default. 150 and DOCSTRING is generated by default.
129 151
130 On a more complicated level, the following command uses sgml-mode as 152 On a more complicated level, the following command uses `sgml-mode' as
131 the parent, and then sets the variable `case-fold-search' to nil: 153 the parent, and then sets the variable `case-fold-search' to nil:
132 154
133 (define-derived-mode article-mode sgml-mode \"Article\" 155 (define-derived-mode article-mode sgml-mode \"Article\"
134 \"Major mode for editing technical articles.\" 156 \"Major mode for editing technical articles.\"
135 (setq case-fold-search nil)) 157 (setq case-fold-search nil))
136 158
137 Note that if the documentation string had been left out, it would have 159 Note that if the documentation string had been left out, it would have
138 been generated automatically, with a reference to the keymap." 160 been generated automatically, with a reference to the keymap.
139 161
140 ; Some trickiness, since what 162 The new mode runs the hook constructed by the function
141 ; appears to be the docstring 163 `derived-mode-hook-name'."
142 ; may really be the first 164 (declare (debug (&define name symbolp sexp [&optional stringp]
143 ; element of the body. 165 [&rest keywordp sexp] def-body)))
144 (if (and docstring (not (stringp docstring))) 166
145 (progn (setq body (cons docstring body)) 167 (when (and docstring (not (stringp docstring)))
146 (setq docstring nil))) 168 ;; Some trickiness, since what appears to be the docstring may really be
147 (setq docstring (or docstring (derived-mode-make-docstring parent child))) 169 ;; the first element of the body.
148 170 (push docstring body)
149 `(progn 171 (setq docstring nil))
150 (derived-mode-init-mode-variables (quote ,child)) 172
151 (put (quote ,child) 'derived-mode-parent (quote ,parent)) 173 (when (eq parent 'fundamental-mode) (setq parent nil))
174
175 (let ((map (derived-mode-map-name child))
176 (syntax (derived-mode-syntax-table-name child))
177 (abbrev (derived-mode-abbrev-table-name child))
178 (declare-abbrev t)
179 (declare-syntax t)
180 (hook (derived-mode-hook-name child))
181 (group nil))
182
183 ;; Process the keyword args.
184 (while (keywordp (car body))
185 (case (pop body)
186 (:group (setq group (pop body)))
187 (:abbrev-table (setq abbrev (pop body)) (setq declare-abbrev nil))
188 (:syntax-table (setq syntax (pop body)) (setq declare-syntax nil))
189 (t (pop body))))
190
191 (setq docstring (derived-mode-make-docstring
192 parent child docstring syntax abbrev))
193
194 `(progn
195 (defvar ,hook nil ,(format "Hook run when entering %s mode." name))
196 (defvar ,map (make-sparse-keymap))
197 ,(if declare-syntax
198 `(defvar ,syntax (make-syntax-table)))
199 ,(if declare-abbrev
200 `(defvar ,abbrev
201 (progn (define-abbrev-table ',abbrev nil) ,abbrev)))
202 (put ',child 'derived-mode-parent ',parent)
203 ,(if group `(put ',child 'custom-mode-group ,group))
204
152 (defun ,child () 205 (defun ,child ()
153 ,docstring 206 ,docstring
154 (interactive) 207 (interactive)
155 ; Run the parent. 208 ; Run the parent.
156 (,parent) 209 (delay-mode-hooks
210
211 (,(or parent 'kill-all-local-variables))
212 ; Identify the child mode.
213 (setq major-mode (quote ,child))
214 (setq mode-name ,name)
157 ; Identify special modes. 215 ; Identify special modes.
158 (if (get (quote ,parent) 'special) 216 ,(when parent
159 (put (quote ,child) 'special t)) 217 `(progn
160 ;; XEmacs addition 218 (if (get (quote ,parent) 'mode-class)
161 (let ((mode-class (get (quote ,parent) 'mode-class))) 219 (put (quote ,child) 'mode-class
162 (if mode-class 220 (get (quote ,parent) 'mode-class)))
163 (put (quote ,child) 'mode-class mode-class)))
164 ; Identify the child mode.
165 (setq major-mode (quote ,child))
166 (setq mode-name ,name)
167 ; Set up maps and tables. 221 ; Set up maps and tables.
168 (derived-mode-set-keymap (quote ,child)) 222 (unless (keymap-parent ,map)
169 (derived-mode-set-syntax-table (quote ,child)) 223 (set-keymap-parent ,map (current-local-map)))
170 (derived-mode-set-abbrev-table (quote ,child)) 224 ,(when declare-syntax
225 `(let ((parent (char-table-parent ,syntax)))
226 (unless (and parent
227 (not (eq parent (standard-syntax-table))))
228 (set-char-table-parent ,syntax (syntax-table)))))))
229
230 (use-local-map ,map)
231 ,(when syntax `(set-syntax-table ,syntax))
232 ,(when abbrev `(setq local-abbrev-table ,abbrev))
171 ; Splice in the body (if any). 233 ; Splice in the body (if any).
172 ,@body 234 ,@body
173 ;;; ; Run the setup function, if 235 )
174 ;;; ; any -- this will soon be 236 ;; Run the hooks, if any.
175 ;;; ; obsolete. 237 ;; Make the generated code work in older Emacs versions
176 ;;; (derived-mode-run-setup-function (quote ,child)) 238 ;; that do not yet have run-mode-hooks.
177 ; Run the hooks, if any. 239 (if (fboundp 'run-mode-hooks)
178 (derived-mode-run-hooks (quote ,child))))) 240 (run-mode-hooks ',hook)
179 241 (run-hooks ',hook))))))
180 242
181 ;; PUBLIC: find the ultimate class of a derived mode. 243 ;; PUBLIC: find the ultimate class of a derived mode.
182 244
183 (defun derived-mode-class (mode) 245 (defun derived-mode-class (mode)
184 "Find the class of a major mode. 246 "Find the class of a major MODE.
185 A mode's class is the first ancestor which is NOT a derived mode. 247 A mode's class is the first ancestor which is NOT a derived mode.
186 Use the `derived-mode-parent' property of the symbol to trace backwards." 248 Use the `derived-mode-parent' property of the symbol to trace backwards.
249 Since major-modes might all derive from `fundamental-mode', this function
250 is not very useful."
187 (while (get mode 'derived-mode-parent) 251 (while (get mode 'derived-mode-parent)
188 (setq mode (get mode 'derived-mode-parent))) 252 (setq mode (get mode 'derived-mode-parent)))
189 mode) 253 mode)
254 (make-obsolete 'derived-mode-class 'derived-mode-p)
190 255
191 ;; PUBLIC: find if the current mode derives from another. 256 ;; PUBLIC: find if the current mode derives from another.
192 ;; from GNU Emacs 21 subr.el 257 ;; from GNU Emacs 21 subr.el
193 258
194 (defun derived-mode-p (&rest modes) 259 (defun derived-mode-p (&rest modes)
198 (while (and (not (memq parent modes)) 263 (while (and (not (memq parent modes))
199 (setq parent (get parent 'derived-mode-parent)))) 264 (setq parent (get parent 'derived-mode-parent))))
200 parent)) 265 parent))
201 266
202 267
203 ;; Inline functions to construct various names from a mode name. 268 ;;; PRIVATE
269
270 (defun derived-mode-make-docstring (parent child &optional
271 docstring syntax abbrev)
272 "Construct a docstring for a new mode if none is provided."
273
274 (let ((map (derived-mode-map-name child))
275 (hook (derived-mode-hook-name child)))
276
277 (unless (stringp docstring)
278 ;; Use a default docstring.
279 (setq docstring
280 (if (null parent)
281 (format "Major-mode.
282 Uses keymap `%s', abbrev table `%s' and syntax-table `%s'." map abbrev syntax)
283 (format "Major mode derived from `%s' by `define-derived-mode'.
284 It inherits all of the parent's attributes, but has its own keymap,
285 abbrev table and syntax table:
286
287 `%s', `%s' and `%s'
288
289 which more-or-less shadow %s's corresponding tables."
290 parent map abbrev syntax parent))))
291
292 (unless (string-match (regexp-quote (symbol-name hook)) docstring)
293 ;; Make sure the docstring mentions the mode's hook.
294 (setq docstring
295 (concat docstring
296 (if (null parent)
297 "\n\nThis mode "
298 (concat
299 "\n\nIn addition to any hooks its parent mode "
300 (if (string-match (regexp-quote (format "`%s'" parent))
301 docstring) nil
302 (format "`%s' " parent))
303 "might have run,\nthis mode "))
304 (format "runs the hook `%s'" hook)
305 ", as the final step\nduring initialization.")))
306
307 (unless (string-match "\\\\[{[]" docstring)
308 ;; And don't forget to put the mode's keymap.
309 (setq docstring (concat docstring "\n\n\\{" (symbol-name map) "}")))
310
311 docstring))
312
313
314 ;;; OBSOLETE
315 ;; The functions below are only provided for backward compatibility with
316 ;; code byte-compiled with versions of derived.el prior to Emacs-21.
204 317
205 (defsubst derived-mode-setup-function-name (mode) 318 (defsubst derived-mode-setup-function-name (mode)
206 "Construct a setup-function name based on a mode name." 319 "Construct a setup-function name based on a MODE name."
207 (intern (concat (symbol-name mode) "-setup"))) 320 (intern (concat (symbol-name mode) "-setup")))
208
209 (defsubst derived-mode-hooks-name (mode)
210 "Construct a hooks name based on a mode name."
211 ;; XEmacs change from -hooks
212 (intern (concat (symbol-name mode) "-hook")))
213
214 (defsubst derived-mode-map-name (mode)
215 "Construct a map name based on a mode name."
216 (intern (concat (symbol-name mode) "-map")))
217
218 (defsubst derived-mode-syntax-table-name (mode)
219 "Construct a syntax-table name based on a mode name."
220 (intern (concat (symbol-name mode) "-syntax-table")))
221
222 (defsubst derived-mode-abbrev-table-name (mode)
223 "Construct an abbrev-table name based on a mode name."
224 (intern (concat (symbol-name mode) "-abbrev-table")))
225 321
226 322
227 ;; Utility functions for defining a derived mode. 323 ;; Utility functions for defining a derived mode.
228 324
229 ;; XEmacs -- don't autoload 325 ;; XEmacs -- don't autoload
230 (defun derived-mode-init-mode-variables (mode) 326 (defun derived-mode-init-mode-variables (mode)
231 "Initialize variables for a new mode. 327 "Initialise variables for a new MODE.
232 Right now, if they don't already exist, set up a blank keymap, an 328 Right now, if they don't already exist, set up a blank keymap, an
233 empty syntax table, and an empty abbrev table -- these will be merged 329 empty syntax table, and an empty abbrev table -- these will be merged
234 the first time the mode is used." 330 the first time the mode is used."
235 331
236 (if (boundp (derived-mode-map-name mode)) 332 (if (boundp (derived-mode-map-name mode))
254 (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t)) 350 (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t))
255 351
256 (if (boundp (derived-mode-abbrev-table-name mode)) 352 (if (boundp (derived-mode-abbrev-table-name mode))
257 t 353 t
258 (eval `(defvar ,(derived-mode-abbrev-table-name mode) 354 (eval `(defvar ,(derived-mode-abbrev-table-name mode)
259 (progn (define-abbrev-table (derived-mode-abbrev-table-name mode) nil) 355 (progn
260 (make-abbrev-table)) 356 (define-abbrev-table (derived-mode-abbrev-table-name mode) nil)
357 (make-abbrev-table))
261 ,(format "Abbrev table for %s." mode))))) 358 ,(format "Abbrev table for %s." mode)))))
262
263 (defun derived-mode-make-docstring (parent child)
264 "Construct a docstring for a new mode if none is provided."
265
266 (format "This major mode is a variant of `%s', created by `define-derived-mode'.
267 It inherits all of the parent's attributes, but has its own keymap,
268 abbrev table and syntax table:
269
270 `%s-map' and `%s-syntax-table'
271
272 which more-or-less shadow
273
274 `%s-map' and `%s-syntax-table'
275
276 \\{%s-map}" parent child child parent parent child))
277
278 359
279 ;; Utility functions for running a derived mode. 360 ;; Utility functions for running a derived mode.
280 361
281 (defun derived-mode-set-keymap (mode) 362 (defun derived-mode-set-keymap (mode)
282 "Set the keymap of the new mode, maybe merging with the parent." 363 "Set the keymap of the new MODE, maybe merging with the parent."
283 (let* ((map-name (derived-mode-map-name mode)) 364 (let* ((map-name (derived-mode-map-name mode))
284 (new-map (eval map-name)) 365 (new-map (eval map-name))
285 (old-map (current-local-map))) 366 (old-map (current-local-map)))
286 (and old-map 367 (and old-map
287 (get map-name 'derived-mode-unmerged) 368 (get map-name 'derived-mode-unmerged)
288 (derived-mode-merge-keymaps old-map new-map)) 369 (derived-mode-merge-keymaps old-map new-map))
289 (put map-name 'derived-mode-unmerged nil) 370 (put map-name 'derived-mode-unmerged nil)
290 (use-local-map new-map))) 371 (use-local-map new-map)))
291 372
292 (defun derived-mode-set-syntax-table (mode) 373 (defun derived-mode-set-syntax-table (mode)
293 "Set the syntax table of the new mode, maybe merging with the parent." 374 "Set the syntax table of the new MODE, maybe merging with the parent."
294 (let* ((table-name (derived-mode-syntax-table-name mode)) 375 (let* ((table-name (derived-mode-syntax-table-name mode))
295 (old-table (syntax-table)) 376 (old-table (syntax-table))
296 (new-table (eval table-name))) 377 (new-table (eval table-name)))
297 (if (get table-name 'derived-mode-unmerged) 378 (if (get table-name 'derived-mode-unmerged)
298 (derived-mode-merge-syntax-tables old-table new-table)) 379 (derived-mode-merge-syntax-tables old-table new-table))
299 (put table-name 'derived-mode-unmerged nil) 380 (put table-name 'derived-mode-unmerged nil)
300 (set-syntax-table new-table))) 381 (set-syntax-table new-table)))
301 382
302 (defun derived-mode-set-abbrev-table (mode) 383 (defun derived-mode-set-abbrev-table (mode)
303 "Set the abbrev table if it exists. 384 "Set the abbrev table for MODE if it exists.
304 Always merge its parent into it, since the merge is non-destructive." 385 Always merge its parent into it, since the merge is non-destructive."
305 (let* ((table-name (derived-mode-abbrev-table-name mode)) 386 (let* ((table-name (derived-mode-abbrev-table-name mode))
306 (old-table local-abbrev-table) 387 (old-table local-abbrev-table)
307 (new-table (eval table-name))) 388 (new-table (eval table-name)))
308 (derived-mode-merge-abbrev-tables old-table new-table) 389 (derived-mode-merge-abbrev-tables old-table new-table)
314 ;;; (let ((fname (derived-mode-setup-function-name mode))) 395 ;;; (let ((fname (derived-mode-setup-function-name mode)))
315 ;;; (if (fboundp fname) 396 ;;; (if (fboundp fname)
316 ;;; (funcall fname)))) 397 ;;; (funcall fname))))
317 398
318 (defun derived-mode-run-hooks (mode) 399 (defun derived-mode-run-hooks (mode)
319 "Run the hooks if they exist." 400 "Run the mode hook for MODE."
320 401 (let ((hooks-name (derived-mode-hook-name mode)))
321 (let ((hooks-name (derived-mode-hooks-name mode)))
322 (if (boundp hooks-name) 402 (if (boundp hooks-name)
323 (run-hooks hooks-name)))) 403 (run-hooks hooks-name))))
324 404
325 ;; Functions to merge maps and tables. 405 ;; Functions to merge maps and tables.
326 406
327 (defun derived-mode-merge-keymaps (old new) 407 (defun derived-mode-merge-keymaps (old new)
328 "Merge an old keymap into a new one. 408 "Merge an OLD keymap into a NEW one.
329 The old keymap is set to be the parent of the new one, so that there will 409 The old keymap is set to be the last cdr of the new one, so that there will
330 be automatic inheritance." 410 be automatic inheritance."
331 ;; XEmacs change. FSF 19.30 & 19.34 has a whole bunch of weird crap here 411 ;; XEmacs change. FSF 19.30 to 21.3 has a whole bunch of weird crap here
332 ;; for merging prefix keys and such. Hopefully none of this is 412 ;; for merging prefix keys and such. Hopefully none of this is
333 ;; necessary in XEmacs. 413 ;; necessary in XEmacs.
334 (set-keymap-parents new (list old))) 414 (set-keymap-parents new (list old)))
335 415
336 (defun derived-mode-merge-syntax-tables (old new) 416 (defun derived-mode-merge-syntax-tables (old new)
337 "Merge an old syntax table into a new one. 417 "Merge an OLD syntax table into a NEW one.
338 Where the new table already has an entry, nothing is copied from the old one." 418 Where the new table already has an entry, nothing is copied from the old one."
339 ;; 20.x 419 ;; XEmacs change: on the other hand, Emacs 21.3 just has
340 (if (fboundp 'map-char-table) 420 ;; (set-char-table-parent new old) here.
341 ;; we use map-char-table not map-syntax-table so we can explicitly 421 ;; We use map-char-table, not map-syntax-table, so we can explicitly
342 ;; check for inheritance. 422 ;; check for inheritance.
343 (map-char-table 423 (map-char-table
344 #'(lambda (key value) 424 #'(lambda (key value)
345 (let ((newval (get-range-char-table key new 'multi))) 425 (let ((newval (get-range-char-table key new 'multi)))
346 (cond ((eq newval 'multi) ; OK, dive into the class hierarchy 426 (cond ((eq newval 'multi) ; OK, dive into the class hierarchy
347 (map-char-table 427 (map-char-table
348 #'(lambda (key1 value1) 428 #'(lambda (key1 value1)
349 (when (eq ?@ (char-syntax-from-code 429 (when (eq ?@ (char-syntax-from-code
350 (get-range-char-table key new ?@))) 430 (get-range-char-table key new ?@)))
351 (put-char-table key1 value new)) 431 (put-char-table key1 value new))
352 nil) 432 nil)
353 new 433 new
354 key)) 434 key))
355 ((eq ?@ (char-syntax-from-code newval)) ;; class at once 435 ((eq ?@ (char-syntax-from-code newval)) ;; class at once
356 (put-char-table key value new)))) 436 (put-char-table key value new))))
357 nil) 437 nil)
358 old) 438 old))
359 ;; pre-20.0
360 (let ((idx 0)
361 (end (min (length new) (length old))))
362 (while (< idx end)
363 (if (not (aref new idx))
364 (aset new idx (aref old idx)))
365 (setq idx (1+ idx))))))
366 439
367 ;; Merge an old abbrev table into a new one. 440 ;; Merge an old abbrev table into a new one.
368 ;; This function requires internal knowledge of how abbrev tables work, 441 ;; This function requires internal knowledge of how abbrev tables work,
369 ;; presuming that they are obarrays with the abbrev as the symbol, the expansion 442 ;; presuming that they are obarrays with the abbrev as the symbol, the expansion
370 ;; as the value of the symbol, and the hook as the function definition. 443 ;; as the value of the symbol, and the hook as the function definition.
371 (defun derived-mode-merge-abbrev-tables (old new) 444 (defun derived-mode-merge-abbrev-tables (old new)
372 (if old 445 (if old
373 (mapatoms 446 (mapatoms
374 (function 447 #'(lambda (symbol)
375 (lambda (symbol) 448 (or (intern-soft (symbol-name symbol) new)
376 (or (intern-soft (symbol-name symbol) new) 449 (define-abbrev new (symbol-name symbol)
377 (define-abbrev new (symbol-name symbol) 450 (symbol-value symbol) (symbol-function symbol))))
378 (symbol-value symbol) (symbol-function symbol)))))
379 old))) 451 old)))
380 452
381 (provide 'derived) 453 (provide 'derived)
382 454
455 ;;; arch-tag: 630be248-47d1-4f02-afa0-8207de0ebea0
383 ;;; derived.el ends here 456 ;;; derived.el ends here