23 |
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
24 |
;; Boston, MA 02111-1307, USA. |
;; Boston, MA 02111-1307, USA. |
25 |
|
|
|
;; Purpose: |
|
|
|
|
|
;; Meta-mode to create simple major modes |
|
|
;; with basic comment and font-lock support |
|
|
|
|
26 |
;;; Commentary: |
;;; Commentary: |
27 |
|
|
28 |
;; INTRODUCTION: |
;; INTRODUCTION: |
29 |
|
;; |
30 |
;; Generic-mode is a meta-mode which can be used to define small modes |
;; The macro `define-generic-mode' can be used to define small modes |
31 |
;; which provide basic comment and font-lock support. These modes are |
;; which provide basic comment and font-lock support. These modes are |
32 |
;; intended for the many configuration files and such which are too |
;; intended for the many configuration files and such which are too |
33 |
;; small for a "real" mode, but still have a regular syntax, comment |
;; small for a "real" mode, but still have a regular syntax, comment |
63 |
;; more than this, or you find yourself writing extensive customizations, |
;; more than this, or you find yourself writing extensive customizations, |
64 |
;; perhaps you should be writing a major mode instead! |
;; perhaps you should be writing a major mode instead! |
65 |
;; |
;; |
66 |
;; LOCAL VARIABLES: |
;; EXAMPLE: |
|
;; |
|
|
;; To put a file into generic mode using local variables, use a line |
|
|
;; like this in a Local Variables block: |
|
67 |
;; |
;; |
68 |
;; mode: default-generic |
;; You can use `define-generic-mode' like this: |
|
;; |
|
|
;; Do NOT use "mode: generic"! |
|
|
;; See also "AUTOMATICALLY ENTERING GENERIC MODE" below. |
|
|
;; |
|
|
;; DEFINING NEW GENERIC MODES: |
|
|
;; |
|
|
;; Use the `define-generic-mode' function to define new modes. |
|
|
;; For example: |
|
69 |
;; |
;; |
70 |
;; (define-generic-mode 'foo-generic-mode |
;; (define-generic-mode 'foo-generic-mode |
71 |
;; (list ?%) |
;; (list ?%) |
74 |
;; (list "\\.FOO\\'") |
;; (list "\\.FOO\\'") |
75 |
;; (list 'foo-setup-function)) |
;; (list 'foo-setup-function)) |
76 |
;; |
;; |
77 |
;; defines a new generic-mode `foo-generic-mode', which has '%' as a |
;; to define a new generic-mode `foo-generic-mode', which has '%' as a |
78 |
;; comment character, and "keyword" as a keyword. When files which |
;; comment character, and "keyword" as a keyword. When files which |
79 |
;; end in '.FOO' are loaded, Emacs will go into foo-generic-mode and |
;; end in '.FOO' are loaded, Emacs will go into foo-generic-mode and |
80 |
;; call foo-setup-function. You can also use the function |
;; call foo-setup-function. You can also use the function |
81 |
;; `foo-generic-mode' (which is interactive) to put a buffer into |
;; `foo-generic-mode' (which is interactive) to put a buffer into |
82 |
;; foo-generic-mode. |
;; foo-generic-mode. |
83 |
;; |
;; |
|
;; AUTOMATICALLY ENTERING GENERIC MODE: |
|
|
;; |
|
|
;; Generic-mode 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-mode. See the variables |
|
|
;; `generic-lines-to-scan' and `generic-find-file-regexp' for |
|
|
;; customization options. |
|
|
;; |
|
84 |
;; GOTCHAS: |
;; GOTCHAS: |
85 |
;; |
;; |
86 |
;; Be careful that your font-lock definitions are correct. Getting |
;; Be careful that your font-lock definitions are correct. Getting |
87 |
;; them wrong can cause Emacs to continually attempt to fontify! This |
;; them wrong can cause Emacs to continually attempt to fontify! This |
88 |
;; problem is not specific to generic-mode. |
;; problem is not specific to generic-mode. |
|
;; |
|
89 |
|
|
90 |
;; Credit for suggestions, brainstorming, help with debugging: |
;; Credit for suggestions, brainstorming, help with debugging: |
91 |
;; ACorreir@pervasive-sw.com (Alfred Correira) |
;; ACorreir@pervasive-sw.com (Alfred Correira) |
92 |
;; Extensive cleanup by: |
;; Extensive cleanup by: |
93 |
;; Stefan Monnier (monnier+gnu/emacs@flint.cs.yale.edu) |
;; Stefan Monnier (monnier+gnu/emacs@flint.cs.yale.edu) |
94 |
;; |
|
95 |
;;; Code: |
;;; Code: |
96 |
|
|
97 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
111 |
instead (which see).") |
instead (which see).") |
112 |
|
|
113 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;; Customization Variables |
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
|
|
(defgroup generic nil |
|
|
"Define simple major modes with comment and font-lock support." |
|
|
:prefix "generic-" |
|
|
:group 'extensions) |
|
|
|
|
|
(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 |
|
|
:type 'boolean) |
|
|
|
|
|
(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 |
|
|
: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 |
|
|
: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 |
|
|
:type '(choice (const :tag "Don't check file names" nil) regexp)) |
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
114 |
;; Functions |
;; Functions |
115 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
116 |
|
|
323 |
'((nil "^\\[\\(.*\\)\\]" 1)) |
'((nil "^\\[\\(.*\\)\\]" 1)) |
324 |
imenu-case-fold-search t)) |
imenu-case-fold-search t)) |
325 |
|
|
|
;; This generic mode is always defined |
|
|
(define-generic-mode default-generic-mode (list ?#) nil nil nil nil :group 'generic) |
|
|
|
|
|
;; 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))))) |
|
|
|
|
|
(defun generic-mode-ini-file-find-file-hook () |
|
|
"Hook function to enter Default-Generic mode automatically for INI files. |
|
|
Done if the first few lines of a file in Fundamental mode look like an |
|
|
INI file. This hook is NOT installed by default." |
|
|
(and (eq major-mode 'fundamental-mode) |
|
|
(save-excursion |
|
|
(goto-char (point-min)) |
|
|
(and (looking-at "^\\s-*\\[.*\\]") |
|
|
(ini-generic-mode))))) |
|
|
|
|
|
(and generic-use-find-file-hook |
|
|
(add-hook 'find-file-hook 'generic-mode-find-file-hook)) |
|
|
|
|
326 |
;;;###autoload |
;;;###autoload |
327 |
(defun generic-make-keywords-list (keywords-list face &optional prefix suffix) |
(defun generic-make-keywords-list (keywords-list face &optional prefix suffix) |
328 |
"Return a regular expression matching the specified KEYWORDS-LIST. |
"Return a regular expression matching the specified KEYWORDS-LIST. |