ERC: Sync version 5.3, release candidate 1.
[bpt/emacs.git] / lisp / generic-x.el
index 9191c39..3310c38 100644 (file)
@@ -1,6 +1,7 @@
-;;; generic-x.el --- Extra Modes for generic-mode
+;;; generic-x.el --- A collection of generic modes
 
-;; Copyright (C) 1997, 1998, 2003, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1998, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author:  Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Tue Oct 08 1996
@@ -10,7 +11,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 ;;
-;; This file contains some pre-defined generic-modes.
+;; This file contains a collection of generic modes.
 ;;
 ;; INSTALLATION:
 ;;
 ;;   (require 'generic-x)
 ;;
 ;; You can decide which modes to load by setting the variable
-;; `generic-extras-enable-list'.  Some platform-specific modes are
-;; affected by the variables `generic-define-mswindows-modes' and
-;; `generic-define-unix-modes' (which see).
+;; `generic-extras-enable-list'.  Its default value is platform-
+;; specific.  The recommended way to set this variable is through
+;; customize:
 ;;
-;; You can also send in new modes; if the file types a reasonably common,
-;; we would like to install them.
+;;   M-x customize-option RET generic-extras-enable-list RET
+;;
+;; This lets you select generic modes from the list of available
+;; modes.  If you manually set `generic-extras-enable-list' in your
+;; .emacs, do it BEFORE loading generic-x with (require 'generic-x).
+;;
+;; You can also send in new modes; if the file types are reasonably
+;; common, we would like to install them.
+;;
+;; DEFAULT GENERIC MODE:
+;;
+;; This file provides a hook which automatically puts a file into
+;; `default-generic-mode' if the first few lines of a file in
+;; fundamental mode start with a hash comment character.  To disable
+;; this functionality, set the variable `generic-use-find-file-hook'
+;; to nil BEFORE loading generic-x.  See the variables
+;; `generic-lines-to-scan' and `generic-find-file-regexp' for
+;; customization options.
 ;;
 ;; PROBLEMS WHEN USED WITH FOLDING MODE:
 ;;
 ;; [The following relates to the obsolete selective-display technique.
-;; Folding mode should use invisible text properties instead. -- Dave
+;; Folding mode should use invisible text properties instead.  -- Dave
 ;; Love]
 ;;
 ;; From Anders Lindgren <andersl@csd.uu.se>
 ;;
 ;; Problem summary: Wayne Adams has found a problem when using folding
-;; mode in conjuction with font-lock for a mode defined in
+;; mode in conjunction with font-lock for a mode defined in
 ;; `generic-x.el'.
 ;;
 ;; The problem, as Wayne described it, was that error messages of the
 ;; >      - various msgs including "Fontifying region...(error Stack
 ;; > overflow in regexp matcher)" appear
 ;;
-;; I have just tracked down the cause of the problem.  The regexp:s in
-;; `generic-x.el' does not take into account the way that folding
-;; hides sections of the buffer.  The technique is known as
+;; I have just tracked down the cause of the problem.  The regexp's in
+;; `generic-x.el' do not take into account the way that folding hides
+;; sections of the buffer.  The technique is known as
 ;; `selective-display' and has been available for a very long time (I
-;; started using it back in the good old' Emacs 18 days).  Basically, a
+;; started using it back in the good old Emacs 18 days).  Basically, a
 ;; section is hidden by creating one very long line were the newline
 ;; character (C-j) is replaced by a linefeed (C-m) character.
 ;;
 ;; Many other hiding packages, besides folding, use the same technique,
 ;; the problem should occur when using them as well.
 ;;
