From 2710ee7047c17b54f147ca478e9cc14de99514f2 Mon Sep 17 00:00:00 2001 From: mjo Date: Wed, 3 Sep 2008 15:19:05 -0400 Subject: [PATCH 1/1] Initial commit. --- nagios-mode.el | 312 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 nagios-mode.el diff --git a/nagios-mode.el b/nagios-mode.el new file mode 100644 index 0000000..26a9d9e --- /dev/null +++ b/nagios-mode.el @@ -0,0 +1,312 @@ +(require 'apropos) +(require 'regexp-opt) +(require 'font-lock) + + +;;;;;;;;;;;;;;;;;;;;;; +;; CUSTOM VARIABLES ;; +;;;;;;;;;;;;;;;;;;;;;; + +(defcustom nagios-indent-level 2 + "*Number of spaces in one indentation (tab)." + :type 'integer :group 'nagios + ) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; INDENTATION FUNCTIONS ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun nagios-indent-line(&optional flag) + "Indents a line, taking nesting into account." + (nagios-indent-to (nagios-calculate-indent)) + ) + + + +(defun nagios-indent-to(indent-column) + "Indent the current line to column indent-column." + (setq pos (point)) + (beginning-of-line) + (setq bol (point)) + (setq pos-offset (- pos bol)) + + (setq first-char-offset + (skip-chars-forward " \t")) + + (setq first-char-pos + (+ bol first-char-offset)) + + (kill-region bol first-char-pos) + + (beginning-of-line) + + (setq pos-change (- indent-column first-char-offset)) + (setq pos-offset (+ pos-offset pos-change)) + + (if (<= pos-offset indent-column) + (setq pos-offset indent-column)) + + (while (< 0 indent-column) + (insert " ") + (setq indent-column (- indent-column 1))) + + (goto-char (+ bol pos-offset)) + + ) + + + +(defun nagios-in-block() + "Determine if the point is inside of a {} block." + (setq pos (point)) + + ;; Get the position of the last opening and closing braces, with + ;; respect to the current point + (setq last-opening-brace (re-search-backward "{" nil t)) + (goto-char pos) + + (setq last-closing-brace (re-search-backward "}" nil t)) + (goto-char pos) + + ;; If either is nil (not found) just set it to -1, so the comparison + ;; doesn't die. + (if (not last-opening-brace) + (setq last-opening-brace -1)) + + (if (not last-closing-brace) + (setq last-closing-brace -1)) + + ;; If the last brace seen in the buffer is an opening brace, we're + ;; in a block. Otherwise, we aren't. + (if (>= last-closing-brace last-opening-brace) + nil + t) + ) + + + +(defun nagios-calculate-indent() + "Calculate the level of indentation." + ;; We're either inside a block, or we aren't. + + (setq indent 0) + + (if (nagios-in-block) + (setq indent nagios-indent-level)) + + (setq pos (point)) + (end-of-line) + (setq eol (point)) + (beginning-of-line) + (setq bol (point)) + + ;; Set the indentation level to 0 if we find either brace on this + ;; line. + (if (re-search-forward "[{}]" eol t) + (setq indent 0)) + + (goto-char pos) + + indent + ) + + + +;;;;;;;;;;;; +;; KEYMAP ;; +;;;;;;;;;;;; + +(defun nagios-insert-right-brace-and-indent() + "Insert a '}' character, and indent the line." + (interactive) + (insert "}") + (nagios-indent-line) + ) + + + +(defvar nagios-mode-map() + "Keymap used in nagios mode.") + +(when (not nagios-mode-map) + (setq nagios-mode-map (make-sparse-keymap)) + (define-key nagios-mode-map (read-kbd-macro "}") 'nagios-insert-right-brace-and-indent) + ) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; REGEXP TRANSFORMATIONS ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun regexp-word(regexp) + "Takes a regular expression as an argument, and adds the word boundary condition to the beginning and end of it." + + (concat "\\<\\(" regexp "\\)\\>") + ) + + + +(defun regexp-alt-raw(element-list) + "Takes a list of elements, and returns the string '\\(element1\\|element2...\\)'" + + (let ((regexp "\\(")) + (mapcar (lambda(elem) + (setq regexp (concat regexp "\\(" elem "\\)" "\\|"))) + element-list) + (concat (substring regexp 0 -2) ; Cut the last "\\|" + "\\)") + ) + ) + + + +;;;;;;;;;;;;;;;;;;;;; +;; SYNTAX PATTERNS ;; +;;;;;;;;;;;;;;;;;;;;; + +(defconst nagios-comments + (eval-when-compile + (regexp-alt-raw + '("#+.*" + ";+.*"))) + ) + + + +(defconst nagios-directives + (eval-when-compile + (regexp-opt + '("active_checks_enabled" "address" "alias" "check_command" + "check_freshness" "check_period" "checks_enabled" "command_line" + "command_name" "contact_groups" "contact_name" "contactgroup_name" + "dependent_host_name" "dependent_service_description" + "email" "event_handler" "event_handler_enabled" + "execution_failure_criteria" "first_notification" + "flap_detection_enabled" "freshness_threshold" + "friday" "high_flap_threshold" "host_name" + "host_notification_commands" + "host_notification_options" + "host_notification_period" "hostgroup_name" + "is_volatile" "last_notification" + "low_flap_threshold" "max_check_attempts" + "members" "monday" "normal_check_interval" + "notification_failure_criteria" + "notification_interval" "notification_options" + "notification_period" "notifications_enabled" + "obsess_over_service" "pager" "parallelize_check" + "parents" "passive_checks_enabled" + "process_perf_data" "retain_nonstatus_information" + "retain_status_information" "retry_check_interval" + "saturday" "service_description" + "service_notification_commands" + "service_notification_options" + "service_notification_period" "stalking_options" + "sunday" "thursday" "timeperiod_name" "tuesday" "wednesday"))) + ) + + + +(defvar nagios-macros + (eval-when-compile + (regexp-alt-raw + '("\\$CONTACT\\(NAME\\|ALIAS\\|EMAIL\\|PAGER\\)\\$" + "\\$HOST\\(NAME\\|ALIAS\\|ADDRESS\\|STATE\\)\\$" + "\\$\\(ARG\\|USER\\)\\([1-9]\\|[1-2][0-9]\\|3[0-2]\\)\\$" + "\\$SERVICE\\(DESC\\|STATE\\)\\$" + "\\$\\(OUTPUT\\|PERFDATA\\|EXECUTIONTIME\\|LATENCY\\)\\$" + "\\$NOTIFICATION\\(TYPE\\|NUMBER\\)\\$" + "\\$\\(\\(SHORT\\)?DATETIME\\|DATE\\|TIME\\|TIMET\\)\\$" + "\\$\\(LASTSTATECHANGE\\|STATETYPE\\)\\$" + "\\$ADMIN\\(EMAIL\\|PAGER\\)\\$" + "\\$\\(SERVICE\\|HOST\\)ATTEMPT\\$"))) + ) + + + +(defvar nagios-definitions + (eval-when-compile + (regexp-alt-raw + '("define +\\(host\\|service\\|timeperiod\\|contact\\|command\\)" + "define +\\(host\\|contact\\)group" + "define +\\(service\\|host\\)dependency" + "define +\\(service\\|host\\|hostgroup\\)escalation"))) + ) + + + +(defvar nagios-special + (eval-when-compile + (regexp-opt + '("name" "register" "use"))) + ) + + + +;;;;;;;;;;;;;;;;;;;;;;;; +;; FONT LOCK VARIABLE ;; +;;;;;;;;;;;;;;;;;;;;;;;; + +(defvar nagios-font-lock-keywords + (list + (cons nagios-comments font-lock-comment-face) + (cons (regexp-word nagios-directives) font-lock-variable-name-face) + (cons (regexp-word nagios-macros) font-lock-doc-face) + (cons (regexp-word nagios-definitions) font-lock-function-name-face) + (cons (regexp-word nagios-special) font-lock-keyword-face)) + + "Rules for highlighting Nagios configuration files." + ) + + + +;;;;;;;;;;;;;;;;;;;;;;;; +;; MAIN MODE FUNCTION ;; +;;;;;;;;;;;;;;;;;;;;;;;; + +(defun nagios-mode() + "Major mode for editing Nagios configuration files." + + (interactive) + + ; Initializing + (kill-all-local-variables) + + ; Setting up indentation handling + (make-local-variable 'indent-line-function) + (setq indent-line-function 'nagios-indent-line) + + ; Setting up font-locking + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults '(nagios-font-lock-keywords nil t nil nil)) + + + ; Setting up syntax recognition + (make-local-variable 'comment-start) + (make-local-variable 'comment-end) + (make-local-variable 'comment-start-skip) + + (setq comment-start "# ") + (setq comment-end "") + (setq comment-start-skip nagios-comments) + + + ;; Keyboard Mapping + (use-local-map nagios-mode-map) + + + ; Setting up syntax table + (modify-syntax-entry ?* ". 23") + (modify-syntax-entry ?/ ". 14") + + ; Final stuff, then we're done + (setq mode-name "nagios" + major-mode 'nagios-mode) + + (run-hooks 'nagios-mode-hook) + ) + + +(provide 'nagios-mode) -- 2.44.2