;;; cfengine.el --- An Emacs major-mode for editing cfengine scripts ;;; Copyright (C) 1997 Rolf Ebert ;;; Authors: Rolf Ebert ;;; Keywords: languages ;;; Rolf Ebert's version: cfengine.el-V1_1 ;;; This file is not part of GNU Emacs or XEmacs. ;; cfengine.el 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) ;; any later version. ;; cfengine.el is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with cfengine; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;; USAGE: ;; I have the following lines in my .emacs ;; ; autoload when needed ;; (autoload 'cfengine-mode "cfengine" "" t nil) ;; ; start colour highlighting ;; ; if GNU Emacs >= 19.31 ;; ; (global-font-lock-mode t) ;; ; if XEmacs ;; (add-hook 'cfengine-mode-hook 'turn-on-font-lock) ;; ; detect file type by name (cf.*) ;; (setq auto-mode-alist (append '(("cf\\." . cfengine-mode)) ;; auto-mode-alist)) (defvar cfengine-indent 3 "*Defines the size of Cfengine indentation.") (defvar cfengine-mode-abbrev-table nil "Abbrev table used in Cfengine mode.") (define-abbrev-table 'cfengine-mode-abbrev-table ()) (defvar cfengine-mode-map () "Local keymap used for Cfengine mode.") (defvar cfengine-mode-syntax-table nil "Syntax table to be used for editing Cfengine source code.") (defvar cfengine-mode-hook nil "*List of functions to call when Cfengine mode is invoked. This is a good place to add specific bindings.") ;;;------------- ;;; functions ;;;------------- (defun cfengine-xemacs () (or (string-match "Lucid" emacs-version) (string-match "XEmacs" emacs-version))) (defun cfengine-create-syntax-table () "Create the syntax table for Cfengine mode." (setq cfengine-mode-syntax-table (make-syntax-table (standard-syntax-table))) (set-syntax-table cfengine-mode-syntax-table) ;; string ;(modify-syntax-entry ?\" "\"" cfengine-mode-syntax-table) ;(modify-syntax-entry ?\' "\"" cfengine-mode-syntax-table) ;(modify-syntax-entry ?\` "\"" cfengine-mode-syntax-table) (modify-syntax-entry ?\" "." cfengine-mode-syntax-table) (modify-syntax-entry ?\' "." cfengine-mode-syntax-table) (modify-syntax-entry ?\` "." cfengine-mode-syntax-table) ;; comment (modify-syntax-entry ?# "<" cfengine-mode-syntax-table) (modify-syntax-entry ?\f ">" cfengine-mode-syntax-table) (modify-syntax-entry ?\n ">" cfengine-mode-syntax-table) (modify-syntax-entry ?% "." cfengine-mode-syntax-table) (modify-syntax-entry ?: "." cfengine-mode-syntax-table) (modify-syntax-entry ?\; "." cfengine-mode-syntax-table) (modify-syntax-entry ?& "." cfengine-mode-syntax-table) (modify-syntax-entry ?\| "." cfengine-mode-syntax-table) (modify-syntax-entry ?+ "." cfengine-mode-syntax-table) (modify-syntax-entry ?* "." cfengine-mode-syntax-table) (modify-syntax-entry ?/ "." cfengine-mode-syntax-table) (modify-syntax-entry ?= "." cfengine-mode-syntax-table) (modify-syntax-entry ?< "." cfengine-mode-syntax-table) (modify-syntax-entry ?> "." cfengine-mode-syntax-table) (modify-syntax-entry ?$ "." cfengine-mode-syntax-table) (modify-syntax-entry ?. "." cfengine-mode-syntax-table) (modify-syntax-entry ?\\ "." cfengine-mode-syntax-table) (modify-syntax-entry ?- "." cfengine-mode-syntax-table) ;; define what belongs in symbols (modify-syntax-entry ?_ "_" cfengine-mode-syntax-table) ;; define parentheses to match (modify-syntax-entry ?\( "()" cfengine-mode-syntax-table) (modify-syntax-entry ?\) ")(" cfengine-mode-syntax-table) ) ;;;###autoload (defun cfengine-mode () "Cfengine mode is the major mode for editing Cfengine code. Bindings are as follows: Indent line '\\[cfengine-tab]' Indent line, insert newline and indent the new line. '\\[newline-and-indent]' Comments are handled using standard Emacs conventions, including: Start a comment '\\[indent-for-comment]' Comment region '\\[comment-region]' Uncomment region '\\[cfengine-uncomment-region]' Continue comment on next line '\\[indent-new-comment-line]' " (interactive) (kill-all-local-variables) (make-local-variable 'require-final-newline) (setq require-final-newline t) (make-local-variable 'comment-start) (setq comment-start "# ") ;; comment end must be set because it may hold a wrong value if ;; this buffer had been in another mode before. RE (make-local-variable 'comment-end) (setq comment-end "") (make-local-variable 'comment-start-skip) ;; used by autofill (setq comment-start-skip "#+[ \t]*") (make-local-variable 'indent-line-function) (setq indent-line-function 'cfengine-indent-current-function) (make-local-variable 'fill-column) (setq fill-column 75) (make-local-variable 'comment-column) (setq comment-column 40) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) (make-local-variable 'case-fold-search) (setq case-fold-search t) (make-local-variable 'outline-regexp) (setq outline-regexp "[^\n\^M]") (make-local-variable 'outline-level) (setq outline-level 'cfengine-outline-level) (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'cfengine-fill-comment-paragraph) ;;(make-local-variable 'adaptive-fill-regexp) (if (cfengine-xemacs) nil ; XEmacs uses properties (make-local-variable 'font-lock-defaults) (setq font-lock-defaults '((cfengine-font-lock-keywords cfengine-font-lock-keywords-1 cfengine-font-lock-keywords-2) nil t ((?\_ . "w")) beginning-of-line ))) (setq major-mode 'cfengine-mode) (setq mode-name "Cfengine") (use-local-map cfengine-mode-map) (if cfengine-mode-syntax-table (set-syntax-table cfengine-mode-syntax-table) (cfengine-create-syntax-table)) ;; add menu 'Cfengine' to the menu bar ; (cfengine-add-cfengine-menu) (run-hooks 'cfengine-mode-hook)) ;;;----------------------;;; ;;; Behaviour Of TAB Key ;;; ;;;----------------------;;; (defun cfengine-tab () "Do indenting or tabbing according to `cfengine-tab-policy'." (interactive) (cond (1 (cfengine-tab-hard)) ((eq cfengine-tab-policy 'indent-auto) (cfengine-indent-current)) )) (defun cfengine-untab () "Do dedenting or detabbing." (interactive) (cfengine-untab-hard)) (defun cfengine-indent-current-function () "Cfengine mode version of the indent-line-function." (interactive "*") (let ((starting-point (point-marker))) (cfengine-beginning-of-line) (cfengine-tab) (if (< (point) starting-point) (goto-char starting-point)) (set-marker starting-point nil) )) (defun cfengine-tab-hard () "Indent current line to next tab stop." (interactive) (save-excursion (beginning-of-line) (insert-char ? cfengine-indent)) (if (save-excursion (= (point) (progn (beginning-of-line) (point)))) (forward-char cfengine-indent))) (defun cfengine-untab-hard () "indent current line to previous tab stop." (interactive) (let ((bol (save-excursion (progn (beginning-of-line) (point)))) (eol (save-excursion (progn (end-of-line) (point))))) (indent-rigidly bol eol (- 0 cfengine-indent)))) ;;;---------------;;; ;;; Miscellaneous ;;; ;;;---------------;;; (defun cfengine-uncomment-region (beg end) "delete `comment-start' at the beginning of a line in the region." (interactive "r") (comment-region beg end -1)) ;;;----------------------- ;;; define keymap for Cfengine ;;;----------------------- (if (not cfengine-mode-map) (progn (setq cfengine-mode-map (make-sparse-keymap)) ;; Indentation and Formatting (define-key cfengine-mode-map "\C-j" 'cfengine-indent-newline-indent) (define-key cfengine-mode-map "\t" 'cfengine-tab) (if (cfengine-xemacs) (define-key cfengine-mode-map '(shift tab) 'cfengine-untab) (define-key cfengine-mode-map [S-tab] 'cfengine-untab)) ; (define-key cfengine-mode-map "\M-\C-e" 'cfengine-next-procedure) ; (define-key cfengine-mode-map "\M-\C-a" 'cfengine-previous-procedure) ; (define-key cfengine-mode-map "\C-c\C-a" 'cfengine-move-to-start) ; (define-key cfengine-mode-map "\C-c\C-e" 'cfengine-move-to-end) (define-key cfengine-mode-map "\177" 'backward-delete-char-untabify) ;; Use predefined function of emacs19 for comments (RE) (define-key cfengine-mode-map "\C-c;" 'comment-region) (define-key cfengine-mode-map "\C-c:" 'cfengine-uncomment-region) )) ;;;------------------- ;;; define menu 'Cfengine' ;;;------------------- (require 'easymenu) (defun cfengine-add-cfengine-menu () "Adds the menu 'Cfengine' to the menu bar in Cfengine mode." (easy-menu-define cfengine-mode-menu cfengine-mode-map "Menu keymap for Cfengine mode." '("Cfengine" ; ["Next Package" cfengine-next-package t] ; ["Previous Package" cfengine-previous-package t] ; ["Next Procedure" cfengine-next-procedure t] ; ["Previous Procedure" cfengine-previous-procedure t] ; ["Goto Start" cfengine-move-to-start t] ; ["Goto End" cfengine-move-to-end t] ; ["------------------" nil nil] ["Indent Current Line (TAB)" cfengine-indent-current-function t] )) (if (cfengine-xemacs) (progn (easy-menu-add cfengine-mode-menu) (setq mode-popup-menu (cons "Cfengine mode" cfengine-mode-menu))))) ;;;--------------------------------------------------- ;;; support for font-lock ;;;--------------------------------------------------- (defconst cfengine-font-lock-keywords-1 (list ;; actions (list "^[ \t]*\\([a-zA-Z0-9]+\\):[^:]" '(1 font-lock-keyword-face) ) ) "Subdued level highlighting for Cfengine mode.") (defconst cfengine-font-lock-keywords-2 (append cfengine-font-lock-keywords-1 (list ;; ;; classes = alphanum or ().|! '("^[ \t]*\\([a-zA-Z0-9_\\(\\)\\.\\|\\!]+\\)::" (1 font-lock-function-name-face)) ;; ;; variables '("\\$[{(]\\([a-zA-Z0-9_]+\\)[)}]" (1 font-lock-variable-name-face)) )) "Gaudy level highlighting for Cfengine mode.") (defvar cfengine-font-lock-keywords cfengine-font-lock-keywords-2 "Default expressions to highlight in Cfengine mode.") ;; set font-lock properties for XEmacs (if (cfengine-xemacs) (put 'cfengine-mode 'font-lock-defaults '(cfengine-font-lock-keywords nil t ((?\_ . "w")) beginning-of-line))) ;;; ;;; support for outline ;;; ;; used by outline-minor-mode (defun cfengine-outline-level () (save-excursion (skip-chars-forward "\t ") (current-column))) ;;; provide ourself (provide 'cfengine-mode) ;;; cfengine.el ends here