-;; The erroronous lines in `generic-extras' look like the following (this
+;; The erroneous lines in `generic-x.el' look like the following (this
 ;; example is from the `ini' section):
 ;;
 ;;     '(("^\\(\\[.*\\]\\)"   1 'font-lock-constant-face)
 ;; [foo]
 ;; bar = xxx
 ;;
-;; However, since the `.' regexp symbol match the linefeed character the
-;; entire folded section is searched, resulting in a regexp stack
+;; However, since the `.' regexp symbol matches the linefeed character
+;; the entire folded section is searched, resulting in a regexp stack
 ;; overflow.
 ;;
-;; Solution suggestion 2: Instead of using ".", use the sequence
-;; "[^\n\r]".  This will make the rules behave just as before, but they
-;; will work together with selective-display.
+;; Solution suggestion: Instead of using ".", use the sequence
+;; "[^\n\r]".  This will make the rules behave just as before, but
+;; they will work together with selective-display.
 
 ;;; Code:
 
-(require 'font-lock)
+(eval-when-compile (require 'font-lock))
 
 (defgroup generic-x nil
-  "Extra modes for generic mode."
+  "A collection of generic modes."
   :prefix "generic-"
-  :group 'generic
+  :group 'data
   :version "20.3")
 
-(defcustom generic-extras-enable-list nil
-  "*List of generic modes to enable by default.
-Each entry in the list should be a symbol.  The variables
-`generic-define-mswindows-modes' and `generic-define-unix-modes'
-also affect which generic modes are defined.  Please note that if
-you set this variable after generic-x is loaded, you must reload
-generic-x to enable the specified modes."
-  :group 'generic-x
-  :type  '(repeat sexp))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Default-Generic mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defcustom generic-define-mswindows-modes
-  (memq system-type '(windows-nt ms-dos))
-  "*If non-nil, some MS-Windows specific generic modes will be defined."
+(defcustom generic-use-find-file-hook t
+  "*If non-nil, add a hook to enter `default-generic-mode' automatically.
+This is done if the first few lines of a file in fundamental mode
+start with a hash comment character."
   :group 'generic-x
   :type  'boolean)
 
-(defcustom generic-define-unix-modes
-  (not (memq system-type '(windows-nt ms-dos)))
-  "*If non-nil, some Unix specific generic modes will be defined."
+(defcustom generic-lines-to-scan 3
+  "*Number of lines that `generic-mode-find-file-hook' looks at.
+Relevant when deciding whether to enter Default-Generic mode automatically.
+This variable should be set to a small positive number."
   :group 'generic-x
-  :type  'boolean)
+  :type  'integer)
+
+(defcustom generic-find-file-regexp "^#"
+  "*Regular expression used by `generic-mode-find-file-hook'.
+Files in fundamental mode whose first few lines contain a match
+for this regexp, should be put into Default-Generic mode instead.
+The number of lines tested for the matches is specified by the
+value of the variable `generic-lines-to-scan', which see."
+  :group 'generic-x
+  :type  'regexp)
+
+(defcustom generic-ignore-files-regexp "[Tt][Aa][Gg][Ss]\\'"
+  "*Regular expression used by `generic-mode-find-file-hook'.
+Files whose names match this regular expression should not be put
+into Default-Generic mode, even if they have lines which match
+the regexp in `generic-find-file-regexp'.  If the value is nil,
+`generic-mode-find-file-hook' does not check the file names."
+  :group 'generic-x
+  :type  '(choice (const :tag "Don't check file names" nil) regexp))
+
+;; This generic mode is always defined
+(define-generic-mode default-generic-mode (list ?#) nil nil nil nil)
+
+;; A more general solution would allow us to enter generic-mode for
+;; *any* comment character, but would require us to synthesize a new
+;; generic-mode on the fly. I think this gives us most of what we
+;; want.
+(defun generic-mode-find-file-hook ()
+  "Hook function to enter Default-Generic mode automatically.
+
+Done if the first few lines of a file in Fundamental mode start
+with a match for the regexp in `generic-find-file-regexp', unless
+the file's name matches the regexp which is the value of the
+variable `generic-ignore-files-regexp'.
+
+This hook will be installed if the variable
+`generic-use-find-file-hook' is non-nil.  The variable
+`generic-lines-to-scan' determines the number of lines to look at."
+  (when (and (eq major-mode 'fundamental-mode)
+            (or (null generic-ignore-files-regexp)
+                (not (string-match
+                      generic-ignore-files-regexp
+                      (file-name-sans-versions buffer-file-name)))))
+    (save-excursion
+      (goto-char (point-min))
+      (when (re-search-forward generic-find-file-regexp
+                              (save-excursion
+                                (forward-line generic-lines-to-scan)
+                                (point)) t)
+       (goto-char (point-min))
+       (default-generic-mode)))))
 
-(and generic-define-mswindows-modes
-     (setq generic-extras-enable-list
-          (append '(bat-generic-mode
-                    ini-generic-mode
-                    inf-generic-mode
-                    rc-generic-mode
-                    reg-generic-mode
-                    rul-generic-mode
-                    hosts-generic-mode
-                    apache-conf-generic-mode
-                    apache-log-generic-mode)
-                  generic-extras-enable-list)))
-
-(and generic-define-unix-modes
-     (setq generic-extras-enable-list
-          (append '(apache-conf-generic-mode
-                    apache-log-generic-mode
-                    samba-generic-mode
-                    hosts-generic-mode
-                    fvwm-generic-mode
-                    x-resource-generic-mode
-                    alias-generic-mode
-                    inetd-conf-generic-mode
-                    etc-services-generic-mode
-                    etc-passwd-generic-mode
-                    etc-fstab-generic-mode)
-                  generic-extras-enable-list)))
+(and generic-use-find-file-hook
+    (add-hook 'find-file-hook 'generic-mode-find-file-hook))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Generic-modes
+;; Other Generic modes
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+;; If you add a generic mode to this file, put it in one of these four
+;; lists as well.
+
+(defconst generic-default-modes
+  '(apache-conf-generic-mode
+    apache-log-generic-mode
+    hosts-generic-mode
+    java-manifest-generic-mode
+    java-properties-generic-mode
+    javascript-generic-mode
+    show-tabs-generic-mode
+    vrml-generic-mode)
+  "List of generic modes that are defined by default.")
+
+(defconst generic-mswindows-modes
+  '(bat-generic-mode
+    inf-generic-mode
+    ini-generic-mode
+    rc-generic-mode
+    reg-generic-mode
+    rul-generic-mode)
+  "List of generic modes that are defined by default on MS-Windows.")
+
+(defconst generic-unix-modes
+  '(alias-generic-mode
+    etc-fstab-generic-mode
+    etc-modules-conf-generic-mode
+    etc-passwd-generic-mode
+    etc-services-generic-mode
+    etc-sudoers-generic-mode
+    fvwm-generic-mode
+    inetd-conf-generic-mode
+    mailagent-rules-generic-mode
+    mailrc-generic-mode
+    named-boot-generic-mode
+    named-database-generic-mode
+    prototype-generic-mode
+    resolve-conf-generic-mode
+    samba-generic-mode
+    x-resource-generic-mode)
+  "List of generic modes that are defined by default on Unix.")
+
+(defconst generic-other-modes
+  '(astap-generic-mode
+    ibis-generic-mode
+    pkginfo-generic-mode
+    spice-generic-mode)
+  "List of generic mode that are not defined by default.")
+
+(defcustom generic-define-mswindows-modes
+  (memq system-type '(windows-nt ms-dos))
+  "*Non-nil means the modes in `generic-mswindows-modes' will be defined.
+This is a list of MS-Windows specific generic modes.  This variable
+only affects the default value of `generic-extras-enable-list'."
+  :group 'generic-x
+  :type 'boolean
+  :version "22.1")
+(make-obsolete-variable 'generic-define-mswindows-modes 'generic-extras-enable-list "22.1")
+
+(defcustom generic-define-unix-modes
+  (not (memq system-type '(windows-nt ms-dos)))
+  "*Non-nil means the modes in `generic-unix-modes' will be defined.
+This is a list of Unix specific generic modes.  This variable only
+affects the default value of `generic-extras-enable-list'."
+  :group 'generic-x
+  :type 'boolean
+  :version "22.1")
+(make-obsolete-variable 'generic-define-unix-modes 'generic-extras-enable-list "22.1")
+
+(defcustom generic-extras-enable-list
+  (append generic-default-modes
+         (if generic-define-mswindows-modes generic-mswindows-modes)
+         (if generic-define-unix-modes generic-unix-modes)
+         nil)
+  "List of generic modes to define.
+Each entry in the list should be a symbol.  If you set this variable
+directly, without using customize, you must reload generic-x to put
+your changes into effect."
+  :group 'generic-x
+  :type (let (list)
+         (dolist (mode
+                  (sort (append generic-default-modes
+                                generic-mswindows-modes
+                                generic-unix-modes
+                                generic-other-modes
+                                nil)
+                        (lambda (a b)
+                          (string< (symbol-name b)
+                                   (symbol-name a))))
+                  (cons 'set list))
+           (push `(const ,mode) list)))
+  :set (lambda (s v)
+        (set-default s v)
+        (unless load-in-progress
+          (load "generic-x")))
+  :version "22.1")
+
 ;;; Apache
 (when (memq 'apache-conf-generic-mode generic-extras-enable-list)
 
@@ -170,8 +305,7 @@ generic-x to enable the specified modes."
            '((nil "^\\([-A-Za-z0-9_]+\\)" 1)
              ("*Directories*" "^\\s-*<Directory\\s-*\\([^>]+\\)>" 1)
              ("*Locations*"   "^\\s-*<Location\\s-*\\([^>]+\\)>" 1))))))
