]> code.delx.au - gnu-emacs/blob - lisp/textmodes/conf-mode.el
(org-export-plain-list-max-depth)
[gnu-emacs] / lisp / textmodes / conf-mode.el
1 ;;; conf-mode.el --- Simple major mode for editing conf/ini/properties files
2
3 ;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4
5 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
6 ;; Keywords: conf ini windows java
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;; Commentary:
26 ;;
27 ;; This mode is designed to edit many similar varieties of Conf/Ini files and
28 ;; Java properties. It started out from Aurélien Tisné's ini-mode.
29 ;; `conf-space-keywords' were inspired by Robert Fitzgerald's any-ini-mode.
30
31
32 ;;; Code:
33
34 (require 'newcomment)
35
36 (defvar outline-heading-end-regexp)
37
38 ;; Variables:
39
40 (defgroup conf nil
41 "Configuration files."
42 :group 'data
43 :version "22.1")
44
45 (defcustom conf-assignment-column 24
46 "Align assignments to this column by default with \\[conf-align-assignments].
47 If this number is negative, the `=' comes before the whitespace. Use 0 to
48 not align (only setting space according to `conf-assignment-space')."
49 :type 'integer
50 :group 'conf)
51
52 (defcustom conf-javaprop-assignment-column 32
53 "Value for `conf-assignment-column' in Java properties buffers."
54 :type 'integer
55 :group 'conf)
56
57 (defcustom conf-colon-assignment-column (- (abs conf-assignment-column))
58 "Value for `conf-assignment-column' in Java properties buffers."
59 :type 'integer
60 :group 'conf)
61
62 (defcustom conf-assignment-space t
63 "Put at least one space around assignments when aligning."
64 :type 'boolean
65 :group 'conf)
66
67 (defcustom conf-colon-assignment-space nil
68 "Value for `conf-assignment-space' in colon style Conf mode buffers."
69 :type 'boolean
70 :group 'conf)
71
72
73 (defvar conf-mode-map
74 (let ((map (make-sparse-keymap)))
75 (define-key map "\C-c\C-u" 'conf-unix-mode)
76 (define-key map "\C-c\C-w" 'conf-windows-mode)
77 (define-key map "\C-c\C-j" 'conf-javaprop-mode)
78 (define-key map "\C-c\C-s" 'conf-space-mode)
79 (define-key map "\C-c " 'conf-space-mode)
80 (define-key map "\C-c\C-c" 'conf-colon-mode)
81 (define-key map "\C-c:" 'conf-colon-mode)
82 (define-key map "\C-c\C-x" 'conf-xdefaults-mode)
83 (define-key map "\C-c\C-p" 'conf-ppd-mode)
84 (define-key map "\C-c\C-q" 'conf-quote-normal)
85 (define-key map "\C-c\"" 'conf-quote-normal)
86 (define-key map "\C-c'" 'conf-quote-normal)
87 (define-key map "\C-c\C-a" 'conf-align-assignments)
88 map)
89 "Local keymap for `conf-mode' buffers.")
90
91 (defvar conf-mode-syntax-table
92 (let ((table (make-syntax-table)))
93 (modify-syntax-entry ?= "." table)
94 (modify-syntax-entry ?_ "_" table)
95 (modify-syntax-entry ?- "_" table)
96 (modify-syntax-entry ?. "_" table)
97 (modify-syntax-entry ?\' "\"" table)
98 (modify-syntax-entry ?\; "<" table)
99 (modify-syntax-entry ?\n ">" table)
100 (modify-syntax-entry ?\r ">" table)
101 table)
102 "Syntax table in use in Windows style `conf-mode' buffers.")
103
104 (defvar conf-unix-mode-syntax-table
105 (let ((table (make-syntax-table conf-mode-syntax-table)))
106 (modify-syntax-entry ?\# "<" table)
107 ;; override
108 (modify-syntax-entry ?\; "." table)
109 table)
110 "Syntax table in use in Unix style `conf-mode' buffers.")
111
112 (defvar conf-javaprop-mode-syntax-table
113 (let ((table (make-syntax-table conf-unix-mode-syntax-table)))
114 (modify-syntax-entry ?/ ". 124" table)
115 (modify-syntax-entry ?* ". 23b" table)
116 table)
117 "Syntax table in use in Java prperties buffers.")
118
119 (defvar conf-ppd-mode-syntax-table
120 (let ((table (make-syntax-table conf-mode-syntax-table)))
121 (modify-syntax-entry ?* ". 1" table)
122 (modify-syntax-entry ?% ". 2" table)
123 ;; override
124 (modify-syntax-entry ?\' "." table)
125 (modify-syntax-entry ?\; "." table)
126 table)
127 "Syntax table in use in PPD `conf-mode' buffers.")
128
129 (defvar conf-xdefaults-mode-syntax-table
130 (let ((table (make-syntax-table conf-mode-syntax-table)))
131 (modify-syntax-entry ?! "<" table)
132 ;; override
133 (modify-syntax-entry ?\; "." table)
134 table)
135 "Syntax table in use in Xdefaults style `conf-mode' buffers.")
136
137
138 (defvar conf-font-lock-keywords
139 `(;; [section] (do this first because it may look like a parameter)
140 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
141 ;; var=val or var[index]=val
142 ("^[ \t]*\\(.+?\\)\\(?:\\[\\(.*?\\)\\]\\)?[ \t]*="
143 (1 'font-lock-variable-name-face)
144 (2 'font-lock-constant-face nil t))
145 ;; section { ... } (do this last because some assign ...{...)
146 ("^[ \t]*\\([^=:\n]+?\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face prepend))
147 "Keywords to hilight in Conf mode.")
148
149 (defvar conf-javaprop-font-lock-keywords
150 '(;; var=val
151 ("^[ \t]*\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(?:\\.\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(?:\\.\\(.+?\\)\\(?:\\.\\([0-9]+\\)\\(\\..+?\\)?\\)?\\)?\\)?\\)?\\)?\\([:= \t]\\|$\\)"
152 (1 'font-lock-variable-name-face)
153 (2 'font-lock-constant-face nil t)
154 (3 'font-lock-variable-name-face nil t)
155 (4 'font-lock-constant-face nil t)
156 (5 'font-lock-variable-name-face nil t)
157 (6 'font-lock-constant-face nil t)
158 (7 'font-lock-variable-name-face nil t)))
159 "Keywords to hilight in Conf Java Properties mode.")
160
161 (defvar conf-space-keywords-alist
162 '(("\\`/etc/gpm/" . "key\\|name\\|foreground\\|background\\|border\\|head")
163 ("\\`/etc/magic\\'" . "[^ \t]+[ \t]+\\(?:[bl]?e?\\(?:short\\|long\\)\\|byte\\|string\\)[^ \t]*")
164 ("/mod\\(?:ules\\|probe\\)\\.conf" . "alias\\|in\\(?:clude\\|stall\\)\\|options\\|remove")
165 ("/manpath\\.config" . "MAN\\(?:DATORY_MANPATH\\|PATH_MAP\\|DB_MAP\\)")
166 ("/sensors\\.conf" . "chip\\|bus\\|label\\|compute\\|set\\|ignore")
167 ("/sane\\(\\.d\\)?/" . "option\\|device\\|port\\|usb\\|sc\\(?:si\\|anner\\)")
168 ("/resmgr\\.conf" . "class\\|add\\|allow\\|deny")
169 ("/dictionary\\.lst\\'" . "DICT\\|HYPH\\|THES")
170 ("/tuxracer/options" . "set"))
171 "File name based settings for `conf-space-keywords'.")
172
173 (defvar conf-space-keywords nil
174 "Regexps for functions that may come before a space assignment.
175 This allows constructs such as
176 keyword var value
177 This variable is best set in the file local variables, or through
178 `conf-space-keywords-alist'.")
179
180 (defvar conf-space-font-lock-keywords
181 `(;; [section] (do this first because it may look like a parameter)
182 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
183 ;; section { ... } (do this first because it looks like a parameter)
184 ("^[ \t]*\\(.+?\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face)
185 ;; var val
186 (eval if conf-space-keywords
187 (list (concat "^[ \t]*\\(" conf-space-keywords "\\)[ \t]+\\([^\000- ]+\\)")
188 '(1 'font-lock-keyword-face)
189 '(2 'font-lock-variable-name-face))
190 '("^[ \t]*\\([^\000- ]+\\)" 1 'font-lock-variable-name-face)))
191 "Keywords to hilight in Conf Space mode.")
192
193 (defvar conf-colon-font-lock-keywords
194 `(;; [section] (do this first because it may look like a parameter)
195 ("^[ \t]*\\[\\(.+\\)\\]" 1 'font-lock-type-face)
196 ;; var: val
197 ("^[ \t]*\\(.+?\\)[ \t]*:"
198 (1 'font-lock-variable-name-face))
199 ;; section { ... } (do this last because some assign ...{...)
200 ("^[ \t]*\\([^:\n]+\\)[ \t\n]*{[^{}]*?$" 1 'font-lock-type-face prepend))
201 "Keywords to hilight in Conf Colon mode.")
202
203 (defvar conf-assignment-sign ?=
204 "Sign used for assignments (char or string).")
205
206 (defvar conf-assignment-regexp ".+?\\([ \t]*=[ \t]*\\)"
207 "Regexp to recognize assignments.
208 It is anchored after the first sexp on a line. There must be a
209 grouping for the assignment sign, including leading and trailing
210 whitespace.")
211
212
213 ;; If anybody can figure out how to get the same effect by configuring
214 ;; `align', I'd be glad to hear.
215 (defun conf-align-assignments (&optional arg)
216 (interactive "P")
217 (setq arg (if arg
218 (prefix-numeric-value arg)
219 conf-assignment-column))
220 (save-excursion
221 (goto-char (point-min))
222 (while (not (eobp))
223 (let ((cs (comment-beginning))) ; go before comment if within
224 (if cs (goto-char cs)))
225 (while (forward-comment 9)) ; max-int?
226 (when (and (not (eobp))
227 (looking-at conf-assignment-regexp))
228 (goto-char (match-beginning 1))
229 (delete-region (point) (match-end 1))
230 (if conf-assignment-sign
231 (if (>= arg 0)
232 (progn
233 (indent-to-column arg)
234 (or (not conf-assignment-space)
235 (memq (char-before (point)) '(?\s ?\t)) (insert ?\s))
236 (insert conf-assignment-sign
237 (if (and conf-assignment-space (not (eolp))) ?\s "")))
238 (insert (if conf-assignment-space ?\s "") conf-assignment-sign)
239 (unless (eolp)
240 (indent-to-column (- arg))
241 (or (not conf-assignment-space)
242 (memq (char-before (point)) '(?\s ?\t)) (insert ?\s))))
243 (unless (eolp)
244 (if (>= (current-column) (abs arg))
245 (insert ?\s)
246 (indent-to-column (abs arg))))))
247 (forward-line))))
248
249
250 (defun conf-quote-normal (arg)
251 "Set the syntax of ' and \" to punctuation.
252 With prefix arg, only do it for ' if 1, or only for \" if 2.
253 This only affects the current buffer. Some conf files use quotes
254 to delimit strings, while others allow quotes as simple parts of
255 the assigned value. In those files font locking will be wrong,
256 and you can correct it with this command. (Some files even do
257 both, i.e. quotes delimit strings, except when they are
258 unbalanced, but hey...)"
259 (interactive "P")
260 (let ((table (copy-syntax-table (syntax-table))))
261 (if (or (not arg) (= (prefix-numeric-value arg) 1))
262 (modify-syntax-entry ?\' "." table))
263 (if (or (not arg) (= (prefix-numeric-value arg) 2))
264 (modify-syntax-entry ?\" "." table))
265 (set-syntax-table table)
266 (and (boundp 'font-lock-mode)
267 font-lock-mode
268 (font-lock-fontify-buffer))))
269
270
271 (defun conf-outline-level ()
272 (let ((depth 0)
273 (pt (match-end 0)))
274 (condition-case nil
275 (while (setq pt (scan-lists pt -1 1)
276 depth (1+ depth)))
277 (scan-error depth))))
278
279 \f
280
281 ;;;###autoload
282 (defun conf-mode ()
283 "Mode for Unix and Windows Conf files and Java properties.
284 Most conf files know only three kinds of constructs: parameter
285 assignments optionally grouped into sections and comments. Yet
286 there is a great range of variation in the exact syntax of conf
287 files. See below for various wrapper commands that set up the
288 details for some of the most widespread variants.
289
290 This mode sets up font locking, outline, imenu and it provides
291 alignment support through `conf-align-assignments'. If strings
292 come out wrong, try `conf-quote-normal'.
293
294 Some files allow continuation lines, either with a backslash at
295 the end of line, or by indenting the next line (further). These
296 constructs cannot currently be recognized.
297
298 Because of this great variety of nuances, which are often not
299 even clearly specified, please don't expect it to get every file
300 quite right. Patches that clearly identify some special case,
301 without breaking the general ones, are welcome.
302
303 If instead you start this mode with the generic `conf-mode'
304 command, it will parse the buffer. It will generally well
305 identify the first four cases listed below. If the buffer
306 doesn't have enough contents to decide, this is identical to
307 `conf-windows-mode' on Windows, elsewhere to `conf-unix-mode'.
308 See also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode',
309 `conf-ppd-mode' and `conf-xdefaults-mode'.
310
311 \\{conf-mode-map}"
312
313 (interactive)
314 ;; `conf-mode' plays two roles: it's the parent of several sub-modes
315 ;; but it's also the function that chooses between those submodes.
316 ;; To tell the difference between those two cases where the function
317 ;; might be called, we check `delay-mode-hooks'.
318 ;; (adopted from tex-mode.el)
319 (if (not delay-mode-hooks)
320 ;; try to guess sub-mode of conf-mode based on buffer content
321 (let ((unix 0) (win 0) (equal 0) (colon 0) (space 0) (jp 0))
322 (save-excursion
323 (goto-char (point-min))
324 (while (not (eobp))
325 (skip-chars-forward " \t\f")
326 (cond ((eq (char-after) ?\#) (setq unix (1+ unix)))
327 ((eq (char-after) ?\;) (setq win (1+ win)))
328 ((eq (char-after) ?\[)) ; nop
329 ((eolp)) ; nop
330 ((eq (char-after) ?})) ; nop
331 ;; recognize at most double spaces within names
332 ((looking-at "[^ \t\n=:]+\\(?: ?[^ \t\n=:]+\\)*[ \t]*[=:]")
333 (if (eq (char-before (match-end 0)) ?=)
334 (setq equal (1+ equal))
335 (setq colon (1+ colon))))
336 ((looking-at "/[/*]") (setq jp (1+ jp)))
337 ((looking-at ".*{")) ; nop
338 ((setq space (1+ space))))
339 (forward-line)))
340 (cond
341 ((> jp (max unix win 3)) (conf-javaprop-mode))
342 ((> colon (max equal space)) (conf-colon-mode))
343 ((> space (max equal colon)) (conf-space-mode))
344 ((or (> win unix) (and (= win unix) (eq system-type 'windows-nt)))
345 (conf-windows-mode))
346 (t (conf-unix-mode))))
347
348 (kill-all-local-variables)
349 (use-local-map conf-mode-map)
350 (setq major-mode 'conf-mode
351 mode-name "Conf[?]")
352 (set (make-local-variable 'font-lock-defaults)
353 '(conf-font-lock-keywords nil t nil nil))
354 ;; Let newcomment.el decide this for itself.
355 ;; (set (make-local-variable 'comment-use-syntax) t)
356 (set (make-local-variable 'parse-sexp-ignore-comments) t)
357 (set (make-local-variable 'outline-regexp)
358 "[ \t]*\\(?:\\[\\|.+[ \t\n]*{\\)")
359 (set (make-local-variable 'outline-heading-end-regexp)
360 "[\n}]")
361 (set (make-local-variable 'outline-level)
362 'conf-outline-level)
363 (set-syntax-table conf-mode-syntax-table)
364 (setq imenu-generic-expression
365 '(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*=" 1)
366 ;; [section]
367 (nil "^[ \t]*\\[[ \t]*\\(.+\\)[ \t]*\\]" 1)
368 ;; section { ... }
369 (nil "^[ \t]*\\([^=:{} \t\n][^=:{}\n]+\\)[ \t\n]*{" 1)))
370 (run-mode-hooks 'conf-mode-hook)))
371
372 (defun conf-mode-initialize (comment &optional font-lock)
373 "Intitializations for sub-modes of conf-mode.
374 COMMENT initializes `comment-start' and `comment-start-skip'.
375 The optional arg FONT-LOCK is the value for FONT-LOCK-KEYWORDS."
376 (set (make-local-variable 'comment-start) comment)
377 (set (make-local-variable 'comment-start-skip)
378 (concat (regexp-quote comment-start) "+\\s *"))
379 (if font-lock
380 (set (make-local-variable 'font-lock-defaults)
381 `(,font-lock nil t nil nil))))
382
383 ;;;###autoload
384 (define-derived-mode conf-unix-mode conf-mode "Conf[Unix]"
385 "Conf Mode starter for Unix style Conf files.
386 Comments start with `#'.
387 For details see `conf-mode'. Example:
388
389 # Conf mode font-locks this right on Unix and with \\[conf-unix-mode]
390
391 \[Desktop Entry]
392 Encoding=UTF-8
393 Name=The GIMP
394 Name[ca]=El GIMP
395 Name[cs]=GIMP"
396 (conf-mode-initialize "#"))
397
398 ;;;###autoload
399 (define-derived-mode conf-windows-mode conf-mode "Conf[WinIni]"
400 "Conf Mode starter for Windows style Conf files.
401 Comments start with `;'.
402 For details see `conf-mode'. Example:
403
404 ; Conf mode font-locks this right on Windows and with \\[conf-windows-mode]
405
406 \[ExtShellFolderViews]
407 Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
408 {5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
409
410 \[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
411 PersistMoniker=file://Folder.htt"
412 (conf-mode-initialize ";"))
413
414 ;; Here are a few more or less widespread styles. There are others, so
415 ;; obscure, they are not covered. E.g. RFC 2614 allows both Unix and Windows
416 ;; comments. Or the donkey has (* Pascal comments *) -- roll your own starter
417 ;; if you need it.
418
419 ;;;###autoload
420 (define-derived-mode conf-javaprop-mode conf-mode "Conf[JavaProp]"
421 "Conf Mode starter for Java properties files.
422 Comments start with `#' but are also recognized with `//' or
423 between `/*' and `*/'.
424 For details see `conf-mode'. Example:
425
426 # Conf mode font-locks this right with \\[conf-javaprop-mode] (Java properties)
427 // another kind of comment
428 /* yet another */
429
430 name:value
431 name=value
432 name value
433 x.1 =
434 x.2.y.1.z.1 =
435 x.2.y.1.z.2.zz ="
436 (conf-mode-initialize "#" 'conf-javaprop-font-lock-keywords)
437 (set (make-local-variable 'conf-assignment-column)
438 conf-javaprop-assignment-column)
439 (set (make-local-variable 'conf-assignment-regexp)
440 ".+?\\([ \t]*[=: \t][ \t]*\\|$\\)")
441 (setq comment-start-skip "\\(?:#+\\|/[/*]+\\)\\s *")
442 (setq imenu-generic-expression
443 '(("Parameters" "^[ \t]*\\(.+?\\)[=: \t]" 1))))
444
445 ;;;###autoload
446 (define-derived-mode conf-space-mode conf-unix-mode "Conf[Space]"
447 "Conf Mode starter for space separated conf files.
448 \"Assignments\" are with ` '. Keywords before the parameters are
449 recognized according to `conf-space-keywords'. Interactively
450 with a prefix ARG of `0' no keywords will be recognized. With
451 any other prefix arg you will be prompted for a regexp to match
452 the keywords.
453
454 For details see `conf-mode'. Example:
455
456 # Conf mode font-locks this right with \\[conf-space-mode] (space separated)
457
458 image/jpeg jpeg jpg jpe
459 image/png png
460 image/tiff tiff tif
461
462 # Or with keywords (from a recognized file name):
463 class desktop
464 # Standard multimedia devices
465 add /dev/audio desktop
466 add /dev/mixer desktop"
467 (conf-mode-initialize "#" 'conf-space-font-lock-keywords)
468 (set (make-local-variable 'conf-assignment-sign)
469 nil)
470 ;; This doesn't seem right, but the next two depend on conf-space-keywords
471 ;; being set, while after-change-major-mode-hook might set up imenu, needing
472 ;; the following result:
473 (hack-local-variables-prop-line)
474 (hack-local-variables)
475 (cond (current-prefix-arg
476 (set (make-local-variable 'conf-space-keywords)
477 (if (> (prefix-numeric-value current-prefix-arg) 0)
478 (read-string "Regexp to match keywords: "))))
479 (conf-space-keywords)
480 (buffer-file-name
481 (set (make-local-variable 'conf-space-keywords)
482 (assoc-default buffer-file-name conf-space-keywords-alist
483 'string-match))))
484 (set (make-local-variable 'conf-assignment-regexp)
485 (if conf-space-keywords
486 (concat "\\(?:" conf-space-keywords "\\)[ \t]+.+?\\([ \t]+\\|$\\)")
487 ".+?\\([ \t]+\\|$\\)"))
488 (setq imenu-generic-expression
489 `(,@(cdr imenu-generic-expression)
490 ("Parameters"
491 ,(if conf-space-keywords
492 (concat "^[ \t]*\\(?:" conf-space-keywords
493 "\\)[ \t]+\\([^ \t\n]+\\)\\(?:[ \t]\\|$\\)")
494 "^[ \t]*\\([^ \t\n[]+\\)\\(?:[ \t]\\|$\\)")
495 1))))
496
497 ;;;###autoload
498 (define-derived-mode conf-colon-mode conf-unix-mode "Conf[Colon]"
499 "Conf Mode starter for Colon files.
500 \"Assignments\" are with `:'.
501 For details see `conf-mode'. Example:
502
503 # Conf mode font-locks this right with \\[conf-colon-mode] (colon)
504
505 <Multi_key> <exclam> <exclam> : \"\\241\" exclamdown
506 <Multi_key> <c> <slash> : \"\\242\" cent"
507 (conf-mode-initialize "#" 'conf-colon-font-lock-keywords)
508 (set (make-local-variable 'conf-assignment-space)
509 conf-colon-assignment-space)
510 (set (make-local-variable 'conf-assignment-column)
511 conf-colon-assignment-column)
512 (set (make-local-variable 'conf-assignment-sign)
513 ?:)
514 (set (make-local-variable 'conf-assignment-regexp)
515 ".+?\\([ \t]*:[ \t]*\\)")
516 (setq imenu-generic-expression
517 `(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*:" 1)
518 ,@(cdr imenu-generic-expression))))
519
520 ;;;###autoload
521 (define-derived-mode conf-ppd-mode conf-colon-mode "Conf[PPD]"
522 "Conf Mode starter for Adobe/CUPS PPD files.
523 Comments start with `*%' and \"assignments\" are with `:'.
524 For details see `conf-mode'. Example:
525
526 *% Conf mode font-locks this right with \\[conf-ppd-mode] (PPD)
527
528 *DefaultTransfer: Null
529 *Transfer Null.Inverse: \"{ 1 exch sub }\""
530 (conf-mode-initialize "*%")
531 ;; no sections, they match within PostScript code
532 (setq imenu-generic-expression (list (car imenu-generic-expression))))
533
534 ;;;###autoload
535 (define-derived-mode conf-xdefaults-mode conf-colon-mode "Conf[Xdefaults]"
536 "Conf Mode starter for Xdefaults files.
537 Comments start with `!' and \"assignments\" are with `:'.
538 For details see `conf-mode'. Example:
539
540 ! Conf mode font-locks this right with \\[conf-xdefaults-mode] (.Xdefaults)
541
542 *background: gray99
543 *foreground: black"
544 (conf-mode-initialize "!"))
545
546 (provide 'conf-mode)
547
548 ;; arch-tag: 0a3805b2-0371-4d3a-8498-8897116b2356
549 ;;; conf-mode.el ends here