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