-  "Generic mode for Apache or HTTPD configuration files."
-  :group 'generic-x))
+  "Generic mode for Apache or HTTPD configuration files."))
 
 (when (memq 'apache-log-generic-mode generic-extras-enable-list)
 
@@ -184,8 +318,7 @@ generic-x to enable the specified modes."
      (2 font-lock-variable-name-face)))
   '("access_log\\'")
   nil
-  "Mode for Apache log files"
-  :group 'generic-x))
+  "Mode for Apache log files."))
 
 ;;; Samba
 (when (memq 'samba-generic-mode generic-extras-enable-list)
@@ -199,8 +332,7 @@ generic-x to enable the specified modes."
      (2 font-lock-type-face)))
   '("smb\\.conf\\'")
   '(generic-bracket-support)
-  "Generic mode for Samba configuration files."
-  :group 'generic-x))
+  "Generic mode for Samba configuration files."))
 
 ;;; Fvwm
 ;; This is pretty basic. Also, modes for other window managers could
@@ -225,8 +357,7 @@ generic-x to enable the specified modes."
   nil
   '("\\.fvwmrc\\'" "\\.fvwm2rc\\'")
   nil
-  "Generic mode for FVWM configuration files."
-  :group 'generic-x))
+  "Generic mode for FVWM configuration files."))
 
 ;;; X Resource
 ;; I'm pretty sure I've seen an actual mode to do this, but I don't
