Mercurial > emacs
annotate lisp/progmodes/cfengine.el @ 95948:d55ec23f052d
*** empty log message ***
| author | Glenn Morris <rgm@gnu.org> |
|---|---|
| date | Sun, 15 Jun 2008 02:53:17 +0000 |
| parents | 52b7a8c22af5 |
| children | a9dc0e7c3f2b |
| rev | line source |
|---|---|
| 52888 | 1 ;;; cfengine.el --- mode for editing Cfengine files |
| 2 | |
| 79717 | 3 ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
|
68773
dc49655f57ae
Update copyright for 2006.
Nick Roberts <nickrob@snap.net.nz>
parents:
64699
diff
changeset
|
4 ;; Free Software Foundation, Inc. |
| 52888 | 5 |
| 6 ;; Author: Dave Love <fx@gnu.org> | |
| 7 ;; Keywords: languages | |
| 8 | |
| 9 ;; This file is part of GNU Emacs. | |
| 10 | |
|
94673
52b7a8c22af5
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
79717
diff
changeset
|
11 ;; GNU Emacs is free software: you can redistribute it and/or modify |
| 52888 | 12 ;; it under the terms of the GNU General Public License as published by |
|
94673
52b7a8c22af5
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
79717
diff
changeset
|
13 ;; the Free Software Foundation, either version 3 of the License, or |
|
52b7a8c22af5
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
79717
diff
changeset
|
14 ;; (at your option) any later version. |
| 52888 | 15 |
| 16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
| 17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 ;; GNU General Public License for more details. | |
| 20 | |
| 21 ;; You should have received a copy of the GNU General Public License | |
|
94673
52b7a8c22af5
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
79717
diff
changeset
|
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
| 52888 | 23 |
| 24 ;;; Commentary: | |
| 25 | |
| 26 ;; Provides support for editing GNU Cfengine files, including | |
| 27 ;; font-locking, Imenu and indention, but with no special keybindings. | |
| 28 | |
| 29 ;; Possible customization for auto-mode selection: | |
| 30 ;; (push '(("^cfagent.conf\\'" . cfengine-mode)) auto-mode-alist) | |
| 31 ;; (push '(("^cf\\." . cfengine-mode)) auto-mode-alist) | |
| 32 | |
| 33 ;; This is not the same as the mode written by Rolf Ebert | |
| 34 ;; <ebert@waporo.muc.de>, distributed with cfengine-2.0.5. It does | |
| 35 ;; better fontification and indentation, inter alia. | |
| 36 | |
| 37 ;;; Code: | |
| 38 | |
| 39 (defgroup cfengine () | |
| 40 "Editing Cfengine files." | |
| 41 :group 'languages) | |
| 42 | |
| 43 (defcustom cfengine-indent 2 | |
| 44 "*Size of a Cfengine indentation step in columns." | |
| 45 :group 'cfengine | |
| 46 :type 'integer) | |
| 47 | |
| 48 (defcustom cfengine-mode-abbrevs nil | |
| 49 "Abbrevs for Cfengine mode." | |
| 50 :group 'cfengine | |
| 51 :type '(repeat (list (string :tag "Name") | |
| 52 (string :tag "Expansion") | |
| 53 (choice :tag "Hook" (const nil) function)))) | |
| 54 | |
| 55 ;; Taken from the doc for pre-release 2.1. | |
| 56 (eval-and-compile | |
| 57 (defconst cfengine-actions | |
| 58 '("acl" "alerts" "binservers" "broadcast" "control" "classes" "copy" | |
| 59 "defaultroute" "disks" "directories" "disable" "editfiles" "files" | |
| 60 "filters" "groups" "homeservers" "ignore" "import" "interfaces" | |
| 61 "links" "mailserver" "methods" "miscmounts" "mountables" | |
| 62 "processes" "packages" "rename" "required" "resolve" | |
| 63 "shellcommands" "tidy" "unmount" | |
| 64 ;; cfservd | |
| 65 "admit" "grant" "deny") | |
| 66 "List of the action keywords supported by Cfengine. | |
| 67 This includes those for cfservd as well as cfagent.")) | |
| 68 | |
| 69 (defvar cfengine-font-lock-keywords | |
| 70 `(;; Actions. | |
| 71 ;; List the allowed actions explicitly, so that errors are more obvious. | |
| 72 (,(concat "^[ \t]*" (eval-when-compile | |
| 73 (regexp-opt cfengine-actions t)) | |
| 74 ":") | |
| 75 1 font-lock-keyword-face) | |
| 76 ;; Classes. | |
| 77 ("^[ \t]*\\([[:alnum:]_().|!]+\\)::" 1 font-lock-function-name-face) | |
| 78 ;; Variables. | |
| 79 ("$(\\([[:alnum:]_]+\\))" 1 font-lock-variable-name-face) | |
| 80 ("${\\([[:alnum:]_]+\\)}" 1 font-lock-variable-name-face) | |
| 81 ;; Variable definitions. | |
| 82 ("\\<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1 font-lock-variable-name-face) | |
| 83 ;; File, acl &c in group: { token ... } | |
| 84 ("{[ \t]*\\([^ \t\n]+\\)" 1 font-lock-constant-face))) | |
| 85 | |
|
72799
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
86 (defconst cfengine-font-lock-syntactic-keywords |
|
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
87 ;; In the main syntax-table, backslash is marked as a punctuation, because |
|
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
88 ;; of its use in DOS-style directory separators. Here we try to recognize |
|
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
89 ;; the cases where backslash is used as an escape inside strings. |
|
75047
0e3ea59d0acd
(cfengine-font-lock-syntactic-keywords): Fix format of value.
Richard M. Stallman <rms@gnu.org>
parents:
72799
diff
changeset
|
90 '(("\\(\\(?:\\\\\\)+\\)\"" 1 "\\"))) |
|
72799
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
91 |
| 52888 | 92 (defvar cfengine-imenu-expression |
| 93 `((nil ,(concat "^[ \t]*" (eval-when-compile | |
| 94 (regexp-opt cfengine-actions t)) | |
| 95 ":[^:]") | |
| 96 1) | |
| 97 ("Variables/classes" "\\<\\([[:alnum:]_]+\\)[ \t]*=[ \t]*(" 1) | |
| 98 ("Variables/classes" "\\<define=\\([[:alnum:]_]+\\)" 1) | |
| 99 ("Variables/classes" "\\<DefineClass\\>[ \t]+\\([[:alnum:]_]+\\)" 1)) | |
| 100 "`imenu-generic-expression' for Cfengine mode.") | |
| 101 | |
| 102 (defun cfengine-outline-level () | |
| 103 "`outline-level' function for Cfengine mode." | |
| 104 (if (looking-at "[^:]+\\(?:[:]+\\)$") | |
| 105 (length (match-string 1)))) | |
| 106 | |
| 107 (defun cfengine-beginning-of-defun () | |
| 108 "`beginning-of-defun' function for Cfengine mode. | |
| 109 Treats actions as defuns." | |
|
55239
1af59a842b93
(cfengine-beginning-of-defun, cfengine-end-of-defun):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
54460
diff
changeset
|
110 (unless (<= (current-column) (current-indentation)) |
|
1af59a842b93
(cfengine-beginning-of-defun, cfengine-end-of-defun):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
54460
diff
changeset
|
111 (end-of-line)) |
| 52888 | 112 (if (re-search-backward "^[[:alpha:]]+: *$" nil t) |
| 113 (beginning-of-line) | |
| 114 (goto-char (point-min))) | |
| 115 t) | |
| 116 | |
| 117 (defun cfengine-end-of-defun () | |
| 118 "`end-of-defun' function for Cfengine mode. | |
| 119 Treats actions as defuns." | |
| 120 (end-of-line) | |
| 121 (if (re-search-forward "^[[:alpha:]]+: *$" nil t) | |
|
55239
1af59a842b93
(cfengine-beginning-of-defun, cfengine-end-of-defun):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
54460
diff
changeset
|
122 (beginning-of-line) |
| 52888 | 123 (goto-char (point-max))) |
| 124 t) | |
| 125 | |
| 126 ;; Fixme: Should get an extra indent step in editfiles BeginGroup...s. | |
| 127 | |
| 128 (defun cfengine-indent-line () | |
| 129 "Indent a line in Cfengine mode. | |
| 130 Intended as the value of `indent-line-function'." | |
| 131 (let ((pos (- (point-max) (point)))) | |
| 132 (save-restriction | |
| 133 (narrow-to-defun) | |
| 134 (back-to-indentation) | |
| 135 (cond | |
| 136 ;; Action selectors aren't indented; class selectors are | |
| 137 ;; indented one step. | |
| 138 ((looking-at "[[:alnum:]_().|!]+:\\(:\\)?") | |
| 139 (if (match-string 1) | |
| 140 (indent-line-to cfengine-indent) | |
| 141 (indent-line-to 0))) | |
| 142 ;; Outdent leading close brackets one step. | |
| 143 ((or (eq ?\} (char-after)) | |
| 144 (eq ?\) (char-after))) | |
| 145 (condition-case () | |
| 146 (indent-line-to (save-excursion | |
| 147 (forward-char) | |
| 148 (backward-sexp) | |
| 149 (current-column))) | |
| 150 (error nil))) | |
| 151 ;; Inside brackets/parens: indent to start column of non-comment | |
| 152 ;; token on line following open bracket or by one step from open | |
| 153 ;; bracket's column. | |
| 154 ((condition-case () | |
| 155 (progn (indent-line-to (save-excursion | |
| 156 (backward-up-list) | |
| 157 (forward-char) | |
| 158 (skip-chars-forward " \t") | |
| 159 (if (looking-at "[^\n#]") | |
| 160 (current-column) | |
| 161 (skip-chars-backward " \t") | |
| 162 (+ (current-column) -1 | |
| 163 cfengine-indent)))) | |
| 164 t) | |
| 165 (error nil))) | |
| 166 ;; Indent by two steps after a class selector. | |
| 167 ((save-excursion | |
| 168 (re-search-backward "^[ \t]*[[:alnum:]_().|!]+::" nil t)) | |
| 169 (indent-line-to (* 2 cfengine-indent))) | |
| 170 ;; Indent by one step if we're after an action header. | |
| 171 ((save-excursion | |
| 172 (goto-char (point-min)) | |
| 173 (looking-at "[[:alpha:]]+:[ \t]*$")) | |
| 174 (indent-line-to cfengine-indent)) | |
| 175 ;; Else don't indent. | |
| 176 (t | |
| 177 (indent-line-to 0)))) | |
| 178 ;; If initial point was within line's indentation, | |
| 179 ;; position after the indentation. Else stay at same point in text. | |
| 180 (if (> (- (point-max) pos) (point)) | |
| 181 (goto-char (- (point-max) pos))))) | |
| 182 | |
|
59996
aac0a33f5772
Change release version from 21.4 to 22.1 throughout.
Kim F. Storm <storm@cua.dk>
parents:
59241
diff
changeset
|
183 ;; This doesn't work too well in Emacs 21.2. See 22.1 development |
| 52888 | 184 ;; code. |
| 185 (defun cfengine-fill-paragraph (&optional justify) | |
| 186 "Fill `paragraphs' in Cfengine code." | |
| 187 (interactive "P") | |
| 188 (or (if (fboundp 'fill-comment-paragraph) | |
| 189 (fill-comment-paragraph justify) ; post Emacs 21.3 | |
| 190 ;; else do nothing in a comment | |
| 191 (nth 4 (parse-partial-sexp (save-excursion | |
| 192 (beginning-of-defun) | |
| 193 (point)) | |
| 194 (point)))) | |
| 195 (let ((paragraph-start | |
| 196 ;; Include start of parenthesized block. | |
| 197 "\f\\|[ \t]*$\\|.*\(") | |
| 198 (paragraph-separate | |
| 199 ;; Include action and class lines, start and end of | |
| 200 ;; bracketed blocks and end of parenthesized blocks to | |
| 201 ;; avoid including these in fill. This isn't ideal. | |
| 202 "[ \t\f]*$\\|.*#\\|.*[\){}]\\|\\s-*[[:alpha:]_().|!]+:") | |
| 203 fill-paragraph-function) | |
| 204 (fill-paragraph justify)) | |
| 205 t)) | |
| 206 | |
| 207 ;;;###autoload | |
| 208 (define-derived-mode cfengine-mode fundamental-mode "Cfengine" | |
| 209 "Major mode for editing cfengine input. | |
| 210 There are no special keybindings by default. | |
| 211 | |
| 212 Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves | |
| 213 to the action header." | |
| 214 (modify-syntax-entry ?# "<" cfengine-mode-syntax-table) | |
| 215 (modify-syntax-entry ?\n ">#" cfengine-mode-syntax-table) | |
| 216 ;; Shell commands can be quoted by single, double or back quotes. | |
| 217 ;; It's debatable whether we should define string syntax, but it | |
| 218 ;; should avoid potential confusion in some cases. | |
| 219 (modify-syntax-entry ?\" "\"" cfengine-mode-syntax-table) | |
| 220 (modify-syntax-entry ?\' "\"" cfengine-mode-syntax-table) | |
| 221 (modify-syntax-entry ?\` "\"" cfengine-mode-syntax-table) | |
| 222 ;; variable substitution: | |
| 223 (modify-syntax-entry ?$ "." cfengine-mode-syntax-table) | |
| 224 ;; Doze path separators: | |
|
72799
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
225 (modify-syntax-entry ?\\ "." cfengine-mode-syntax-table) |
| 52888 | 226 ;; Otherwise, syntax defaults seem OK to give reasonable word |
| 227 ;; movement. | |
| 228 | |
| 229 (set (make-local-variable 'parens-require-spaces) nil) | |
|
59241
685fd8697e78
(cfengine-mode): Use mode-require-final-newline.
Richard M. Stallman <rms@gnu.org>
parents:
55239
diff
changeset
|
230 (set (make-local-variable 'require-final-newline) mode-require-final-newline) |
| 52888 | 231 (set (make-local-variable 'comment-start) "# ") |
| 232 (set (make-local-variable 'comment-start-skip) | |
| 233 "\\(\\(?:^\\|[^\\\\\n]\\)\\(?:\\\\\\\\\\)*\\)#+[ \t]*") | |
| 234 (set (make-local-variable 'indent-line-function) #'cfengine-indent-line) | |
| 235 (set (make-local-variable 'outline-regexp) "[ \t]*\\(\\sw\\|\\s_\\)+:+") | |
| 236 (set (make-local-variable 'outline-level) #'cfengine-outline-level) | |
| 237 (set (make-local-variable 'fill-paragraph-function) | |
| 238 #'cfengine-fill-paragraph) | |
| 239 (define-abbrev-table 'cfengine-mode-abbrev-table cfengine-mode-abbrevs) | |
| 240 ;; Fixme: Use `font-lock-syntactic-keywords' to set the args of | |
| 241 ;; functions in evaluated classes to string syntax, and then obey | |
| 242 ;; syntax properties. | |
| 243 (setq font-lock-defaults | |
|
72799
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
244 '(cfengine-font-lock-keywords nil nil nil beginning-of-line |
|
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
245 (font-lock-syntactic-keywords |
|
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
246 . cfengine-font-lock-syntactic-keywords))) |
| 52888 | 247 (setq imenu-generic-expression cfengine-imenu-expression) |
| 248 (set (make-local-variable 'beginning-of-defun-function) | |
| 249 #'cfengine-beginning-of-defun) | |
|
54460
82f7cd1ab4eb
(cfengine-mode): Set parse-sexp-ignore-comments.
Juanma Barranquero <lekktu@gmail.com>
parents:
52910
diff
changeset
|
250 (set (make-local-variable 'end-of-defun-function) #'cfengine-end-of-defun) |
|
82f7cd1ab4eb
(cfengine-mode): Set parse-sexp-ignore-comments.
Juanma Barranquero <lekktu@gmail.com>
parents:
52910
diff
changeset
|
251 ;; Like Lisp mode. Without this, we lose with, say, |
|
82f7cd1ab4eb
(cfengine-mode): Set parse-sexp-ignore-comments.
Juanma Barranquero <lekktu@gmail.com>
parents:
52910
diff
changeset
|
252 ;; `backward-up-list' when there's an unbalanced quote in a |
|
82f7cd1ab4eb
(cfengine-mode): Set parse-sexp-ignore-comments.
Juanma Barranquero <lekktu@gmail.com>
parents:
52910
diff
changeset
|
253 ;; preceding comment. |
|
82f7cd1ab4eb
(cfengine-mode): Set parse-sexp-ignore-comments.
Juanma Barranquero <lekktu@gmail.com>
parents:
52910
diff
changeset
|
254 (set (make-local-variable 'parse-sexp-ignore-comments) t)) |
| 52888 | 255 |
| 256 (provide 'cfengine) | |
| 257 | |
|
72799
ff69721bef4a
(cfengine-font-lock-syntactic-keywords): New var.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
68773
diff
changeset
|
258 ;; arch-tag: 6b931be2-1505-4124-afa6-9675971e26d4 |
| 52888 | 259 ;;; cfengine.el ends here |
