Use completion-at-point rather than completion-in-region.
[bpt/emacs.git] / lisp / progmodes / meta-mode.el
CommitLineData
bcd70d97 1;;; meta-mode.el --- major mode for editing Metafont or MetaPost sources -*- lexical-binding:t -*-
6b279740 2
73b0cd50 3;; Copyright (C) 1997, 2001-2011 Free Software Foundation, Inc.
6b279740
RS
4
5;; Author: Ulrik Vieth <vieth@thphy.uni-duesseldorf.de>
6;; Version: 1.0
7;; Keywords: Metafont, MetaPost, tex, languages
8
1eadb66c 9;; This file is part of GNU Emacs.
6b279740 10
b1fc2b50 11;; GNU Emacs is free software: you can redistribute it and/or modify
6b279740 12;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
6b279740 15
1eadb66c 16;; GNU Emacs is distributed in the hope that it will be useful,
6b279740
RS
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
b1fc2b50 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
6b279740
RS
23
24;;; Commentary:
25
26;; Description:
27;;
28;; This Emacs Lisp package provides a major mode for editing Metafont
29;; or MetaPost sources. It includes all the necessary code to set up
30;; a major mode including an approriate syntax table, keymap, and a
31;; mode-specific pull-down menu. It also provides a sophisticated set
32;; of font-lock patterns, a fancy indentation function adapted from
818226ac 33;; AUCTeX's latex.el, and some basic mode-specific editing functions
6b279740
RS
34;; such as functions to move to the beginning or end of the enclosing
35;; environment, or to mark, re-indent, or comment-out environments.
36;; On the other hand, it doesn't yet provide any functionality for
37;; running Metafont or MetaPost in a shell buffer form within Emacs,
38;; but such functionality might be added later, either as part of this
39;; package or as a separate Emacs Lisp package.
40
41;; Installation:
a1506d29 42;;
6b279740
RS
43;; An interface to running Metafont or MetaPost as a shell process
44;; from within Emacs is currently under development as a separate
45;; Emacs Lisp package (meta-buf.el). In order to have that package
46;; loaded automatically when first entering Metafont or MetaPost mode,
47;; you might use the load-hook provided in this package by adding
48;; these lines to your startup file:
a1506d29
JB
49;;
50;; (add-hook 'meta-mode-load-hook
8a4c5051 51;; (lambda () (require 'meta-buf)))
6b279740
RS
52;;
53;; The add-on package loaded this way may in turn make use of the
54;; mode-hooks provided in this package to activate additional features
55;; when entering Metafont or MetaPost mode.
56
57;; Font Lock Support:
58;;
59;; If you are using global-font-lock-mode (introduced in Emacs 19.31),
60;; fontification in Metafont and/or MetaPost mode will be activated
61;; automatically. To speed up fontification for the rather complex
62;; patterns used in these modes, it may be a good idea to activate
63;; lazy-lock as a font-lock-support-mode (introduced in Emacs 19.32)
64;; by adding these lines to your startup file:
65;;
66;; (global-font-lock-mode t)
67;; (setq font-lock-support-mode 'lazy-lock-mode)
68;;
69;; If you are using an older version of Emacs, which doesn't provide
70;; global-font-lock-mode or font-lock-support-mode, you can also
71;; activate fontification in Metafont and/or MetaPost mode by adding
72;; the following lines to your startup file:
a1506d29 73;;
6b279740
RS
74;; (add-hook 'meta-common-mode-hook 'turn-on-font-lock)
75;; (add-hook 'meta-common-mode-hook 'turn-on-lazy-lock)
76
77;; Customization:
78;;
79;; Following the usual Emacs Lisp coding conventions, the major modes
80;; defined in this package provide several hook variables to allow for
81;; local customization when entering the modes. In particular, there
82;; is a `meta-common-mode-hook' which applies to both modes as well as
83;; `metafont-mode-hook' and `metapost-mode-hook' which apply to the
84;; individual modes. In addition, there are several variables and
85;; regexps controlling e.g. the behavior of the indentation function,
86;; which may be customized via `edit-options'. Please refer to the
87;; docstrings in the code below for details.
88
89;; Availability:
90;;
91;; This package is currently available via my "TeX Software" WWW page:
92;;
93;; http://www.thphy.uni-duesseldorf.de/~vieth/subjects/tex/software.html
94;;
95;; As of this version 1.0, this package will be uploaded to CTAN
96;; archives, where it shall find a permanent home, presumably in
97;; tex-archive/support/emacs-modes. It will also be submitted for
98;; integration into the GNU Emacs distribution at that time.
99;;
100;; History:
101;;
102;; v 0.0 -- 1997/02/01 UV Started writing meta-mode.el.
103;; v 0.1 -- 1997/02/02 UV Added preliminary set of font-lock patterns.
104;; v 0.2 -- 1997/02/03 UV Improved and debugged font-lock patterns.
105;; Added indent-line-function for TAB.
106;; v 0.3 -- 1997/02/17 UV Improved font-lock patterns and syntax table.
107;; Improved and debbuged indentation function.
108;; v 0.4 -- 1997/02/18 UV Added functions to indent regions for M-C-q,
109;; also added a preliminary mode-specific menu.
a1506d29 110;; v 0.5 -- 1997/02/19 UV Added functions to skip to next or previous
6b279740
RS
111;; defun and to re-indent or comment-out defuns.
112;; v 0.6 -- 1997/02/20 UV More debugging, testing and clean-up.
113;; v 0.7 -- 1997/02/22 UV Use easymenu to define mode-specific menu.
114;; v 0.8 -- 1997/02/24 UV Added completion function for M-TAB.
115;; v 0.9 -- 1997/03/08 UV Added fill-paragraph function for comments.
116;; Also fixed a few remaining font-lock problems.
117;; Added meta-mode-load-hook to load meta-buf.el.
118;; v 1.0 -- 1997/04/07 UV Cleanup for official public release.
119;;
120;; Historical Footnote:
121;;
122;; This package was begun on February 1, 1997, exactly 20 years after
123;; the genesis of TeX took place according to Don Knuth's own account
ff319790 124;; (cf. ``The Errors of TeX'', reprinted in ``Literate Programming'',
6b279740
RS
125;; Chapter 10, p. 249). What better date could there be to choose?
126;;
127
128\f
129;;; Code:
130
131(require 'easymenu)
132
28d16ed3
AS
133(defgroup meta-font nil
134 "Major mode for editing Metafont or MetaPost sources."
8ec3bce0 135 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
28d16ed3
AS
136 :group 'languages)
137
6b279740
RS
138;;; Fontification.
139
140(defvar meta-font-lock-keywords
141 (let ((input-keywords
142 "\\(input\\|generate\\)")
143 (begin-keywords
144 (concat "\\(begin\\(char\\|fig\\|graph\\|logochar\\)\\|"
145 "\\cmchar\\|dcchar\\|ecchar\\)"))
146 (end-keywords
147 "\\(end\\(char\\|fig\\|graph\\)\\)")
148 (macro-keywords-1
149 "\\(def\\|let\\|mode_def\\|vardef\\)")
150 (macro-keywords-2
151 "\\(primarydef\\|secondarydef\\|tertiarydef\\)")
152;(make-regexp
153; '("expr" "suffix" "text" "primary" "secondary" "tertiary") t)
154 (args-keywords
155 (concat "\\(expr\\|primary\\|s\\(econdary\\|uffix\\)\\|"
156 "te\\(rtiary\\|xt\\)\\)"))
157;(make-regexp
158; '("boolean" "color" "numeric" "pair" "path" "pen" "picture"
159; "string" "transform" "newinternal") t)
160 (type-keywords
161 (concat "\\(boolean\\|color\\|n\\(ewinternal\\|umeric\\)\\|"
162 "p\\(a\\(ir\\|th\\)\\|en\\|icture\\)\\|string\\|"
163 "transform\\)"))
164;(make-regexp
165; '("for" "forever" "forsuffixes" "endfor"
166; "step" "until" "upto" "downto" "thru" "within"
167; "iff" "if" "elseif" "else" "fi" "exitif" "exitunless"
168; "let" "def" "vardef" "enddef" "mode_def"
169; "true" "false" "known" "unknown" "and" "or" "not"
170; "save" "interim" "inner" "outer" "relax"
171; "begingroup" "endgroup" "expandafter" "scantokens"
172; "generate" "input" "endinput" "end" "bye"
173; "message" "errmessage" "errhelp" "special" "numspecial"
174; "readstring" "readfrom" "write") t)
175 (syntactic-keywords
176 (concat "\\(and\\|b\\(egingroup\\|ye\\)\\|"
177 "d\\(ef\\|ownto\\)\\|e\\(lse\\(\\|if\\)"
178 "\\|nd\\(\\|def\\|for\\|group\\|input\\)"
179 "\\|rr\\(help\\|message\\)"
180 "\\|x\\(it\\(if\\|unless\\)\\|pandafter\\)\\)\\|"
181 "f\\(alse\\|i\\|or\\(\\|ever\\|suffixes\\)\\)\\|"
182 "generate\\|i\\(ff?\\|n\\(ner\\|put\\|terim\\)\\)\\|"
183 "known\\|let\\|m\\(essage\\|ode_def\\)\\|"
184 "n\\(ot\\|umspecial\\)\\|o\\(r\\|uter\\)\\|"
185 "re\\(ad\\(from\\|string\\)\\|lax\\)\\|"
186 "s\\(ave\\|cantokens\\|pecial\\|tep\\)\\|"
187 "t\\(hru\\|rue\\)\\|"
188 "u\\(n\\(known\\|til\\)\\|pto\\)\\|"
189 "vardef\\|w\\(ithin\\|rite\\)\\)"))
190 )
191 (list
192 ;; embedded TeX code in btex ... etex
193 (cons (concat "\\(btex\\|verbatimtex\\)"
89c19c1e 194 "[ \t\f]+\\(.*\\)[ \t\f]+"
6b279740
RS
195 "\\(etex\\)")
196 '((1 font-lock-keyword-face)
197 (2 font-lock-string-face)
198 (3 font-lock-keyword-face)))
199 ;; unary macro definitions: def, vardef, let
200 (cons (concat "\\<" macro-keywords-1 "\\>"
89c19c1e 201 "[ \t\f]+\\(\\sw+\\|\\s_+\\|\\s.+\\)")
6b279740
RS
202 '((1 font-lock-keyword-face)
203 (2 font-lock-function-name-face)))
204 ;; binary macro defintions: <leveldef> x operator y
205 (cons (concat "\\<" macro-keywords-2 "\\>"
89c19c1e
MC
206 "[ \t\f]+\\(\\sw+\\)"
207 "[ \t\f]*\\(\\sw+\\|\\s.+\\)"
208 "[ \t\f]*\\(\\sw+\\)")
6b279740
RS
209 '((1 font-lock-keyword-face)
210 (2 font-lock-variable-name-face nil t)
211 (3 font-lock-function-name-face nil t)
212 (4 font-lock-variable-name-face nil t)))
213 ;; variable declarations: numeric, pair, color, ...
214 (cons (concat "\\<" type-keywords "\\>"
89c19c1e 215 "\\([ \t\f]+\\(\\sw+\\)\\)*")
6b279740
RS
216 '((1 font-lock-type-face)
217 (font-lock-match-meta-declaration-item-and-skip-to-next
218 (goto-char (match-end 1)) nil
219 (1 font-lock-variable-name-face nil t))))
220 ;; argument declarations: expr, suffix, text, ...
221 (cons (concat "\\<" args-keywords "\\>"
89c19c1e 222 "\\([ \t\f]+\\(\\sw+\\|\\s_+\\)\\)*")
6b279740
RS
223 '((1 font-lock-type-face)
224 (font-lock-match-meta-declaration-item-and-skip-to-next
225 (goto-char (match-end 1)) nil
226 (1 font-lock-variable-name-face nil t))))
227 ;; special case of arguments: expr x of y
89c19c1e
MC
228 (cons (concat "\\(expr\\)[ \t\f]+\\(\\sw+\\)"
229 "[ \t\f]+\\(of\\)[ \t\f]+\\(\\sw+\\)")
6b279740
RS
230 '((1 font-lock-type-face)
231 (2 font-lock-variable-name-face)
232 (3 font-lock-keyword-face nil t)
233 (4 font-lock-variable-name-face nil t)))
234 ;; syntactic keywords
235 (cons (concat "\\<" syntactic-keywords "\\>")
236 'font-lock-keyword-face)
237 ;; beginchar, beginfig
238 (cons (concat "\\<" begin-keywords "\\>")
239 'font-lock-keyword-face)
240 ;; endchar, endfig
241 (cons (concat "\\<" end-keywords "\\>")
242 'font-lock-keyword-face)
243 ;; input, generate
244 (cons (concat "\\<" input-keywords "\\>"
89c19c1e 245 "[ \t\f]+\\(\\sw+\\)")
6b279740 246 '((1 font-lock-keyword-face)
883212ce 247 (2 font-lock-constant-face)))
6b279740 248 ;; embedded Metafont/MetaPost code in comments
a1506d29 249 (cons "|\\([^|]+\\)|"
883212ce 250 '(1 font-lock-constant-face t))
6b279740
RS
251 ))
252 "Default expressions to highlight in Metafont or MetaPost mode.")
253
254
255(defun font-lock-match-meta-declaration-item-and-skip-to-next (limit)
256 ;; Match and move over Metafont/MetaPost declaration item after point.
257 ;;
258 ;; The expected syntax of an item is either "word" or "symbol",
259 ;; possibly ending with optional whitespace. Everything following
260 ;; the item (but belonging to it) is expected to by skipable by
261 ;; `forward-sexp'. The list of items is expected to be separated
262 ;; by commas and terminated by semicolons or equals signs.
263 ;;
89c19c1e 264 (if (looking-at "[ \t\f]*\\(\\sw+\\|\\s_+\\)")
6b279740
RS
265 (save-match-data
266 (condition-case nil
267 (save-restriction
268 ;; Restrict to end of line, currently guaranteed to be LIMIT.
269 (narrow-to-region (point-min) limit)
270 (goto-char (match-end 1))
271 ;; Move over any item value, etc., to the next item.
89c19c1e 272 (while (not (looking-at "[ \t\f]*\\(\\(,\\)\\|;\\|=\\|$\\)"))
6b279740
RS
273 (goto-char (or (scan-sexps (point) 1) (point-max))))
274 (goto-char (match-end 2)))
275 (error t)))))
276
277
278\f
279;;; Completion.
280
281;; The data used to prepare the following lists of primitives and
282;; standard macros available in Metafont or MetaPost was extracted
283;; from the original sources like this:
284;;
285;; grep '^primitive' texk-7.0/web2c/{mf,mp}.web |\
286;; sed 's/primitive(\("[a-zA-Z]*"\).*/\1/' > {mf,mp}_prim.list
287;;
a1506d29 288;; grep '\(let\|def\|vardef\|primarydef\|secondarydef\|tertiarydef\)'
6b279740
RS
289;; texmf/meta{font,post}/plain.{mf,mp} > {mf,mp}_plain.list
290
a1506d29 291(defconst meta-common-primitives-list
6b279740
RS
292 '("ASCII" "addto" "also" "and" "angle" "atleast" "batchmode"
293 "begingroup" "boolean" "boundarychar" "char" "charcode" "chardp"
294 "charexists" "charext" "charht" "charic" "charlist" "charwd"
295 "contour" "controls" "cosd" "curl" "cycle" "day" "decimal" "def"
296 "delimiters" "designsize" "directiontime" "doublepath" "dump" "else"
297 "elseif" "end" "enddef" "endfor" "endgroup" "endinput" "errhelp"
298 "errmessage" "errorstopmode" "everyjob" "exitif" "expandafter"
299 "expr" "extensible" "false" "fi" "floor" "fontdimen" "fontmaking"
300 "for" "forever" "forsuffixes" "headerbyte" "hex" "if" "inner"
301 "input" "interim" "intersectiontimes" "jobname" "kern" "known"
302 "length" "let" "ligtable" "makepath" "makepen" "message" "mexp"
303 "mlog" "month" "newinternal" "nonstopmode" "normaldeviate" "not"
304 "nullpen" "nullpicture" "numeric" "oct" "odd" "of" "or" "outer"
305 "pair" "path" "pausing" "pen" "pencircle" "penoffset" "picture"
306 "point" "postcontrol" "precontrol" "primary" "primarydef" "quote"
307 "randomseed" "readstring" "reverse" "rotated" "save" "scaled"
308 "scantokens" "scrollmode" "secondary" "secondarydef" "shifted"
309 "shipout" "show" "showdependencies" "showstats" "showstopping"
310 "showtoken" "showvariable" "sind" "skipto" "slanted" "special"
311 "sqrt" "step" "str" "string" "subpath" "substring" "suffix"
312 "tension" "tertiary" "tertiarydef" "text" "time" "to"
313 "tracingcapsules" "tracingchoices" "tracingcommands"
314 "tracingequations" "tracingmacros" "tracingonline" "tracingoutput"
315 "tracingrestores" "tracingspecs" "tracingstats" "tracingtitles"
316 "transform" "transformed" "true" "turningnumber" "uniformdeviate"
317 "unknown" "until" "vardef" "warningcheck" "withpen" "xpart"
318 "xscaled" "xxpart" "xypart" "year" "ypart" "yscaled" "yxpart"
a1506d29 319 "yypart" "zscaled")
6b279740
RS
320 "List of primitives common to Metafont and MetaPost.")
321
a1506d29 322(defconst metafont-primitives-list
6b279740
RS
323 '("at" "autorounding" "chardx" "chardy" "cull" "display"
324 "dropping" "fillin" "from" "granularity" "hppp" "inwindow"
325 "keeping" "numspecial" "openwindow" "proofing" "smoothing"
326 "totalweight" "tracingedges" "tracingpens" "turningcheck" "vppp"
327 "withweight" "xoffset" "yoffset")
328 "List of primitives only defined in Metafont.")
329
a1506d29 330(defconst metapost-primitives-list
6b279740
RS
331 '("arclength" "arctime" "bluepart" "bounded" "btex" "clip"
332 "clipped" "color" "dashed" "dashpart" "etex" "filled" "fontpart"
333 "fontsize" "greenpart" "infont" "linecap" "linejoin" "llcorner"
334 "lrcorner" "miterlimit" "mpxbreak" "pathpart" "penpart"
335 "prologues" "readfrom" "redpart" "setbounds" "stroked" "textpart"
336 "textual" "tracinglostchars" "truecorners" "ulcorner" "urcorner"
337 "verbatimtex" "withcolor" "within" "write")
338 "List of primitives only defined in MetaPost.")
339
a1506d29 340(defconst meta-common-plain-macros-list
6b279740
RS
341 '( "abs" "bot" "bye" "byte" "ceiling" "clear_pen_memory"
342 "clearit" "clearpen" "clearxy" "counterclockwise" "cutdraw" "decr"
343 "dir" "direction" "directionpoint" "div" "dotprod" "downto" "draw"
344 "drawdot" "erase" "exitunless" "fill" "filldraw" "flex" "gobble"
345 "hide" "incr" "interact" "interpath" "intersectionpoint" "inverse"
346 "label" "labels" "lft" "loggingall" "magstep" "makelabel" "max"
347 "min" "mod" "numtok" "penlabels" "penpos" "penstroke" "pickup"
348 "range" "reflectedabout" "relax" "rotatedabout" "rotatedaround"
349 "round" "rt" "savepen" "shipit" "softjoin" "solve" "stop"
350 "superellipse" "takepower" "tensepath" "thru" "top" "tracingall"
351 "tracingnone" "undraw" "undrawdot" "unfill" "unfilldraw"
352 "unitvector" "upto" "whatever")
353 "List of macros common to plain Metafont and MetaPost.")
354
a1506d29 355(defconst metafont-plain-macros-list
6b279740
RS
356 '("beginchar" "change_width" "culldraw" "cullit" "cutoff"
357 "define_blacker_pixels" "define_corrected_pixels"
358 "define_good_x_pixels" "define_good_y_pixels"
359 "define_horizontal_corrected_pixels" "define_pixels"
360 "define_whole_blacker_pixels" "define_whole_pixels"
361 "define_whole_vertical_blacker_pixels"
362 "define_whole_vertical_pixels" "endchar" "fix_units"
363 "font_coding_scheme" "font_extra_space" "font_identifier"
364 "font_normal_shrink" "font_normal_space" "font_normal_stretch"
365 "font_quad" "font_size" "font_slant" "font_x_height" "gfcorners"
366 "good.bot" "good.lft" "good.rt" "good.top" "good.x" "good.y"
367 "grayfont" "hround" "imagerules" "italcorr" "labelfont"
368 "lowres_fix" "makebox" "makegrid" "maketicks" "mode_lowres"
369 "mode_proof" "mode_setup" "mode_smoke" "nodisplays" "notransforms"
370 "openit" "penrazor" "pensquare" "proofoffset" "proofrule"
371 "proofrulethickness" "screenchars" "screenrule" "screenstrokes"
a1506d29 372 "showit" "slantfont" "smode" "titlefont" "vround")
6b279740
RS
373 "List of macros only defined in plain Metafont.")
374
a1506d29 375(defconst metapost-plain-macros-list
6b279740
RS
376 '("arrowhead" "bbox" "beginfig" "buildcycle" "center" "cutafter"
377 "cutbefore" "dashpattern" "dotlabel" "dotlabels" "drawarrow"
378 "drawdblarrow" "drawoptions" "endfig" "image" "label" "off" "on"
a1506d29 379 "thelabel")
6b279740
RS
380 "List of macros only defined in plain MetaPost.")
381
a1506d29
JB
382(defconst metapost-graph-macros-list
383 '("augment" "auto.x" "auto.y" "autogrid" "begingraph" "endgraph"
384 "format" "frame" "gdata" "gdotlabel" "gdraw" "gdrawarrow"
385 "gdrawdblarrow" "gfill" "glabel" "grid" "itick" "otick" "plot"
6b279740
RS
386 "setcoords" "setrange")
387 "List of macros only defined in MetaPost \"graph\" package.")
a1506d29
JB
388
389(defconst metapost-boxes-macros-list
6b279740
RS
390 '("boxit" "boxjoin" "bpath" "circleit" "drawboxed" "drawboxes"
391 "drawunboxed" "fixpos" "fixsize" "pic" "rboxit")
392 "List of macros only defined in MetaPost \"boxes\" package.")
393
394
395(defvar metafont-symbol-list
396 (append meta-common-primitives-list
397 metafont-primitives-list
398 meta-common-plain-macros-list
399 metafont-plain-macros-list)
400 "List of known symbols to complete in Metafont mode.")
401
402(defvar metapost-symbol-list
403 (append meta-common-primitives-list
404 metapost-primitives-list
405 meta-common-plain-macros-list
406 metapost-plain-macros-list
407 metapost-graph-macros-list
408 metapost-boxes-macros-list)
409 "List of known symbols to complete in MetaPost mode.")
410
411
412(defvar meta-symbol-list nil
413 "List of known symbols to complete in Metafont or MetaPost mode.")
414
a1506d29 415(defvar meta-symbol-changed nil
6b279740
RS
416 "Flag indicating whether `meta-symbol-list' has been initialized.")
417
418(defvar meta-complete-list nil
419; (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
420; (list "" 'ispell-complete-word))
421 "List of ways to perform completion in Metafont or MetaPost mode.
422
423Each entry is a list with the following elements:
4241. Regexp matching the preceding text.
4252. A number indicating the subgroup in the regexp containing the text.
4263. A function returning an alist of possible completions.
4274. Text to append after a succesful completion (if any).
428
429Or alternatively:
4301. Regexp matching the preceding text.
4312. Function to do the actual completion.")
432
433
434(defun meta-add-symbols (&rest entries)
435 "Add entries to list of known symbols in Metafont or MetaPost mode."
436 (if meta-symbol-changed
437 (setq meta-symbol-list (cons entries meta-symbol-list))
438 (setq meta-symbol-changed t)
439 (setq meta-symbol-list (cons entries meta-symbol-list))))
440
441(defun meta-symbol-list ()
442 "Return value of list of known symbols in Metafont or MetaPost mode.
443If the list was changed, sort the list and remove duplicates first."
444 (if (not meta-symbol-changed)
445 ()
446 (setq meta-symbol-changed nil)
447 (message "Preparing completion list...")
448 ;; sort list of symbols
449 (setq meta-symbol-list
450 (sort (mapcar 'meta-listify (apply 'append meta-symbol-list))
451 'meta-car-string-lessp))
452 ;; remove duplicates
453 (let ((entry meta-symbol-list))
454 (while (and entry (cdr entry))
455 (let ((this (car entry))
456 (next (car (cdr entry))))
457 (if (not (string-equal (car this) (car next)))
458 (setq entry (cdr entry))
459 (if (> (length next) (length this))
460 (setcdr this (cdr next)))
461 (setcdr entry (cdr (cdr entry)))))))
462 (message "Preparing completion list... done"))
463 meta-symbol-list)
464
465(defun meta-listify (a)
466 ;; utility function used in `meta-add-symbols'
467 (if (listp a) a (list a)))
468
469(defun meta-car-string-lessp (a b)
470 ;; utility function used in `meta-add-symbols'
471 (string-lessp (car a) (car b)))
472
473
bcd70d97 474(defun meta-completions-at-point ()
6b279740
RS
475 (let ((list meta-complete-list)
476 entry)
477 (while list
478 (setq entry (car list)
479 list (cdr list))
bcd70d97 480 (if (looking-back (car entry) (max (point-min) (- (point) 200)))
6b279740
RS
481 (setq list nil)))
482 (if (numberp (nth 1 entry))
483 (let* ((sub (nth 1 entry))
484 (close (nth 3 entry))
485 (begin (match-beginning sub))
486 (end (match-end sub))
d6b8d4e7 487 (list (funcall (nth 2 entry))))
bcd70d97
SM
488 (list
489 begin end list
490 :exit-function
491 (unless (zerop (length close))
492 (lambda (_s finished)
493 (when (memq finished '(sole finished))
494 (if (looking-at (regexp-quote close))
495 (goto-char (match-end 0))
496 (insert close)))))))
497 (nth 1 entry))))
498
499(define-obsolete-function-alias 'meta-complete-symbol
500 'completion-at-point "24.1")
6b279740
RS
501\f
502;;; Indentation.
503
28d16ed3 504(defcustom meta-indent-level 2
3406534c 505 "Indentation of begin-end blocks in Metafont or MetaPost mode."
28d16ed3
AS
506 :type 'integer
507 :group 'meta-font)
6b279740
RS
508
509
28d16ed3 510(defcustom meta-left-comment-regexp "%%+"
3406534c 511 "Regexp matching comments that should be placed on the left margin."
28d16ed3
AS
512 :type 'regexp
513 :group 'meta-font)
6b279740 514
28d16ed3 515(defcustom meta-right-comment-regexp nil
3406534c 516 "Regexp matching comments that should be placed to the right margin."
28d16ed3
AS
517 :type '(choice regexp
518 (const :tag "None" nil))
519 :group 'meta-font)
6b279740 520
28d16ed3 521(defcustom meta-ignore-comment-regexp "%[^%]"
3406534c 522 "Regexp matching comments that whose indentation should not be touched."
28d16ed3
AS
523 :type 'regexp
524 :group 'meta-font)
6b279740
RS
525
526
28d16ed3 527(defcustom meta-begin-environment-regexp
6b279740
RS
528 (concat "\\(begin\\(char\\|fig\\|gr\\(aph\\|oup\\)\\|logochar\\)\\|"
529 "def\\|for\\(\\|ever\\|suffixes\\)\\|if\\|mode_def\\|"
530 "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)")
3406534c 531 "Regexp matching the beginning of environments to be indented."
28d16ed3
AS
532 :type 'regexp
533 :group 'meta-font)
6b279740 534
28d16ed3 535(defcustom meta-end-environment-regexp
6b279740
RS
536 (concat "\\(end\\(char\\|def\\|f\\(ig\\|or\\)\\|gr\\(aph\\|oup\\)\\)"
537 "\\|fi\\)")
3406534c 538 "Regexp matching the end of environments to be indented."
28d16ed3
AS
539 :type 'regexp
540 :group 'meta-font)
6b279740 541
28d16ed3 542(defcustom meta-within-environment-regexp
6b279740
RS
543; (concat "\\(e\\(lse\\(\\|if\\)\\|xit\\(if\\|unless\\)\\)\\)")
544 (concat "\\(else\\(\\|if\\)\\)")
3406534c 545 "Regexp matching keywords within environments not to be indented."
28d16ed3
AS
546 :type 'regexp
547 :group 'meta-font)
6b279740
RS
548
549
550(defun meta-comment-indent ()
551 "Return the indentation for a comment in Metafont or MetaPost mode."
552 (if (and meta-left-comment-regexp
553 (looking-at meta-left-comment-regexp))
554 (current-column)
89c19c1e 555 (skip-chars-backward "\t\f ")
a1506d29 556 (max (if (bolp) 0 (1+ (current-column)))
6b279740
RS
557 comment-column)))
558
559(defun meta-indent-line ()
560 "Indent the line containing point as Metafont or MetaPost source."
561 (interactive)
562 (let ((indent (meta-indent-calculate)))
e814121e
GM
563 (if (/= (current-indentation) indent)
564 (save-excursion
565 (delete-region (line-beginning-position)
566 (progn (back-to-indentation) (point)))
567 (indent-to indent)))
6b279740
RS
568 (if (< (current-column) indent)
569 (back-to-indentation))))
570
571(defun meta-indent-calculate ()
572 "Return the indentation of current line of Metafont or MetaPost source."
8a4c5051
MC
573 ;; Indentation within strings is not considered as Meta* don't allow multi
574 ;; line strings.
6b279740
RS
575 (save-excursion
576 (back-to-indentation)
a1506d29 577 (cond
8a4c5051 578 ;; Comments to the left margin.
6b279740
RS
579 ((and meta-left-comment-regexp
580 (looking-at meta-left-comment-regexp))
581 0)
8a4c5051 582 ;; Comments to the right margin.
6b279740
RS
583 ((and meta-right-comment-regexp
584 (looking-at meta-right-comment-regexp))
585 comment-column)
586 ;; Comments best left alone.
a1506d29 587 ((and meta-ignore-comment-regexp
6b279740
RS
588 (looking-at meta-ignore-comment-regexp))
589 (current-indentation))
8a4c5051
MC
590 ;; Beginning of buffer.
591 ((eq (point-at-bol) (point-min))
592 0)
6b279740 593 ;; Backindent at end of environments.
8a4c5051 594 ((meta-indent-looking-at-code
6b279740 595 (concat "\\<" meta-end-environment-regexp "\\>"))
8a4c5051 596 (- (meta-indent-current-indentation) meta-indent-level))
6b279740 597 ;; Backindent at keywords within environments.
8a4c5051 598 ((meta-indent-looking-at-code
6b279740 599 (concat "\\<" meta-within-environment-regexp "\\>"))
8a4c5051
MC
600 (- (meta-indent-current-indentation) meta-indent-level))
601 (t (meta-indent-current-indentation)))))
602
603(defun meta-indent-in-string-p ()
604 "Tell if the point is in a string."
605 (or (nth 3 (syntax-ppss))
606 (eq (get-text-property (point) 'face) font-lock-string-face)))
607
608(defun meta-indent-looking-at-code (regexp)
609 "Same as `looking-at' but checks that the point is not in a string."
610 (unless (meta-indent-in-string-p)
611 (looking-at regexp)))
612
613(defun meta-indent-previous-line ()
614 "Go to the previous line of code, skipping comments."
89c19c1e 615 (skip-chars-backward "\n\t\f ")
8a4c5051
MC
616 (move-to-column (current-indentation))
617 ;; Ignore comments.
618 (while (and (looking-at comment-start) (not (bobp)))
89c19c1e 619 (skip-chars-backward "\n\t\f ")
ebd3fa6b
MC
620 (when (not (bobp))
621 (move-to-column (current-indentation)))))
8a4c5051
MC
622
623(defun meta-indent-unfinished-line ()
624 "Tell if the current line of code ends with an unfinished expression."
625 (save-excursion
626 (end-of-line)
627 ;; Skip backward the comments.
ebd3fa6b
MC
628 (let ((point-not-in-string (point)))
629 (while (search-backward comment-start (point-at-bol) t)
630 (unless (meta-indent-in-string-p)
631 (setq point-not-in-string (point))))
632 (goto-char point-not-in-string))
8a4c5051
MC
633 ;; Search for the end of the previous expression.
634 (if (search-backward ";" (point-at-bol) t)
635 (progn (while (and (meta-indent-in-string-p)
636 (search-backward ";" (point-at-bol) t)))
637 (if (= (char-after) ?\;)
638 (forward-char)
639 (beginning-of-line)))
640 (beginning-of-line))
641 ;; See if the last statement of the line is environment-related,
642 ;; or exists at all.
643 (if (meta-indent-looking-at-code
89c19c1e 644 (concat "[ \t\f]*\\($\\|" (regexp-quote comment-start)
8a4c5051
MC
645 "\\|\\<" meta-end-environment-regexp "\\>"
646 "\\|\\<" meta-begin-environment-regexp "\\>"
647 "\\|\\<" meta-within-environment-regexp "\\>\\)"))
648 nil
649 t)))
650
651(defun meta-indent-current-indentation ()
652 "Return the indentation wanted for the current line of code."
653 (+ (meta-indent-current-nesting)
654 (if (save-excursion
655 (back-to-indentation)
656 (and (not (looking-at (concat "\\<" meta-end-environment-regexp "\\>"
657 "\\|\\<" meta-within-environment-regexp "\\>")))
658 (progn (meta-indent-previous-line)
659 (meta-indent-unfinished-line))))
660 meta-indent-level
661 0)))
662
663(defun meta-indent-current-nesting ()
664 "Return the indentation according to the nearest environment keyword."
665 (save-excursion
666 (save-restriction
667 (widen)
668 (back-to-indentation)
669 (let ((to-add 0))
670 ;; If we found some environment marker backward...
671 (if (catch 'found
672 (while (re-search-backward
673 (concat "(\\|)\\|\\<" meta-end-environment-regexp "\\>"
674 "\\|\\<" meta-begin-environment-regexp "\\>"
675 "\\|\\<" meta-within-environment-regexp "\\>")
676 nil t)
677 ;; If we aren't in a string or in a comment, we've found something.
678 (unless (or (meta-indent-in-string-p)
679 (nth 4 (syntax-ppss)))
680 (cond ((= (char-after) ?\()
681 (setq to-add (+ to-add meta-indent-level)))
682 ((= (char-after) ?\))
683 (setq to-add (- to-add meta-indent-level)))
684 (t (throw 'found t))))))
685 (progn
686 ;; ... then use it to compute the current indentation.
687 (back-to-indentation)
688 (+ to-add (current-indentation) (meta-indent-level-count)
689 ;; Compensate for backindent of end and within keywords.
690 (if (meta-indent-looking-at-code
691 (concat "\\<" meta-end-environment-regexp "\\>\\|"
692 "\\<" meta-within-environment-regexp "\\>"))
693 meta-indent-level
694 ;; Compensate for unfinished line.
695 (if (save-excursion
696 (meta-indent-previous-line)
697 (meta-indent-unfinished-line))
698 (- meta-indent-level)
699 0))))
700 0)))))
6b279740
RS
701
702(defun meta-indent-level-count ()
703 "Count indentation change for begin-end commands in the current line."
704 (save-excursion
705 (save-restriction
706 (let ((count 0))
a1506d29 707 (narrow-to-region
6b279740
RS
708 (point) (save-excursion
709 (re-search-forward "[^\\\\\"]%\\|\n\\|\\'" nil t)
710 (backward-char) (point)))
711 (while (re-search-forward "\\<\\sw+\\>\\|(\\|)" nil t)
712 (save-excursion
713 (goto-char (match-beginning 0))
714 (cond
715 ;; Count number of begin-end keywords within line.
8a4c5051 716 ((meta-indent-looking-at-code
6b279740
RS
717 (concat "\\<" meta-begin-environment-regexp "\\>"))
718 (setq count (+ count meta-indent-level)))
8a4c5051 719 ((meta-indent-looking-at-code
6b279740 720 (concat "\\<" meta-end-environment-regexp "\\>"))
8a4c5051 721 (setq count (- count meta-indent-level))))))
6b279740
RS
722 count))))
723
724
725\f
6b279740
RS
726;;; Editing commands.
727
28d16ed3 728(defcustom meta-begin-defun-regexp
6b279740
RS
729 (concat "\\(begin\\(char\\|fig\\|logochar\\)\\|def\\|mode_def\\|"
730 "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)")
3406534c 731 "Regexp matching beginning of defuns in Metafont or MetaPost mode."
28d16ed3
AS
732 :type 'regexp
733 :group 'meta-font)
6b279740 734
28d16ed3 735(defcustom meta-end-defun-regexp
6b279740 736 (concat "\\(end\\(char\\|def\\|fig\\)\\)")
3406534c 737 "Regexp matching the end of defuns in Metafont or MetaPost mode."
28d16ed3
AS
738 :type 'regexp
739 :group 'meta-font)
6b279740
RS
740
741
742(defun meta-beginning-of-defun (&optional arg)
743 "Move backward to beginnning of a defun in Metafont or MetaPost code.
a1506d29 744With numeric argument, do it that many times.
6b279740
RS
745Negative arg -N means move forward to Nth following beginning of defun.
746Returns t unless search stops due to beginning or end of buffer."
747 (interactive "p")
748 (if (or (null arg) (= 0 arg)) (setq arg 1))
749 (and arg (< arg 0) (not (eobp)) (forward-char 1))
a1506d29 750 (and (re-search-backward
6b279740
RS
751 (concat "\\<" meta-begin-defun-regexp "\\>") nil t arg)
752 (progn (goto-char (match-beginning 0))
753 (skip-chars-backward "%")
89c19c1e 754 (skip-chars-backward " \t\f") t)))
a1506d29 755
6b279740
RS
756(defun meta-end-of-defun (&optional arg)
757 "Move forward to end of a defun in Metafont or MetaPost code.
a1506d29 758With numeric argument, do it that many times.
6b279740
RS
759Negative argument -N means move back to Nth preceding end of defun.
760Returns t unless search stops due to beginning or end of buffer."
761 (interactive "p")
762 (if (or (null arg) (= 0 arg)) (setq arg 1))
763 (and (< arg 0) (not (bobp)) (forward-line -1))
764 (and (re-search-forward
765 (concat "\\<" meta-end-defun-regexp "\\>") nil t arg)
766 (progn (goto-char (match-end 0))
767 (skip-chars-forward ";")
89c19c1e 768 (skip-chars-forward " \t\f")
6b279740
RS
769 (if (looking-at "\n") (forward-line 1)) t)))
770
771
772(defun meta-comment-region (beg end &optional arg)
773 "Comment out active region as Metafont or MetaPost source."
774 (interactive "r")
775 (comment-region beg end arg))
776
777(defun meta-uncomment-region (beg end)
778 "Uncomment active region as Metafont or MetaPost source."
779 (interactive "r")
780 (comment-region beg end -1))
781
782(defun meta-comment-defun (&optional arg)
783 "Comment out current environment as Metafont or MetaPost source.
784With prefix argument, uncomment the environment.
785The environment used is the one that contains point or follows point."
786 (interactive "P")
787 (save-excursion
788 (let* ((end (if (meta-end-of-defun) (point) (point-max)))
789 (beg (if (meta-beginning-of-defun) (point) (point-min))))
790 (comment-region beg end arg))))
791
792(defun meta-uncomment-defun ()
793 "Uncomment current environment as Metafont or MetaPost source."
794 (interactive)
795 (meta-comment-defun -1))
796
797
798(defun meta-indent-region (beg end)
799 "Indent the active region as Metafont or MetaPost source."
800 (interactive "r")
801 (indent-region beg end nil))
802
803(defun meta-indent-buffer ()
804 "Indent the whole buffer contents as Metafont or MetaPost source."
805 (interactive)
806 (save-excursion
807 (indent-region (point-min) (point-max) nil)))
808
809(defun meta-indent-defun ()
810 "Indent the current environment as Metafont or MetaPost source.
811The environment indented is the one that contains point or follows point."
812 (interactive)
813 (save-excursion
814 (let* ((end (if (meta-end-of-defun) (point) (point-max)))
815 (beg (if (meta-beginning-of-defun) (point) (point-min))))
816 (indent-region beg end nil))))
817
818
819(defun meta-mark-defun ()
820 "Put mark at end of the environment, point at the beginning.
821The environment marked is the one that contains point or follows point."
822 (interactive)
823 (push-mark (point))
824 (meta-end-of-defun)
825 (push-mark (point) nil t)
826 (meta-beginning-of-defun))
827
828
829\f
830;;; Syntax table, keymap and menu.
831
175069ef 832(define-abbrev-table 'meta-mode-abbrev-table ()
6b279740 833 "Abbrev table used in Metafont or MetaPost mode.")
6b279740 834
175069ef 835(defvar meta-common-mode-syntax-table
ff319790
SM
836 (let ((st (make-syntax-table)))
837 ;; underscores are word constituents
838 (modify-syntax-entry ?_ "w" st)
839 ;; miscellaneous non-word symbols
840 (modify-syntax-entry ?# "_" st)
841 (modify-syntax-entry ?@ "_" st)
842 (modify-syntax-entry ?$ "_" st)
843 (modify-syntax-entry ?? "_" st)
844 (modify-syntax-entry ?! "_" st)
845 ;; binary operators
846 (modify-syntax-entry ?& "." st)
847 (modify-syntax-entry ?+ "." st)
848 (modify-syntax-entry ?- "." st)
849 (modify-syntax-entry ?/ "." st)
850 (modify-syntax-entry ?* "." st)
851 (modify-syntax-entry ?. "." st)
852 (modify-syntax-entry ?: "." st)
853 (modify-syntax-entry ?= "." st)
854 (modify-syntax-entry ?< "." st)
855 (modify-syntax-entry ?> "." st)
856 (modify-syntax-entry ?| "." st)
857 ;; opening and closing delimiters
858 (modify-syntax-entry ?\( "()" st)
859 (modify-syntax-entry ?\) ")(" st)
860 (modify-syntax-entry ?\[ "(]" st)
861 (modify-syntax-entry ?\] ")[" st)
862 (modify-syntax-entry ?\{ "(}" st)
863 (modify-syntax-entry ?\} "){" st)
864 ;; comment character
865 (modify-syntax-entry ?% "<" st)
866 (modify-syntax-entry ?\n ">" st)
867 ;; escape character, needed for embedded TeX code
868 (modify-syntax-entry ?\\ "\\" st)
869 st)
6b279740 870 "Syntax table used in Metafont or MetaPost mode.")
6b279740 871
175069ef 872(defvar meta-common-mode-map
ff319790 873 (let ((map (make-sparse-keymap)))
ff319790
SM
874 ;; Comment Paragraphs:
875 ;; (define-key map "\M-a" 'backward-sentence)
876 ;; (define-key map "\M-e" 'forward-sentence)
877 ;; (define-key map "\M-h" 'mark-paragraph)
878 ;; (define-key map "\M-q" 'fill-paragraph)
879 ;; Navigation:
880 (define-key map "\M-\C-a" 'meta-beginning-of-defun)
881 (define-key map "\M-\C-e" 'meta-end-of-defun)
882 (define-key map "\M-\C-h" 'meta-mark-defun)
883 ;; Indentation:
884 (define-key map "\M-\C-q" 'meta-indent-defun)
885 (define-key map "\C-c\C-qe" 'meta-indent-defun)
886 (define-key map "\C-c\C-qr" 'meta-indent-region)
887 (define-key map "\C-c\C-qb" 'meta-indent-buffer)
888 ;; Commenting Out:
889 (define-key map "\C-c%" 'meta-comment-defun)
890 ;; (define-key map "\C-uC-c%" 'meta-uncomment-defun)
891 (define-key map "\C-c;" 'meta-comment-region)
892 (define-key map "\C-c:" 'meta-uncomment-region)
893 ;; Symbol Completion:
bcd70d97 894 (define-key map "\M-\t" 'completion-at-point)
ff319790
SM
895 ;; Shell Commands:
896 ;; (define-key map "\C-c\C-c" 'meta-command-file)
897 ;; (define-key map "\C-c\C-k" 'meta-kill-job)
898 ;; (define-key map "\C-c\C-l" 'meta-recenter-output)
899 map)
6b279740 900 "Keymap used in Metafont or MetaPost mode.")
175069ef 901(define-obsolete-variable-alias 'meta-mode-map 'meta-common-mode-map "24.1")
6b279740 902
a1506d29 903(easy-menu-define
175069ef 904 meta-mode-menu meta-common-mode-map
6b279740
RS
905 "Menu used in Metafont or MetaPost mode."
906 (list "Meta"
907 ["Forward Environment" meta-beginning-of-defun t]
908 ["Backward Environment" meta-end-of-defun t]
909 "--"
910 ["Indent Line" meta-indent-line t]
911 ["Indent Environment" meta-indent-defun t]
a1506d29 912 ["Indent Region" meta-indent-region
6b279740
RS
913 :active (meta-mark-active)]
914 ["Indent Buffer" meta-indent-buffer t]
915 "--"
916 ["Comment Out Environment" meta-comment-defun t]
917 ["Uncomment Environment" meta-uncomment-defun t]
a1506d29 918 ["Comment Out Region" meta-comment-region
6b279740 919 :active (meta-mark-active)]
a1506d29 920 ["Uncomment Region" meta-uncomment-region
6b279740
RS
921 :active (meta-mark-active)]
922 "--"
bcd70d97 923 ["Complete Symbol" completion-at-point t]
6b279740
RS
924; "--"
925; ["Command on Buffer" meta-command-file t]
926; ["Kill Job" meta-kill-job t]
927; ["Recenter Output Buffer" meta-recenter-output-buffer t]
928 ))
929
930;; Compatibility: XEmacs doesn't have the `mark-active' variable.
931(defun meta-mark-active ()
932 "Return whether the mark and region are currently active in this buffer."
3a51abf1 933 (if (boundp 'mark-active) mark-active (mark)))
6b279740
RS
934
935
936\f
937;;; Hook variables.
938
28d16ed3 939(defcustom meta-mode-load-hook nil
3406534c 940 "Hook evaluated when first loading Metafont or MetaPost mode."
28d16ed3
AS
941 :type 'hook
942 :group 'meta-font)
943
944(defcustom meta-common-mode-hook nil
3406534c 945 "Hook evaluated by both `metafont-mode' and `metapost-mode'."
28d16ed3
AS
946 :type 'hook
947 :group 'meta-font)
948
949(defcustom metafont-mode-hook nil
3406534c 950 "Hook evaluated by `metafont-mode' after `meta-common-mode-hook'."
28d16ed3
AS
951 :type 'hook
952 :group 'meta-font)
953(defcustom metapost-mode-hook nil
3406534c 954 "Hook evaluated by `metapost-mode' after `meta-common-mode-hook'."
28d16ed3
AS
955 :type 'hook
956 :group 'meta-font)
6b279740
RS
957
958
959\f
960;;; Initialization.
961
175069ef 962(define-derived-mode meta-common-mode prog-mode "-Meta-common-"
6b279740 963 "Common initialization for Metafont or MetaPost mode."
175069ef
SM
964 :abbrev-table meta-mode-abbrev-table
965 (set (make-local-variable 'paragraph-start)
966 (concat page-delimiter "\\|$"))
967 (set (make-local-variable 'paragraph-separate)
968 (concat page-delimiter "\\|$"))
969
970 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
971
972 (set (make-local-variable 'comment-start-skip) "%+[ \t\f]*")
973 (set (make-local-variable 'comment-start) "%")
974 (set (make-local-variable 'comment-end) "")
975 (set (make-local-variable 'comment-multi-line) nil)
6b279740 976
89c19c1e
MC
977 ;; We use `back-to-indentation' but \f is no indentation sign.
978 (modify-syntax-entry ?\f "_ ")
979
175069ef 980 (set (make-local-variable 'parse-sexp-ignore-comments) t)
6b279740 981
bcd70d97 982 (add-hook 'completion-at-point-functions #'meta-completions-at-point nil t)
175069ef
SM
983 (set (make-local-variable 'comment-indent-function) #'meta-comment-indent)
984 (set (make-local-variable 'indent-line-function) #'meta-indent-line)
6b279740
RS
985 ;; No need to define a mode-specific 'indent-region-function.
986 ;; Simply use the generic 'indent-region and 'comment-region.
987
988 ;; Set defaults for font-lock mode.
175069ef
SM
989 (set (make-local-variable 'font-lock-defaults)
990 '(meta-font-lock-keywords
991 nil nil ((?_ . "w")) nil
992 (font-lock-comment-start-regexp . "%")))
6b279740
RS
993
994 ;; Activate syntax table, keymap and menu.
175069ef 995 (easy-menu-add meta-mode-menu))
6b279740
RS
996
997
1eadb66c 998;;;###autoload
175069ef
SM
999(define-derived-mode metafont-mode meta-common-mode "Metafont"
1000 "Major mode for editing Metafont sources."
6b279740 1001 ;; Set defaults for completion function.
175069ef
SM
1002 (set (make-local-variable 'meta-symbol-list) nil)
1003 (set (make-local-variable 'meta-symbol-changed) nil)
6b279740 1004 (apply 'meta-add-symbols metafont-symbol-list)
175069ef 1005 (set (make-local-variable 'meta-complete-list)
6b279740 1006 (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
175069ef 1007 (list "" 'ispell-complete-word))))
6b279740 1008
1eadb66c 1009;;;###autoload
175069ef
SM
1010(define-derived-mode metapost-mode meta-common-mode "MetaPost"
1011 "Major mode for editing MetaPost sources."
6b279740 1012 ;; Set defaults for completion function.
175069ef
SM
1013 (set (make-local-variable 'meta-symbol-list) nil)
1014 (set (make-local-variable 'meta-symbol-changed) nil)
6b279740 1015 (apply 'meta-add-symbols metapost-symbol-list)
175069ef 1016 (set (make-local-variable 'meta-complete-list)
6b279740 1017 (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
175069ef 1018 (list "" 'ispell-complete-word))))
6b279740
RS
1019
1020
1021;;; Just in case ...
1022
1023(provide 'meta-mode)
1024(run-hooks 'meta-mode-load-hook)
1025
1026;;; meta-mode.el ends here