@@ -239,8 +370,7 @@ generic-x to enable the specified modes."
   '(("^\\([^:\n]+:\\)" 1 font-lock-variable-name-face))
   '("\\.Xdefaults\\'" "\\.Xresources\\'" "\\.Xenvironment\\'" "\\.ad\\'")
   nil
-  "Generic mode for X Resource configuration files."
-  :group 'generic-x))
+  "Generic mode for X Resource configuration files."))
 
 ;;; Hosts
 (when (memq 'hosts-generic-mode generic-extras-enable-list)
@@ -251,10 +381,13 @@ generic-x to enable the specified modes."
   '(("\\([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\\)" 1 font-lock-constant-face))
   '("[hH][oO][sS][tT][sS]\\'")
   nil
-  "Generic mode for HOSTS files."
-  :group 'generic-x))
+  "Generic mode for HOSTS files."))
 
 ;;; Windows INF files
+
+;; If i-g-m-f-f-h is defined, then so is i-g-m.
+(declare-function ini-generic-mode "generic-x")
+
 (when (memq 'inf-generic-mode generic-extras-enable-list)
 
 (define-generic-mode inf-generic-mode
@@ -263,8 +396,7 @@ generic-x to enable the specified modes."
   '(("^\\(\\[.*\\]\\)" 1 font-lock-constant-face))
   '("\\.[iI][nN][fF]\\'")
   '(generic-bracket-support)
-  "Generic mode for MS-Windows INF files."
-  :group 'generic-x))
+  "Generic mode for MS-Windows INF files."))
 
 ;;; Windows INI files
 ;; Should define escape character as well!
@@ -284,8 +416,20 @@ generic-x to enable the specified modes."
       (setq imenu-generic-expression
            '((nil "^\\[\\(.*\\)\\]" 1)
              ("*Variables*" "^\\s-*\\([^=]+\\)\\s-*=" 1))))))
-  "Generic mode for MS-Windows INI files."
-  :group 'generic-x))
+  "Generic mode for MS-Windows INI files.
+You can use `ini-generic-mode-find-file-hook' to enter this mode
+automatically for INI files whose names do not end in \".ini\".")
+
+(defun ini-generic-mode-find-file-hook ()
+  "Hook function to enter Ini-Generic mode automatically for INI files.
+Done if the first few lines of a file in Fundamental mode look
+like an INI file.  You can add this hook to `find-file-hook'."
+  (and (eq major-mode 'fundamental-mode)
+       (save-excursion
+        (goto-char (point-min))
+        (and (looking-at "^\\s-*\\[.*\\]")
+             (ini-generic-mode)))))
+(defalias 'generic-mode-ini-file-find-file-hook 'ini-generic-mode-find-file-hook))
 
 ;;; Windows REG files
 ;;; Unfortunately, Windows 95 and Windows NT have different REG file syntax!
@@ -294,7 +438,7 @@ generic-x to enable the specified modes."
 (define-generic-mode reg-generic-mode
   '(?\;)
   '("key" "classes_root" "REGEDIT" "REGEDIT4")
-  '(("\\(\\[.*]\\)"          1 font-lock-constant-face)
+  '(("\\(\\[.*\\]\\)"        1 font-lock-constant-face)
     ("^\\([^\n\r]*\\)\\s-*=" 1 font-lock-variable-name-face))
   '("\\.[rR][eE][gG]\\'")
   (list
@@ -302,8 +446,9 @@ generic-x to enable the specified modes."
     (lambda ()
       (setq imenu-generic-expression
            '((nil "^\\s-*\\(.*\\)\\s-*=" 1))))))
-  "Generic mode for MS-Windows Registry files."
-  :group 'generic-x))
+  "Generic mode for MS-Windows Registry files."))
+
+(declare-function w32-shell-name "w32-fns" ())
 
 ;;; DOS/Windows BAT files
 (when (memq 'bat-generic-mode generic-extras-enable-list)
@@ -355,7 +500,7 @@ generic-x to enable the specified modes."
        "MD"        "md"         "Md"
        "PATH"      "path"       "Path"
        "PAUSE"     "pause"      "Pause"
-       "PROMPT"            "prompt"     "Prompt"
+       "PROMPT"    "prompt"     "Prompt"
        "RD"        "rd"         "Rd"
        "REN"       "ren"        "Ren"
        "SET"       "set"        "Set"
@@ -374,17 +519,17 @@ generic-x to enable the specified modes."
        (1 font-lock-builtin-face)
        (2 font-lock-variable-name-face t t))))
   '("\\.[bB][aA][tT]\\'"
