Fix last change of grow_mini_window.
[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
ab422c4d 3;; Copyright (C) 2004-2013 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)
b2371818
DN
314 (when font-lock-mode
315 (font-lock-fontify-buffer))))
dd0f1553
DP
316
317
318(defun conf-outline-level ()
319 (let ((depth 0)
320 (pt (match-end 0)))
321 (condition-case nil
322 (while (setq pt (scan-lists pt -1 1)
323 depth (1+ depth)))
324 (scan-error depth))))
325
326\f
327
328;;;###autoload
0b6f31bf 329(defun conf-mode ()
dd0f1553
DP
330 "Mode for Unix and Windows Conf files and Java properties.
331Most conf files know only three kinds of constructs: parameter
332assignments optionally grouped into sections and comments. Yet
333there is a great range of variation in the exact syntax of conf
334files. See below for various wrapper commands that set up the
335details for some of the most widespread variants.
336
337This mode sets up font locking, outline, imenu and it provides
338alignment support through `conf-align-assignments'. If strings
339come out wrong, try `conf-quote-normal'.
340
341Some files allow continuation lines, either with a backslash at
342the end of line, or by indenting the next line (further). These
343constructs cannot currently be recognized.
344
345Because of this great variety of nuances, which are often not
346even clearly specified, please don't expect it to get every file
347quite right. Patches that clearly identify some special case,
348without breaking the general ones, are welcome.
349
350If instead you start this mode with the generic `conf-mode'
351command, it will parse the buffer. It will generally well
352identify the first four cases listed below. If the buffer
353doesn't have enough contents to decide, this is identical to
f5d4cf94
DP
354`conf-windows-mode' on Windows, elsewhere to `conf-unix-mode'.
355See also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode',
356`conf-ppd-mode' and `conf-xdefaults-mode'.
dd0f1553
DP
357
358\\{conf-mode-map}"
359
360 (interactive)
0b6f31bf
SM
361 ;; `conf-mode' plays two roles: it's the parent of several sub-modes
362 ;; but it's also the function that chooses between those submodes.
363 ;; To tell the difference between those two cases where the function
364 ;; might be called, we check `delay-mode-hooks'.
365 ;; (adopted from tex-mode.el)
366 (if (not delay-mode-hooks)
367 ;; try to guess sub-mode of conf-mode based on buffer content
dd0f1553
DP
368 (let ((unix 0) (win 0) (equal 0) (colon 0) (space 0) (jp 0))
369 (save-excursion
370 (goto-char (point-min))
371 (while (not (eobp))
372 (skip-chars-forward " \t\f")
373 (cond ((eq (char-after) ?\#) (setq unix (1+ unix)))
374 ((eq (char-after) ?\;) (setq win (1+ win)))
375 ((eq (char-after) ?\[)) ; nop
376 ((eolp)) ; nop
377 ((eq (char-after) ?})) ; nop
378 ;; recognize at most double spaces within names
379 ((looking-at "[^ \t\n=:]+\\(?: ?[^ \t\n=:]+\\)*[ \t]*[=:]")
380 (if (eq (char-before (match-end 0)) ?=)
381 (setq equal (1+ equal))
382 (setq colon (1+ colon))))
383 ((looking-at "/[/*]") (setq jp (1+ jp)))
384 ((looking-at ".*{")) ; nop
385 ((setq space (1+ space))))
386 (forward-line)))
d902d95e
SM
387 (cond
388 ((> jp (max unix win 3)) (conf-javaprop-mode))
389 ((> colon (max equal space)) (conf-colon-mode))
390 ((> space (max equal colon)) (conf-space-mode))
391 ((or (> win unix) (and (= win unix) (eq system-type 'windows-nt)))
392 (conf-windows-mode))
393 (t (conf-unix-mode))))
0b6f31bf 394
dd0f1553
DP
395 (kill-all-local-variables)
396 (use-local-map conf-mode-map)
dd0f1553 397 (setq major-mode 'conf-mode
0b6f31bf 398 mode-name "Conf[?]")
d902d95e
SM
399 (set (make-local-variable 'font-lock-defaults)
400 '(conf-font-lock-keywords nil t nil nil))
0b6f31bf 401 ;; Let newcomment.el decide this for itself.
d902d95e 402 ;; (set (make-local-variable 'comment-use-syntax) t)
dd0f1553
DP
403 (set (make-local-variable 'parse-sexp-ignore-comments) t)
404 (set (make-local-variable 'outline-regexp)
405 "[ \t]*\\(?:\\[\\|.+[ \t\n]*{\\)")
406 (set (make-local-variable 'outline-heading-end-regexp)
407 "[\n}]")
408 (set (make-local-variable 'outline-level)
409 'conf-outline-level)
0b6f31bf 410 (set-syntax-table conf-mode-syntax-table)
dd0f1553
DP
411 (setq imenu-generic-expression
412 '(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*=" 1)
413 ;; [section]
414 (nil "^[ \t]*\\[[ \t]*\\(.+\\)[ \t]*\\]" 1)
415 ;; section { ... }
f5d4cf94 416 (nil "^[ \t]*\\([^=:{} \t\n][^=:{}\n]+\\)[ \t\n]*{" 1)))
dd0f1553
DP
417 (run-mode-hooks 'conf-mode-hook)))
418
0b6f31bf 419(defun conf-mode-initialize (comment &optional font-lock)
f6b1b0a8 420 "Initializations for sub-modes of conf-mode.
0b6f31bf
SM
421COMMENT initializes `comment-start' and `comment-start-skip'.
422The optional arg FONT-LOCK is the value for FONT-LOCK-KEYWORDS."
423 (set (make-local-variable 'comment-start) comment)
424 (set (make-local-variable 'comment-start-skip)
425 (concat (regexp-quote comment-start) "+\\s *"))
426 (if font-lock
427 (set (make-local-variable 'font-lock-defaults)
428 `(,font-lock nil t nil nil))))
429
dd0f1553 430;;;###autoload
0b6f31bf 431(define-derived-mode conf-unix-mode conf-mode "Conf[Unix]"
dd0f1553
DP
432 "Conf Mode starter for Unix style Conf files.
433Comments start with `#'.
434For details see `conf-mode'. Example:
435
d902d95e 436# Conf mode font-locks this right on Unix and with \\[conf-unix-mode]
dd0f1553
DP
437
438\[Desktop Entry]
439 Encoding=UTF-8
440 Name=The GIMP
441 Name[ca]=El GIMP
442 Name[cs]=GIMP"
0b6f31bf 443 (conf-mode-initialize "#"))
dd0f1553
DP
444
445;;;###autoload
0b6f31bf 446(define-derived-mode conf-windows-mode conf-mode "Conf[WinIni]"
dd0f1553
DP
447 "Conf Mode starter for Windows style Conf files.
448Comments start with `;'.
449For details see `conf-mode'. Example:
450
d902d95e 451; Conf mode font-locks this right on Windows and with \\[conf-windows-mode]
dd0f1553
DP
452
453\[ExtShellFolderViews]
454Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
455{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
456
457\[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
458PersistMoniker=file://Folder.htt"
0b6f31bf 459 (conf-mode-initialize ";"))
dd0f1553
DP
460
461;; Here are a few more or less widespread styles. There are others, so
462;; obscure, they are not covered. E.g. RFC 2614 allows both Unix and Windows
463;; comments. Or the donkey has (* Pascal comments *) -- roll your own starter
464;; if you need it.
465
466;;;###autoload
0b6f31bf 467(define-derived-mode conf-javaprop-mode conf-mode "Conf[JavaProp]"
dd0f1553
DP
468 "Conf Mode starter for Java properties files.
469Comments start with `#' but are also recognized with `//' or
470between `/*' and `*/'.
471For details see `conf-mode'. Example:
472
d902d95e 473# Conf mode font-locks this right with \\[conf-javaprop-mode] (Java properties)
dd0f1553
DP
474// another kind of comment
475/* yet another */
476
477name:value
478name=value
479name value
480x.1 =
481x.2.y.1.z.1 =
482x.2.y.1.z.2.zz ="
0b6f31bf 483 (conf-mode-initialize "#" 'conf-javaprop-font-lock-keywords)
dd0f1553
DP
484 (set (make-local-variable 'conf-assignment-column)
485 conf-javaprop-assignment-column)
486 (set (make-local-variable 'conf-assignment-regexp)
487 ".+?\\([ \t]*[=: \t][ \t]*\\|$\\)")
dd0f1553
DP
488 (setq comment-start-skip "\\(?:#+\\|/[/*]+\\)\\s *")
489 (setq imenu-generic-expression
490 '(("Parameters" "^[ \t]*\\(.+?\\)[=: \t]" 1))))
491
492;;;###autoload
0b6f31bf 493(define-derived-mode conf-space-mode conf-unix-mode "Conf[Space]"
dd0f1553
DP
494 "Conf Mode starter for space separated conf files.
495\"Assignments\" are with ` '. Keywords before the parameters are
e5e0a7db
RS
496recognized according to the variable `conf-space-keywords-alist'.
497Alternatively, you can specify a value for the file local variable
498`conf-space-keywords'.
499Use the function `conf-space-keywords' if you want to specify keywords
500in an interactive fashion instead.
dd0f1553
DP
501
502For details see `conf-mode'. Example:
503
d902d95e 504# Conf mode font-locks this right with \\[conf-space-mode] (space separated)
dd0f1553
DP
505
506image/jpeg jpeg jpg jpe
507image/png png
508image/tiff tiff tif
509
510# Or with keywords (from a recognized file name):
511class desktop
512# Standard multimedia devices
513add /dev/audio desktop
514add /dev/mixer desktop"
0b6f31bf 515 (conf-mode-initialize "#" 'conf-space-font-lock-keywords)
d3632631
RS
516 (make-local-variable 'conf-assignment-sign)
517 (setq conf-assignment-sign nil)
dd3a63bf 518 (make-local-variable 'conf-space-keywords)
8969e906 519 (cond (buffer-file-name
e5e0a7db
RS
520 ;; We set conf-space-keywords directly, but a value which is
521 ;; in the local variables list or interactively specified
522 ;; (see the function conf-space-keywords) takes precedence.
d3632631
RS
523 (setq conf-space-keywords
524 (assoc-default buffer-file-name conf-space-keywords-alist
525 'string-match))))
dd3a63bf
RS
526 (conf-space-mode-internal)
527 ;; In case the local variables list specifies conf-space-keywords,
528 ;; recompute other things from that afterward.
8969e906
RS
529 (add-hook 'hack-local-variables-hook 'conf-space-mode-internal nil t))
530
e5e0a7db 531;;;###autoload
8969e906
RS
532(defun conf-space-keywords (keywords)
533 "Enter Conf Space mode using regexp KEYWORDS to match the keywords.
534See `conf-space-mode'."
535 (interactive "sConf Space keyword regexp: ")
536 (delay-mode-hooks
537 (conf-space-mode))
e5e0a7db 538 (if (string-equal keywords "")
8969e906
RS
539 (setq keywords nil))
540 (setq conf-space-keywords keywords)
541 (conf-space-mode-internal)
542 (run-mode-hooks))
dd0f1553 543
dd3a63bf 544(defun conf-space-mode-internal ()
dd3a63bf
RS
545 (make-local-variable 'conf-assignment-regexp)
546 (setq conf-assignment-regexp
547 (if conf-space-keywords
548 (concat "\\(?:" conf-space-keywords "\\)[ \t]+.+?\\([ \t]+\\|$\\)")
549 ".+?\\([ \t]+\\|$\\)"))
550 ;; If Font Lock is already enabled, reenable it with new
551 ;; conf-assignment-regexp.
552 (when (and font-lock-mode
553 (boundp 'font-lock-keywords)) ;see `normal-mode'
554 (font-lock-add-keywords nil nil)
555 (font-lock-mode 1))
8969e906
RS
556 ;; Copy so that we don't destroy shared structure.
557 (setq imenu-generic-expression (copy-sequence imenu-generic-expression))
558 ;; Get rid of any existing Parameters element.
559 (setq imenu-generic-expression
560 (delq (assoc "Parameters" imenu-generic-expression)
561 imenu-generic-expression))
562 ;; Add a new one based on conf-space-keywords.
dd3a63bf 563 (setq imenu-generic-expression
8969e906
RS
564 (cons `("Parameters"
565 ,(if conf-space-keywords
566 (concat "^[ \t]*\\(?:" conf-space-keywords
567 "\\)[ \t]+\\([^ \t\n]+\\)\\(?:[ \t]\\|$\\)")
568 "^[ \t]*\\([^ \t\n[]+\\)\\(?:[ \t]\\|$\\)")
e5e0a7db 569 1)
8969e906 570 imenu-generic-expression)))
dd3a63bf 571
dd0f1553 572;;;###autoload
0b6f31bf 573(define-derived-mode conf-colon-mode conf-unix-mode "Conf[Colon]"
dd0f1553
DP
574 "Conf Mode starter for Colon files.
575\"Assignments\" are with `:'.
576For details see `conf-mode'. Example:
577
d902d95e 578# Conf mode font-locks this right with \\[conf-colon-mode] (colon)
dd0f1553
DP
579
580<Multi_key> <exclam> <exclam> : \"\\241\" exclamdown
581<Multi_key> <c> <slash> : \"\\242\" cent"
0b6f31bf 582 (conf-mode-initialize "#" 'conf-colon-font-lock-keywords)
dd0f1553
DP
583 (set (make-local-variable 'conf-assignment-space)
584 conf-colon-assignment-space)
585 (set (make-local-variable 'conf-assignment-column)
586 conf-colon-assignment-column)
587 (set (make-local-variable 'conf-assignment-sign)
588 ?:)
589 (set (make-local-variable 'conf-assignment-regexp)
590 ".+?\\([ \t]*:[ \t]*\\)")
dd0f1553
DP
591 (setq imenu-generic-expression
592 `(("Parameters" "^[ \t]*\\(.+?\\)[ \t]*:" 1)
593 ,@(cdr imenu-generic-expression))))
594
f5d4cf94 595;;;###autoload
0b6f31bf 596(define-derived-mode conf-ppd-mode conf-colon-mode "Conf[PPD]"
f5d4cf94 597 "Conf Mode starter for Adobe/CUPS PPD files.
6c1192bf 598Comments start with `*%' and \"assignments\" are with `:'.
f5d4cf94
DP
599For details see `conf-mode'. Example:
600
d902d95e 601*% Conf mode font-locks this right with \\[conf-ppd-mode] (PPD)
f5d4cf94
DP
602
603*DefaultTransfer: Null
604*Transfer Null.Inverse: \"{ 1 exch sub }\""
0b6f31bf 605 (conf-mode-initialize "*%")
f5d4cf94
DP
606 ;; no sections, they match within PostScript code
607 (setq imenu-generic-expression (list (car imenu-generic-expression))))
608
dd0f1553 609;;;###autoload
0b6f31bf 610(define-derived-mode conf-xdefaults-mode conf-colon-mode "Conf[Xdefaults]"
dd0f1553
DP
611 "Conf Mode starter for Xdefaults files.
612Comments start with `!' and \"assignments\" are with `:'.
613For details see `conf-mode'. Example:
614
d902d95e 615! Conf mode font-locks this right with \\[conf-xdefaults-mode] (.Xdefaults)
dd0f1553
DP
616
617*background: gray99
618*foreground: black"
0b6f31bf 619 (conf-mode-initialize "!"))
dd0f1553 620
dd0f1553
DP
621(provide 'conf-mode)
622
623;;; conf-mode.el ends here