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