* wesnoth-mode.el: Added support for ifndef.
[wesnoth-mode.git] / wesnoth-mode.el
blobbb2eeaf4603328613f7fe74a30a9b17c2e5d867d
1 ;; wesnoth-mode.el - A major mode for editing WML.
2 ;; Copyright (C) 2006, 2007 Chris Mann
4 ;; This program is free software; you can redistribute it and/or
5 ;; modify it under the terms of the GNU General Public License as
6 ;; published by the Free Software Foundation; either version 2 of the
7 ;; License, or (at your option) any later version.
9 ;; This program is distributed in the hope that it will be useful, but
10 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ;; General Public License for more details.
14 ;; You should have received a copy of the GNU General Public License
15 ;; along with this program; see the file COPYING. If not, write to the
16 ;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17 ;; MA 02139, USA.
19 ;;; Description:
20 ;; wesnoth-mode is a major mode for Emacs which assists in the editing
21 ;; of Wesnoth Markup Language (WML) files. Currently, this mode
22 ;; features syntax highlighting support, automatic indentation,
23 ;; tag-completion and preliminary support for syntax checking.
25 ;;; Usage:
26 ;; Add the following to your .emacs:
27 ;; (add-to-list 'load-path "path/to/wesnoth-mode")
28 ;; (autoload 'wesnoth-mode "wesnoth-mode" "Major mode for editing WML." t)
29 ;; Optionally adding:
30 ;; (add-to-list 'auto-mode-alist '("\\.cfg\\'" . wesnoth-mode))
31 ;; to automatically load wesnoth-mode for all files ending in '.cfg'.
33 ;;; Changes:
34 ;; 1.2.2
35 ;; * Fixed #endif not highlighting correctly.
36 ;; * Improvements to jumping to matching tag.
38 (defconst wesnoth-mode-version "1.2.2"
39 "The current version of wesnoth-mode.")
41 (defgroup wesnoth-mode nil "Wesnoth-mode access"
42 :group 'languages
43 :prefix "wesnoth-")
45 (defcustom wesnoth-base-indent 4
46 "The number of columns to indent WML."
47 :type 'integer
48 :group 'wesnoth-mode)
50 (defcustom wesnoth-indentation-function 'wesnoth-indent-line-default
51 "Use the specified function when indenting WML.
52 You can specify either `wesnoth-indent-line-default' or
53 `wesnoth-indent-line-savefile' as the indentation style or a
54 customised function for indentation."
55 :type 'function
56 :group 'wesnoth-mode)
58 (defcustom wesnoth-auto-indent-flag t
59 "Whether to attempt tag indentation when a newline is created.
60 If nil, no indentation will be attempted. Otherwise, attempt to
61 indent the line."
62 :type 'boolean
63 :group 'wesnoth-mode)
65 (defconst wesnoth-preprocessor-regexp
66 "#\\(?:define \\|e\\(?:lse\\|nd\\(?:\\(?:de\\|i\\)f\\)\\)\\|\\(?:if\\|un\\)def \\)"
67 "Regular expression to match all preprocessor statements.")
69 (defconst wesnoth-preprocessor-opening-regexp
70 "#\\(?:define \\|else\\|ifdef \\)"
71 "Regular expression to match \"opening\" preprocessor statements.")
73 (defconst wesnoth-preprocessor-closing-regexp
74 "#e\\(?:lse\\|nd\\(?:\\(?:de\\|i\\)f\\)\\)"
75 "Regular expression to match \"closing\" preprocessor statements.")
77 (defvar wesnoth-mode-hook nil)
79 (defvar wesnoth-mode-map ()
80 "Keymap used in wesnoth mode.")
81 (unless wesnoth-mode-map
82 (setq wesnoth-mode-map (make-sparse-keymap))
83 (define-key wesnoth-mode-map "\C-\M-a" 'wesnoth-jump-backward)
84 (define-key wesnoth-mode-map "\C-\M-e" 'wesnoth-jump-forward)
85 (define-key wesnoth-mode-map "\C-c\C-m" 'wesnoth-jump-to-matching)
86 (define-key wesnoth-mode-map "\C-cm" 'wesnoth-jump-to-matching)
87 (define-key wesnoth-mode-map "\C-m" 'wesnoth-newline)
88 (define-key wesnoth-mode-map "\C-j" 'wesnoth-newline-and-indent)
89 (define-key wesnoth-mode-map "\C-c\C-c" 'wesnoth-check-structure)
90 (define-key wesnoth-mode-map "\C-cc" 'wesnoth-check-structure)
91 (define-key wesnoth-mode-map "\C-c\C-n" 'wesnoth-check-tag-names)
92 (define-key wesnoth-mode-map "\C-cn" 'wesnoth-check-tag-names)
93 (define-key wesnoth-mode-map "\C-c\C-e" 'wesnoth-insert-tag)
94 (define-key wesnoth-mode-map "\C-ce" 'wesnoth-insert-tag))
96 (defvar wesnoth-syntax-table
97 (let ((wesnoth-syntax-table (make-syntax-table)))
98 (modify-syntax-entry ?= "." wesnoth-syntax-table)
99 (modify-syntax-entry ?\_ "w" wesnoth-syntax-table)
100 (modify-syntax-entry ?- "_" wesnoth-syntax-table)
101 (modify-syntax-entry ?. "_" wesnoth-syntax-table)
102 (modify-syntax-entry ?\n ">" wesnoth-syntax-table)
103 (modify-syntax-entry ?\r ">" wesnoth-syntax-table)
104 wesnoth-syntax-table)
105 "Syntax table for wesnoth-mode.")
107 ;; Prevents automatic syntax-highlighting of elements which might be
108 ;; pre-processor statements.
109 (defvar wesnoth-syntactic-keywords
110 (list
111 '("^[\t ]*\\(#\\(?:define \\|e\\(?:lse\\|nd\\(?:\\(?:de\\|i\\)f\\)\\)\\|\\(?:ifn?\\|un\\)def \\)\\)" 1 "w")
112 '("\\(#[\t ]*.*$\\)" 1 "<"))
113 "Highlighting syntactic keywords within wesnoth-mode.")
115 (defvar wesnoth-font-lock-keywords
116 (list
117 '("\\(#\\(?:define\\|\\(?:ifn?\\|un\\)def\\)\\)"
118 1 font-lock-preprocessor-face)
119 '("\\(#\\(?:define\\|\\(?:ifn?\\|un\\)def\\)\\)[\t ]+\\(\\w+\\)"
120 2 font-lock-function-name-face)
121 '("\\(#e\\(?:lse\\|nd\\(?:\\(?:de\\|i\\)f\\)\\)\\)" . font-lock-preprocessor-face)
122 '("[\t ]*\\({[[:word:]/\.]+\\|{[@~][[:word:]/\.]+\\).*\\(}\\)"
123 (1 font-lock-function-name-face)
124 (2 font-lock-function-name-face))
125 '("\\[[^]]+\\]" . font-lock-type-face)
126 '("\\$\\w+" . font-lock-variable-name-face)
127 '("\\(\\w+\\(\\,[\t ]*\\w+\\)*\\)="
128 1 font-lock-variable-name-face))
129 "Syntax highlighting for wesnoth-mode.")
131 (defvar wesnoth-tags-list
132 (list
133 "abilities" "about" "advances" "advancefrom" "ai" "allow_recruit" "and"
134 "animation" "array" "attack" "attacks" "avoid" "binary_path" "bold"
135 "campaign" "capture_village" "choose""clear_variable" "colour_adjust"
136 "command" "deaths" "defend" "defends" "defense" "delay" "destination"
137 "disallow_recruit" "do" "effect" "else" "end_turn" "endlevel" "era" "event"
138 "expenses" "filter" "filter_radius" "filter_second" "format" "frame"
139 "game_config" "generator" "gold" "have_unit" "header" "hide_unit" "if"
140 "illuminated_time" "image" "img" "income" "italic" "item" "jump" "kill"
141 "killed" "label" "language" "leader_goal" "main_map" "menu" "message"
142 "mini_map" "missile_frame" "modifications" "modify_side" "modify_turns"
143 "move" "move_unit_fake" "movement_costs" "movetype" "multiplayer"
144 "multiplayer_side" "music" "not" "num_units" "object" "objectives"
145 "objective" "observers" "option" "or" "panel" "part" "place_shroud"
146 "position" "print" "protect_location" "protect_unit" "race" "random"
147 "recall" "recalls" "recruit" "recruits" "redraw" "ref" "remove_shroud"
148 "remove_unit_overlay" "removeitem" "replay" "replay_start" "resistance"
149 "resolution" "results" "role" "save" "scenario" "scroll" "scroll_to"
150 "scroll_to_unit" "section" "set_recruit" "set_variable" "side"
151 "side_playing" "snapshot" "sound" "source" "specials" "statistics" "status"
152 "stone" "store_gold" "store_locations" "store_starting_location"
153 "store_unit" "story" "target" "team" "teleport" "teleport_anim" "terrain"
154 "terrain_graphics" "test" "textdomain" "theme" "then" "tile" "time"
155 "time_area" "time_of_day" "topic" "toplevel" "trait" "turn" "tutorial"
156 "unhide_unit" "unit" "unit_abilities" "unit_alignment" "unit_description"
157 "unit_hp" "unit_image" "unit_level" "unit_moves" "unit_overlay"
158 "unit_profile" "unit_status" "unit_traits" "unit_type" "unit_weapons"
159 "unit_xp" "units" "unstone" "unstore_unit" "upkeep" "variable" "variables"
160 "village" "villages" "while")
161 "A list containing all tags which are available for use in WML.")
163 (defun wesnoth-insert-tag ()
164 "Inserts the specified opening tag and it's matching closing tag.
165 Both the opening and closing tags will be placed on their own
166 lines with point positioned between them. Completion of tags at
167 the prompt uses `wesnoth-tags-list'."
168 (interactive)
169 (let ((tagname
170 (completing-read
171 "Tag: "
172 wesnoth-tags-list
173 nil nil)))
174 (progn
175 (beginning-of-line)
176 (unless (looking-at "^[\t ]*$")
177 (end-of-line)
178 (insert "\n"))
179 (end-of-line)
180 (insert "[" tagname "]")
181 (wesnoth-indent-line)
182 (insert "\n")
183 (wesnoth-indent-line)
184 (save-excursion
185 (insert "\n[/" tagname "]")
186 (wesnoth-indent-line)
187 (forward-line -1)))))
189 (defun wesnoth-jump-forward (repeat)
190 "Move point to the end of the next tag.
191 REPEAT is an optional numeric argument. If REPEAT is non-nil,
192 jump forward the specified number of tags."
193 (interactive "p")
194 (or repeat (setq repeat 1))
195 (and (< repeat 0) (wesnoth-jump-backward (abs repeat)))
196 (let ((iterations 0))
197 (while (< iterations repeat)
198 (end-of-line)
199 (search-forward-regexp
200 (concat "^[\t ]*\\(\\[\\w+\\]\\|"
201 wesnoth-preprocessor-opening-regexp "\\)")
202 (buffer-size) t)
203 (setq iterations (1+ iterations)))))
205 (defun wesnoth-jump-backward (repeat)
206 "Move point to the beginning of the previous tag.
207 REPEAT is an optional numeric argument. If REPEAT is non-nil,
208 jump backward the specified number of tags."
209 (interactive "p")
210 (or repeat (setq repeat 1))
211 (and (< repeat 0) (wesnoth-jump-forward (abs repeat)))
212 (let ((iterations 0))
213 (while (< iterations repeat)
214 (beginning-of-line)
215 (search-backward-regexp
216 (concat "^[\t ]*\\(\\[\\w+\\]\\|"
217 wesnoth-preprocessor-opening-regexp "\\)")
218 0 t)
219 (unless (bobp)
220 (search-forward-regexp "[^[:blank:]]")
221 (backward-char))
222 (setq iterations (1+ iterations)))))
224 (defun wesnoth-jump-to-matching ()
225 "Jump point to the matching opening/closing tag.
226 A tag must be on the same line as point for jumping to occur. If
227 the tag structure is not correct this may have unexpected
228 results."
229 (interactive)
230 (let ((open-tags 0)
231 (search-started nil)
232 (tag-position nil)
233 (search-backward nil))
234 (save-excursion
235 (beginning-of-line)
236 (if (looking-at
237 (concat "^[\t ]*\\(\\[\\|"
238 wesnoth-preprocessor-regexp "\\)"))
239 (when (looking-at
240 (concat "^[\t ]*\\(\\[/\\|#\\(?:endif\\|enddef\\)\\)"))
241 (setq search-backward t))
242 (if (wesnoth-wml-start-pos)
243 (if (> (point) (wesnoth-wml-start-pos))
244 (search-backward-regexp
245 (concat "^[\t ]*\\(\\[\\|"
246 wesnoth-preprocessor-regexp "\\)")
247 (point-min) t)
248 (goto-char (point-min))
249 (search-forward-regexp
250 (concat "^[\t ]*\\(\\[\\|"
251 wesnoth-preprocessor-regexp "\\)"))
252 (beginning-of-line))
253 (error "%s" "Unable to locate tag to jump from")))
254 (if search-backward
255 (progn
256 (end-of-line)
257 (while (and
258 (or (< open-tags 0) (not search-started))
259 (search-backward-regexp
260 (concat "^[\t ]*\\(\\[\\|"
261 wesnoth-preprocessor-regexp "\\)")
262 (point-min) t))
263 (setq search-started t)
264 (if (looking-at
265 "^[\t ]*\\(\\[\\+?\\w+\\]\\|#\\(?:define\\|ifn?def\\) \\)")
266 (setq open-tags (1+ open-tags))
267 (when (looking-at
268 (concat "^[\t ]*\\(\\[/\\w+\\]\\|#\\(?:endif\\|enddef\\)\\)"))
269 (setq open-tags (1- open-tags))))))
270 (while (and
271 (or (> open-tags 0) (not search-started))
272 (search-forward-regexp
273 (concat "^[\t ]*\\(\\[\\|"
274 wesnoth-preprocessor-regexp "\\)")
275 (point-max) t))
276 (beginning-of-line)
277 (setq search-started t)
278 (if (looking-at
279 "^[\t ]*\\(\\[\\+?\\w+\\]\\|#\\(?:define\\|ifn?def\\) \\)")
280 (setq open-tags (1+ open-tags))
281 (when (looking-at
282 (concat "^[\t ]*\\(\\[\\+?/\\w+\\]\\|#\\(?:endif\\|enddef\\)\\)"))
283 (setq open-tags (1- open-tags))))
284 (end-of-line)))
285 (setq tag-position (point)))
286 (if (interactive-p)
287 (goto-char tag-position)
288 tag-position))
289 (end-of-line)
290 (search-backward-regexp "\\[\\|#"))
292 (defun wesnoth-wml-start-pos ()
293 "Determine the position of `point' relative to where the actual WML begins.
294 Return the likely starting position of the WML if it is found.
295 Otherwise return nil."
296 (save-excursion
297 (goto-char (point-min))
298 (when (search-forward-regexp
299 (concat "^[\t ]*\\(\\[\\)\\|\\("
300 wesnoth-preprocessor-opening-regexp
301 "\\)")
302 (buffer-size) t)
303 (beginning-of-line)
304 (point))))
306 (defun wesnoth-indent-line-default ()
307 "Indent the current line as WML using normal-style indentation."
308 (beginning-of-line)
309 (if (or (not (wesnoth-wml-start-pos))
310 (<= (point) (wesnoth-wml-start-pos))
311 (nth 3 (syntax-ppss (point))))
312 (indent-line-to 0)
313 (let ((not-indented t) cur-indent)
314 (if (looking-at
315 (concat "^[ \t]*\\(\\[\\/[^]]*?\\|\\("
316 wesnoth-preprocessor-closing-regexp "\\)\\)"))
317 (progn
318 (save-excursion
319 (search-backward-regexp
320 (concat "^[\t ]*\\[\\|\\(" wesnoth-preprocessor-regexp "\\)"))
321 (setq cur-indent (current-indentation))
322 (beginning-of-line)
323 (when (looking-at
324 (concat "^[\t ]*\\(\\[/.+\\]\\|\\("
325 wesnoth-preprocessor-closing-regexp
326 "\\)\\)"))
327 (setq cur-indent (- (current-indentation) wesnoth-base-indent))))
328 (if (< cur-indent 0)
329 (setq cur-indent 0)))
330 (if (not (looking-at
331 (concat "^[ \t]*\\(\\[[^/]*?\\]\\|\\("
332 wesnoth-preprocessor-closing-regexp "\\)\\)")))
333 (save-excursion
334 (search-backward-regexp
335 (concat "^[\t ]*\\(\\[\\|\\("
336 wesnoth-preprocessor-regexp "\\)\\)"))
337 (if (looking-at
338 (concat "^[\t ]*\\(\\[/.+\\]\\|\\("
339 wesnoth-preprocessor-closing-regexp
340 "\\)\\)"))
341 (progn
342 (setq cur-indent (- (current-indentation) wesnoth-base-indent))
343 (if (< cur-indent 0)
344 (setq cur-indent 0))
345 (setq not-indented nil))
346 (setq cur-indent (current-indentation))
347 (setq not-indented nil)))
348 (save-excursion
349 (unless cur-indent
350 (search-backward-regexp
351 (concat "^[\t ]*\\([[}]\\|\\("
352 wesnoth-preprocessor-regexp
353 "\\)\\)"))
354 (if (looking-at
355 (concat "^[ \t]*\\(\\[[^/]*?\\]\\|\\("
356 wesnoth-preprocessor-opening-regexp "\\)\\)"))
357 (setq cur-indent (+ (current-indentation) wesnoth-base-indent))
358 (setq cur-indent (current-indentation)))))))
359 (unless (and (not cur-indent) (= (current-indentation) cur-indent))
360 (indent-line-to cur-indent))))
361 (beginning-of-line)
362 (search-forward-regexp "[\t ]*"))
364 (defun wesnoth-indent-line-savefile ()
365 "Indent the current line as WML code using savefile-style indentation."
366 (beginning-of-line)
367 (if (or (not (wesnoth-wml-start-pos))
368 (<= (point) (wesnoth-wml-start-pos))
369 (nth 3 (syntax-ppss (point))))
370 (indent-line-to 0)
371 (let ((cur-indent))
372 (if (looking-at
373 (concat "^[ \t]*\\(\\[\\/[^]]*?\\|\\("
374 wesnoth-preprocessor-closing-regexp "\\)\\)"))
375 (progn
376 (save-excursion
377 (search-backward-regexp "^[ \t]+.\\|^[{[#]")
378 (setq cur-indent (- (current-indentation) wesnoth-base-indent))
379 (when (looking-at
380 (concat "^[ \t]*\\(\\[[^/].+\\]\\|\\("
381 wesnoth-preprocessor-opening-regexp "\\)\\)"))
382 (setq cur-indent (current-indentation))))
383 (if (< cur-indent 0)
384 (setq cur-indent 0)))
385 (save-excursion
386 (unless cur-indent
387 (search-backward-regexp "^[\t ]*\\([[#}]\\)")
388 (if (looking-at
389 (concat "^[ \t]*\\(\\[[^/]+?\\]\\|\\("
390 wesnoth-preprocessor-opening-regexp "\\)\\)"))
391 (setq cur-indent (+ (current-indentation) wesnoth-base-indent))
392 (setq cur-indent (current-indentation))))))
393 (unless (and (not cur-indent)
394 (= (current-indentation) cur-indent))
395 (indent-line-to cur-indent))))
396 (beginning-of-line)
397 (search-forward-regexp "[\t ]*"))
399 (defun wesnoth-newline ()
400 "Indent both the current line and the newline created.
401 If `wesnoth-auto-indent-flag' is nil, indentation will not be
402 performed."
403 (interactive)
404 (when wesnoth-auto-indent-flag
405 (save-excursion
406 (beginning-of-line)
407 (if (looking-at "^[\t ]*$")
408 (indent-line-to 0)
409 (wesnoth-indent-line))))
410 (newline))
412 (defun wesnoth-newline-and-indent ()
413 "Indent both the current line and the newline created.
414 If `wesnoth-auto-indent-flag' is nil, indentation will not be
415 performed."
416 (interactive)
417 (wesnoth-newline)
418 (wesnoth-indent-line))
420 (defun wesnoth-check-tag-names ()
421 "Check the names of all tags in the buffer for correctness.
422 If a tag is found which is not present in the list an error will
423 be signalled and point will be moved to the corresponding
424 position."
425 (interactive)
426 (let ((tag-position nil)
427 (missing-tag-name nil))
428 (save-excursion
429 (goto-char (point-min))
430 (while (and
431 (search-forward-regexp "^[\t ]*\\[" (point-max) t)
432 (not tag-position))
433 (beginning-of-line)
434 (when (looking-at "^[\t ]*\\[[/]?\\(\\w+\\)\\]")
435 (unless (member (match-string-no-properties 1) wesnoth-tags-list)
436 (setq tag-position (point))
437 (setq missing-tag-name (match-string-no-properties 1))))
438 (end-of-line)))
439 (when tag-position
440 (goto-char tag-position)
441 (message "'%s' is not known to exist"
442 missing-tag-name))))
444 (defun wesnoth-check-structure ()
445 "Check the buffer for correct nesting of elements.
446 If a problem is found in the structure, point will be placed at
447 the location which an element was expected and the expected
448 element will be displayed in the minibuffer."
449 (interactive)
450 (let ((unmatched-tag-list '())
451 (error-position nil))
452 (save-excursion
453 (goto-char (point-min))
454 (while (and
455 (search-forward-regexp
456 (concat "^[\t ]*\\[\\|\\(" wesnoth-preprocessor-regexp "\\)")
457 (point-max) t)
458 (not error-position))
459 (beginning-of-line)
460 (if (looking-at "^[\t ]*#\\(\\w+\\)")
461 (let ((preprocessor-name (match-string-no-properties 1)))
462 (cond
463 ((string= preprocessor-name "define")
464 (setq unmatched-tag-list
465 (cons preprocessor-name unmatched-tag-list)))
466 ((string= preprocessor-name "ifdef")
467 (setq unmatched-tag-list
468 (cons preprocessor-name unmatched-tag-list)))
469 ((string= preprocessor-name "ifdef")
470 (setq unmatched-tag-list
471 (cons preprocessor-name unmatched-tag-list)))
472 ((string= preprocessor-name "else")
473 (unless (string-match "ifn?def" (car unmatched-tag-list))
474 (setq error-position (point))))
475 ((string= preprocessor-name "endif")
476 (if (string-match "ifn?def" (car unmatched-tag-list))
477 (setq unmatched-tag-list (cdr unmatched-tag-list))
478 (setq error-position (point))))
479 ((string= preprocessor-name "enddef")
480 (if (string= (car unmatched-tag-list) "define")
481 (setq unmatched-tag-list (cdr unmatched-tag-list))
482 (setq error-position (point))))))
483 (if (looking-at "^[\t ]*\\[\\+?\\(\\w+\\)\\]")
484 (setq unmatched-tag-list
485 (cons (match-string-no-properties 1)
486 unmatched-tag-list))
487 (when (looking-at "^[\t ]*\\[/\\(\\w+\\)\\]")
488 (if (string= (match-string-no-properties 1)
489 (car unmatched-tag-list))
490 (setq unmatched-tag-list (cdr unmatched-tag-list))
491 (setq error-position (point))))))
492 (end-of-line)))
493 (if (not (or unmatched-tag-list error-position))
494 (message "%s" "Tag structure appears consistent.")
495 (if error-position
496 (goto-char error-position)
497 (goto-char (point-max)))
498 (let ((expected nil))
499 (cond ((string= (car unmatched-tag-list) "define")
500 (setq expected "#enddef"))
501 ((string-match "ifn?def" (car unmatched-tag-list))
502 (setq expected "#endif"))
503 ((not unmatched-tag-list)
504 (setq expected "Unexpected end of file")))
505 (and (interactive-p)
506 (message "Expecting: '%s'"
508 expected (concat "[/" (car unmatched-tag-list)
509 "]"))))
510 (or expected (concat "[/" (car unmatched-tag-list) "]"))))))
512 ;; TODO This should allow interactive fixing.
513 (defun wesnoth-fix-structure ()
514 "Attempt to fix faults in the structure of the current buffer."
515 (interactive)
516 (let ((element (wesnoth-check-structure)))
517 (while element
518 (if (string= element "Unexpected end of file")
519 (delete-region (point) (point-max))
520 (beginning-of-line)
521 (open-line 1)
522 (insert element)
523 (wesnoth-indent-line))
524 (setq element (wesnoth-check-structure)))))
526 (defun wesnoth-indent-line ()
527 "Determine and performs indentation on the current line.
528 The Indentation style can be customised by modifying
529 `wesnoth-indentation-function'."
530 (interactive)
531 (funcall wesnoth-indentation-function))
533 (define-derived-mode wesnoth-mode fundamental-mode "wesnoth-mode"
534 "Major mode for editing WML."
535 (set-syntax-table wesnoth-syntax-table)
536 (set (make-local-variable 'outline-regexp) "^[\t ]*\\[\\w+")
537 (set (make-local-variable 'comment-start) "#")
538 (set (make-local-variable 'indent-line-function) 'wesnoth-indent-line)
539 (set (make-local-variable 'font-lock-defaults)
540 '(wesnoth-font-lock-keywords
541 nil t nil nil
542 (font-lock-syntactic-keywords . wesnoth-syntactic-keywords)))
543 (setq indent-tabs-mode nil)
544 (setq mode-name "WML")
545 (run-hooks 'wesnoth-mode-hook))
547 (provide 'wesnoth-mode)