+    "\\.[cC][mM][dD]\\'"
     "\\`[cC][oO][nN][fF][iI][gG]\\."
     "\\`[aA][uU][tT][oO][eE][xX][eE][cC]\\.")
   '(generic-bat-mode-setup-function)
-  "Generic mode for MS-Windows BAT files."
-  :group 'generic-x)
+  "Generic mode for MS-Windows batch files.")
 
 (defvar bat-generic-mode-syntax-table nil
-  "Syntax table in use in bat-generic-mode buffers.")
+  "Syntax table in use in `bat-generic-mode' buffers.")
 
 (defvar bat-generic-mode-keymap (make-sparse-keymap)
-  "Keymap for bet-generic-mode.")
+  "Keymap for `bat-generic-mode'.")
 
 (defun bat-generic-mode-compile ()
   "Run the current BAT file in a compilation buffer."
@@ -396,6 +541,7 @@ generic-x to enable the specified modes."
     (compile
      (concat (w32-shell-name) " -c " (buffer-file-name)))))
 
+(eval-when-compile (require 'comint))
 (defun bat-generic-mode-run-as-comint ()
   "Run the current BAT file in a comint buffer."
   (interactive)
@@ -456,8 +602,7 @@ generic-x to enable the specified modes."
     (lambda ()
       (setq imenu-generic-expression
            '((nil "\\s-/\\([^/]+\\)/[i, \t\n]" 1))))))
-  "Mode for Mailagent rules files."
-  :group 'generic-x))
+  "Mode for Mailagent rules files."))
 
 ;; Solaris/Sys V prototype files
 (when (memq 'prototype-generic-mode generic-extras-enable-list)
@@ -480,8 +625,7 @@ generic-x to enable the specified modes."
      (2 font-lock-variable-name-face)))
   '("prototype\\'")
   nil
-  "Mode for Sys V prototype files."
-  :group 'generic-x))
+  "Mode for Sys V prototype files."))
 
 ;; Solaris/Sys V pkginfo files
 (when (memq 'pkginfo-generic-mode generic-extras-enable-list)
@@ -494,11 +638,12 @@ generic-x to enable the specified modes."
      (2 font-lock-variable-name-face)))
   '("pkginfo\\'")
   nil
-  "Mode for Sys V pkginfo files."
-  :group 'generic-x))
+  "Mode for Sys V pkginfo files."))
 
 ;; Javascript mode
 ;; Includes extra keywords from Armando Singer [asinger@MAIL.COLGATE.EDU]
+(when (memq 'javascript-generic-mode generic-extras-enable-list)
+
 (define-generic-mode javascript-generic-mode
   '("//" ("/*" . "*/"))
   '("break"
@@ -572,10 +717,11 @@ generic-x to enable the specified modes."
       (setq imenu-generic-expression
            '((nil "^function\\s-+\\([A-Za-z0-9_]+\\)" 1)
              ("*Variables*" "^var\\s-+\\([A-Za-z0-9_]+\\)" 1))))))
-  "Mode for JavaScript files."
-  :group 'generic-x)
+  "Mode for JavaScript files."))
 
 ;; VRML files
+(when (memq 'vrml-generic-mode generic-extras-enable-list)
+
 (define-generic-mode vrml-generic-mode
   '(?#)
   '("DEF"
@@ -624,10 +770,11 @@ generic-x to enable the specified modes."
              ("*Definitions*"
               "DEF\\s-+\\([-A-Za-z0-9_]+\\)\\s-+\\([A-Za-z0-9]+\\)\\s-*{"
               1))))))
-  "Generic Mode for VRML files."
-  :group 'generic-x)
+  "Generic Mode for VRML files."))
 
 ;; Java Manifests
+(when (memq 'java-manifest-generic-mode generic-extras-enable-list)
+
 (define-generic-mode java-manifest-generic-mode
   '(?#)
   '("Name"
@@ -644,10 +791,11 @@ generic-x to enable the specified modes."
      (2 font-lock-constant-face)))
   '("[mM][aA][nN][iI][fF][eE][sS][tT]\\.[mM][fF]\\'")
   nil
-  "Mode for Java Manifest files"
-  :group 'generic-x)
+  "Mode for Java Manifest files."))
 
 ;; Java properties files
+(when (memq 'java-properties-generic-mode generic-extras-enable-list)
+
 (define-generic-mode java-properties-generic-mode
   '(?! ?#)
   nil
@@ -675,8 +823,7 @@ generic-x to enable the specified modes."
     (lambda ()
       (setq imenu-generic-expression
            '((nil "^\\([^#! \t\n\r=:]+\\)" 1))))))
-  "Mode for Java properties files."
-  :group 'generic-x)
+  "Mode for Java properties files."))
 
 ;; C shell alias definitions
 (when (memq 'alias-generic-mode generic-extras-enable-list)
@@ -694,8 +841,7 @@ generic-x to enable the specified modes."
     (lambda ()
       (setq imenu-generic-expression
            '((nil "^\\(alias\\|unalias\\)\\s-+\\([-a-zA-Z0-9_]+\\)" 2))))))
-  "Mode for C Shell alias files."
-  :group 'generic-x))
+  "Mode for C Shell alias files."))
 
 ;;; Windows RC files
 ;; Contributed by ACorreir@pervasive-sw.com (Alfred Correira)
@@ -785,10 +931,9 @@ generic-x to enable the specified modes."
      '("^#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
        (1 font-lock-constant-face)
        (2 font-lock-variable-name-face nil t))))
-    '("\\.[rR][cC]$")
+    '("\\.[rR][cC]\\'")
     nil
-    "Generic mode for MS-Windows Resource files."
-    :group 'generic-x))
+    "Generic mode for MS-Windows Resource files."))
 
 ;; InstallShield RUL files
 ;; Contributed by  Alfred.Correira@Pervasive.Com
@@ -1341,7 +1486,7 @@ generic-x to enable the specified modes."
   "Function argument constants used in InstallShield 3 and 5."))
 
 (defvar rul-generic-mode-syntax-table nil
-  "Syntax table to use in rul-generic-mode buffers.")
+  "Syntax table to use in `rul-generic-mode' buffers.")
 
 (setq rul-generic-mode-syntax-table
       (make-syntax-table c++-mode-syntax-table))
@@ -1406,10 +1551,9 @@ generic-x to enable the specified modes."
      (generic-make-keywords-list
       installshield-funarg-constants-list
       font-lock-variable-name-face "[^_]" "[^_]"))) ; is this face the best choice?
-  '("\\.[rR][uU][lL]$")
+  '("\\.[rR][uU][lL]\\'")
   '(generic-rul-mode-setup-function)
-  "Generic mode for InstallShield RUL files."
-  :group 'generic-x)
+  "Generic mode for InstallShield RUL files.")
 
 (define-skeleton rul-if
   "Insert an if statement."
@@ -1436,6 +1580,8 @@ generic-x to enable the specified modes."
   > "end;"))
 
 ;; Additions by ACorreir@pervasive-sw.com (Alfred Correira)
+(when (memq 'mailrc-generic-mode generic-extras-enable-list)
+
 (define-generic-mode mailrc-generic-mode
   '(?#)
   '("alias"
@@ -1457,8 +1603,7 @@ generic-x to enable the specified modes."
      (2 font-lock-variable-name-face)))
   '("\\.mailrc\\'")
   nil
-  "Mode for mailrc files."
-  :group 'generic-x)
+  "Mode for mailrc files."))
 
 ;; Inetd.conf
 (when (memq 'inetd-conf-generic-mode generic-extras-enable-list)
@@ -1478,8 +1623,7 @@ generic-x to enable the specified modes."
    (function
     (lambda ()
       (setq imenu-generic-expression
-           '((nil "^\\([-A-Za-z0-9_]+\\)" 1))))))
-  :group 'generic-x))
+           '((nil "^\\([-A-Za-z0-9_]+\\)" 1))))))))
 
 ;; Services
 (when (memq 'etc-services-generic-mode generic-extras-enable-list)
@@ -1497,8 +1641,7 @@ generic-x to enable the specified modes."
    (function
     (lambda ()
       (setq imenu-generic-expression
-           '((nil "^\\([-A-Za-z0-9_]+\\)" 1))))))
-  :group 'generic-x))
+           '((nil "^\\([-A-Za-z0-9_]+\\)" 1))))))))
 
 ;; Password and Group files
 (when (memq 'etc-passwd-generic-mode generic-extras-enable-list)
@@ -1540,8 +1683,7 @@ generic-x to enable the specified modes."
    (function
     (lambda ()
       (setq imenu-generic-expression
-           '((nil "^\\([-A-Za-z0-9_]+\\):" 1))))))
-  :group 'generic-x))
+           '((nil "^\\([-A-Za-z0-9_]+\\):" 1))))))))
 
 ;; Fstab
 (when (memq 'etc-fstab-generic-mode generic-extras-enable-list)
@@ -1572,6 +1714,8 @@ generic-x to enable the specified modes."
     "reiserfs"
     "romfs"
     "smbfs"
+    "cifs"
+    "usbdevfs"
     "sysv"
     "tmpfs"
     "udf"
@@ -1583,33 +1727,49 @@ generic-x to enable the specified modes."
     "swap"
     "auto"
     "ignore")
-  '(("^\\([/-A-Za-z0-9_]+\\)\\s-+\\([/-A-Za-z0-9_]+\\)"
-     (1 font-lock-type-face)
-     (2 font-lock-variable-name-face)))
+  '(("^\\([^# \t]+\\)\\s-+\\([^# \t]+\\)"
+     (1 font-lock-type-face t)
+     (2 font-lock-variable-name-face t)))
   '("/etc/[v]*fstab\\'")
   (list
    (function
     (lambda ()
       (setq imenu-generic-expression
-           '((nil "^\\([/-A-Za-z0-9_]+\\)\\s-+" 1))))))
-  :group 'generic-x))
+           '((nil "^\\([^# \t]+\\)\\s-+" 1))))))))
+
+;; /etc/sudoers
+(when (memq 'etc-sudoers-generic-mode generic-extras-enable-list)
+
+(define-generic-mode etc-sudoers-generic-mode
+  '(?#)
+  '("User_Alias" "Runas_Alias" "Host_Alias"  "Cmnd_Alias"
+    "NOPASSWD" "PASSWD" "NOEXEC" "EXEC"
+    "ALL")
+  '(("\\<\\(root\\|su\\)\\>" 1 font-lock-warning-face)
+    ("\\(\\*\\)" 1 font-lock-warning-face)
+    ("\\<\\(%[A-Za-z0-9_]+\\)\\>" 1 font-lock-variable-name-face))
+  '("/etc/sudoers\\'")
+  nil
+  "Generic mode for sudoers configuration files."))
 
 ;; From Jacques Duthen <jacques.duthen@sncf.fr>
+(when (memq 'show-tabs-generic-mode generic-extras-enable-list)
+
 (eval-when-compile
 
 (defconst show-tabs-generic-mode-font-lock-defaults-1
   '(;; trailing spaces must come before...
-    ("[ \t]+$" . 'show-tabs-space-face)
+    ("[ \t]+$" . 'show-tabs-space)
     ;; ...embedded tabs
-    ("[^\n\t]\\(\t+\\)" (1 'show-tabs-tab-face))))
+    ("[^\n\t]\\(\t+\\)" (1 'show-tabs-tab))))
 
 (defconst show-tabs-generic-mode-font-lock-defaults-2
   '(;; trailing spaces must come before...
-    ("[ \t]+$" . 'show-tabs-space-face)
+    ("[ \t]+$" . 'show-tabs-space)
     ;; ...tabs
-    ("\t+" . 'show-tabs-tab-face))))
+    ("\t+" . 'show-tabs-tab))))
 
-(defface show-tabs-tab-face
+(defface show-tabs-tab
   '((((class grayscale) (background light)) (:background "DimGray"   :weight bold))
     (((class grayscale) (background dark))  (:background "LightGray" :weight bold))
     (((class color)     (min-colors 88))    (:background "red1"))
@@ -1617,8 +1777,10 @@ generic-x to enable the specified modes."
     (t (:weight bold)))
   "Font Lock mode face used to highlight TABs."
   :group 'generic-x)
+;; backward-compatibility alias
+(put 'show-tabs-tab-face 'face-alias 'show-tabs-tab)
 
-(defface show-tabs-space-face
+(defface show-tabs-space
   '((((class grayscale) (background light)) (:background "DimGray"   :weight bold))
     (((class grayscale) (background dark))  (:background "LightGray" :weight bold))
     (((class color)     (min-colors 88))    (:background "yellow1"))
@@ -1626,6 +1788,8 @@ generic-x to enable the specified modes."
     (t (:weight bold)))
   "Font Lock mode face used to highlight spaces."
   :group 'generic-x)
+;; backward-compatibility alias
+(put 'show-tabs-space-face 'face-alias 'show-tabs-space)
 
 (define-generic-mode show-tabs-generic-mode
   nil ;; no comment char
@@ -1634,13 +1798,14 @@ generic-x to enable the specified modes."
   nil ;; no auto-mode-alist
   ;; '(show-tabs-generic-mode-hook-fun)
   nil
-  "Generic mode to show tabs and trailing spaces"
-  :group 'generic-x)
+  "Generic mode to show tabs and trailing spaces."))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; DNS modes
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(when (memq 'named-boot-generic-mode generic-extras-enable-list)
+
 (define-generic-mode named-boot-generic-mode
   ;; List of comment characters
   '(?\;)
@@ -1656,8 +1821,9 @@ generic-x to enable the specified modes."
   ;; List of additional automode-alist expressions
   '("/etc/named.boot\\'")
   ;; List of set up functions to call
-  nil
-  :group 'generic-x)
+  nil))
+
+(when (memq 'named-database-generic-mode generic-extras-enable-list)
 
 (define-generic-mode named-database-generic-mode
   ;; List of comment characters
@@ -1667,11 +1833,10 @@ generic-x to enable the specified modes."
   ;; List of additional font-lock-expressions
   '(("\\([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\\)" 1 font-lock-constant-face)
     ("^\\([.A-Za-z0-9]+\\)"                 1 font-lock-variable-name-face))
-  ;; List of additional automode-alist expressions
+  ;; List of additional auto-mode-alist expressions
   nil
   ;; List of set up functions to call
-  nil
-  :group 'generic-x)
+  nil)
 
 (defvar named-database-time-string "%Y%m%d%H"
   "Timestring for named serial numbers.")
@@ -1679,7 +1844,9 @@ generic-x to enable the specified modes."
 (defun named-database-print-serial ()
   "Print a serial number based on the current date."
   (interactive)
-  (insert (format-time-string named-database-time-string (current-time))))
+  (insert (format-time-string named-database-time-string (current-time)))))
+
+(when (memq 'resolve-conf-generic-mode generic-extras-enable-list)
 
 (define-generic-mode resolve-conf-generic-mode
   ;; List of comment characters
@@ -1688,16 +1855,17 @@ generic-x to enable the specified modes."
   '("nameserver" "domain" "search" "sortlist" "options")
   ;; List of additional font-lock-expressions
   nil
-  ;; List of additional automode-alist expressions
+  ;; List of additional auto-mode-alist expressions
   '("/etc/resolv[e]?.conf\\'")
   ;; List of set up functions to call
-  nil
-  :group 'generic-x)
+  nil))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Modes for spice and common electrical engineering circuit netlist formats
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(when (memq 'spice-generic-mode generic-extras-enable-list)
+
 (define-generic-mode spice-generic-mode
   nil
   '("and"
@@ -1734,8 +1902,9 @@ generic-x to enable the specified modes."
    (function
     (lambda()
       (setq font-lock-defaults '(generic-font-lock-keywords nil t)))))
-  "Generic mode for SPICE circuit netlist files."
-  :group 'generic-x)
+  "Generic mode for SPICE circuit netlist files."))
+
+(when (memq 'ibis-generic-mode generic-extras-enable-list)
 
 (define-generic-mode ibis-generic-mode
   '(?|)
@@ -1744,8 +1913,9 @@ generic-x to enable the specified modes."
     ("\\(\\(_\\|\\w\\)+\\)\\s-*=" 1 font-lock-variable-name-face))
   '("\\.[iI][bB][sS]\\'")
   '(generic-bracket-support)
-  "Generic mode for IBIS circuit netlist files."
-  :group 'generic-x)
+  "Generic mode for IBIS circuit netlist files."))
+
+(when (memq 'astap-generic-mode generic-extras-enable-list)
 
 (define-generic-mode astap-generic-mode
   nil
@@ -1780,8 +1950,9 @@ generic-x to enable the specified modes."
    (function
     (lambda()
       (setq font-lock-defaults '(generic-font-lock-keywords nil t)))))
-  "Generic mode for ASTAP circuit netlist files."
-  :group 'generic-x)
+  "Generic mode for ASTAP circuit netlist files."))
+
+(when (memq 'etc-modules-conf-generic-mode generic-extras-enable-list)
 
 (define-generic-mode etc-modules-conf-generic-mode
   ;; List of comment characters
@@ -1823,8 +1994,7 @@ generic-x to enable the specified modes."
   ;; List of additional automode-alist expressions
   '("/etc/modules.conf" "/etc/conf.modules")
   ;; List of set up functions to call
-  nil
-  :group 'generic-x)
+  nil))
 
 (provide 'generic-x)