2 ;; nagios-mode, an Emacs mode for Nagios <http://www.nagios.org/>
3 ;; configuration files.
5 ;; Copyright Michael Orlitzky
7 ;; http://michael.orlitzky.com/
9 ;; This program is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; This program is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; http://www.fsf.org/licensing/licenses/gpl.html
28 (defcustom nagios-indent-level 2
29 "Number of spaces in one indentation (tab)."
30 :type 'integer :group 'nagios
37 (defun nagios-indent-line(&optional flag)
38 "Indents a line, taking nesting into account."
39 (nagios-indent-to (nagios-calculate-indent))
44 (defun nagios-indent-to(indent-column)
45 "Indent the current line to column indent-column."
49 (setq pos-offset (- pos bol))
51 (setq first-char-offset
52 (skip-chars-forward " \t"))
55 (+ bol first-char-offset))
57 (delete-region bol first-char-pos)
61 (setq pos-change (- indent-column first-char-offset))
62 (setq pos-offset (+ pos-offset pos-change))
64 (if (<= pos-offset indent-column)
65 (setq pos-offset indent-column))
67 (while (< 0 indent-column)
69 (setq indent-column (- indent-column 1)))
71 (goto-char (+ bol pos-offset))
77 (defun last-opening-brace()
78 ;; Get the position of the last opening brace, with
79 ;; respect to the current point.
81 (let ((lob (re-search-backward "{" nil t)))
89 (defun last-closing-brace()
90 ;; Get the position of the last closing brace, with
91 ;; respect to the current point.
93 (let ((lcb (re-search-backward "}" nil t)))
101 (defun nagios-in-block()
102 "Determine if the point is inside of a {} block."
104 ;; If the last brace seen in the buffer is an opening brace, we're
105 ;; in a block. Otherwise, we aren't.
106 (if (>= (last-closing-brace) (last-opening-brace))
113 (defun nagios-calculate-indent()
114 "Calculate the level of indentation."
115 ;; We're either inside a block, or we aren't.
119 (if (nagios-in-block)
120 (setq indent nagios-indent-level))
128 ;; Set the indentation level to 0 if we find either brace on this
130 (if (re-search-forward "[{}]" eol t)
142 (defun nagios-insert-right-brace-and-indent()
143 "Insert a '}' character, and indent the line."
150 (defvar nagios-mode-map()
151 "Keymap used in nagios mode.")
153 (when (not nagios-mode-map)
154 (setq nagios-mode-map (make-sparse-keymap))
155 (define-key nagios-mode-map
157 'nagios-insert-right-brace-and-indent)
162 ;; Regular Expression Transformations
164 (defun regexp-alt-raw(element-list)
165 "Takes a list of elements, and returns the string '\\(element1\\|element2...\\)'"
167 ;; This is necessary since regexp-opt does not accept regular
168 ;; expressions as arguments. We use regexp-opt when we can, of
171 (let ((regexp "\\("))
172 (mapcar (lambda(elem)
173 (setq regexp (concat regexp "\\(" elem "\\)" "\\|")))
175 (concat (substring regexp 0 -2) ; Cut the last "\\|"
182 (defconst nagios-directives
184 (concat "^[ \t\r\n]*"
187 '("active_checks_enabled" "address" "alias" "check_command"
188 "check_freshness" "check_interval" "check_period" "checks_enabled"
189 "command_line" "command_name" "contactgroups" "contact_groups"
190 "contactgroup_members" "contact_name" "contactgroup_name" "contacts"
191 "dependent_host_name" "dependent_service_description" "email"
192 "event_handler" "event_handler_enabled" "execution_failure_criteria"
193 "failure_prediction_enabled" "first_notification"
194 "first_notification_delay" "flap_detection_enabled" "freshness_threshold"
195 "friday" "high_flap_threshold" "host_name" "host_notification_commands"
196 "host_notification_options" "host_notification_period"
197 "host_notifications_enabled" "hostgroup_name" "hostgroups"
198 "is_volatile" "last_notification" "low_flap_threshold"
199 "max_check_attempts" "members" "monday" "normal_check_interval"
200 "notes" "notification_failure_criteria"
201 "notification_interval" "notification_options"
202 "notification_period" "notifications_enabled"
203 "obsess_over_service" "pager" "parallelize_check"
204 "parents" "passive_checks_enabled"
205 "process_perf_data" "retain_nonstatus_information"
206 "retain_status_information" "retry_check_interval"
207 "retry_interval" "saturday" "service_description"
208 "service_notification_commands" "service_notification_options"
209 "service_notification_period" "service_notifications_enabled"
210 "servicegroup_name" "stalking_options"
211 "sunday" "thursday" "timeperiod_name" "tuesday" "wednesday") t)
219 (defconst nagios-macros
259 "$CONTACTGROUPALIAS$"
260 "$CONTACTGROUPMEMBERS$"
262 "$CONTACTGROUPNAMES$"
268 "$HOSTACKAUTHORALIAS$"
269 "$HOSTACKAUTHORNAME$"
282 "$HOSTEXECUTIONTIME$"
283 "$HOSTGROUPACTIONURL$"
289 "$HOSTGROUPNOTESURL$"
294 "$HOSTNOTIFICATIONID$"
295 "$HOSTNOTIFICATIONNUMBER$"
297 "$HOSTPERCENTCHANGE$"
308 "$LASTHOSTPROBLEMID$"
310 "$LASTHOSTSTATECHANGE$"
312 "$LASTHOSTUNREACHABLE$"
315 "$LASTSERVICECRITICAL$"
316 "$LASTSERVICEEVENTID$"
318 "$LASTSERVICEPROBLEMID$"
320 "$LASTSERVICESTATECHANGE$"
321 "$LASTSERVICESTATEID$"
322 "$LASTSERVICEUNKNOWN$"
323 "$LASTSERVICEWARNING$"
327 "$LONGSERVICEOUTPUT$"
330 "$MAXSERVICEATTEMPTS$"
332 "$NOTIFICATIONAUTHOR$"
333 "$NOTIFICATIONAUTHORALIAS$"
334 "$NOTIFICATIONAUTHORNAME$"
335 "$NOTIFICATIONCOMMENT$"
336 "$NOTIFICATIONISESCALATED$"
337 "$NOTIFICATIONNUMBER$"
338 "$NOTIFICATIONRECIPIENTS$"
343 "$RETENTIONDATAFILE$"
345 "$SERVICEACKAUTHORALIAS$"
346 "$SERVICEACKAUTHORNAME$"
347 "$SERVICEACKCOMMENT$"
350 "$SERVICECHECKCOMMAND$"
353 "$SERVICEDISPLAYNAME$"
356 "$SERVICEDURATIONSEC$"
358 "$SERVICEEXECUTIONTIME$"
359 "$SERVICEGROUPACTIONURL$"
360 "$SERVICEGROUPALIAS$"
361 "$SERVICEGROUPMEMBERS$"
363 "$SERVICEGROUPNAMES$"
364 "$SERVICEGROUPNOTES$"
365 "$SERVICEGROUPNOTESURL$"
366 "$SERVICEISVOLATILE$"
370 "$SERVICENOTIFICATIONID$"
371 "$SERVICENOTIFICATIONNUMBER$"
373 "$SERVICEPERCENTCHANGE$"
375 "$SERVICEPERFDATAFILE$"
386 "$TOTALHOSTPROBLEMS$"
387 "$TOTALHOSTPROBLEMSUNHANDLED$"
389 "$TOTALHOSTSDOWNUNHANDLED$"
390 "$TOTALHOSTSERVICES$"
391 "$TOTALHOSTSERVICESCRITICAL$"
392 "$TOTALHOSTSERVICESOK$"
393 "$TOTALHOSTSERVICESUNKNOWN$"
394 "$TOTALHOSTSERVICESWARNING$"
395 "$TOTALHOSTSUNREACHABLE$"
396 "$TOTALHOSTSUNREACHABLEUNHANDLED$"
398 "$TOTALSERVICEPROBLEMS$"
399 "$TOTALSERVICEPROBLEMSUNHANDLED$"
400 "$TOTALSERVICESCRITICAL$"
401 "$TOTALSERVICESCRITICALUNHANDLED$"
403 "$TOTALSERVICESUNKNOWN$"
404 "$TOTALSERVICESUNKNOWNUNHANDLED$"
405 "$TOTALSERVICESWARNING$"
406 "$TOTALSERVICESWARNINGUNHANDLED$"
667 (defconst nagios-definitions
670 (concat "^[ \t\r\n]*"
675 "define contactgroup"
677 "define hostdependency"
678 "define hostescalation"
681 "define hostgroupescalation"
684 "define servicedependency"
685 "define serviceescalation"
686 "define serviceextinfo"
687 "define servicegroup"
688 "define timeperiod"))
690 ;; These can be "terminated" by either an opening curly
691 ;; brace, or a space.
698 (defconst nagios-special
700 (concat "^[ \t\r\n]*"
703 '("name" "register" "use") t)
710 ;; The One True Font Locking Variable
712 (defvar nagios-font-lock-keywords
714 (cons nagios-special font-lock-keyword-face)
715 (cons nagios-directives font-lock-variable-name-face)
716 (cons nagios-macros font-lock-constant-face)
717 (cons nagios-definitions '(1 font-lock-function-name-face)))
719 "Rules for highlighting Nagios configuration files."
724 (defvar nagios-mode-syntax-table nil
725 "Syntax table used in nagios-mode buffers.")
726 (if nagios-mode-syntax-table
728 (setq nagios-mode-syntax-table (make-syntax-table))
729 (modify-syntax-entry ?# "< b" nagios-mode-syntax-table) ;; Comment style 1
730 (modify-syntax-entry ?\; "< b" nagios-mode-syntax-table) ;; Comment style 2
731 (modify-syntax-entry ?\n "> b" nagios-mode-syntax-table) ;; End comment
735 ;; Main Mode Function
738 "Major mode for editing Nagios configuration files."
741 (kill-all-local-variables)
742 (make-local-variable 'font-lock-defaults)
743 (make-local-variable 'comment-start)
744 (make-local-variable 'comment-start-skip)
745 (make-local-variable 'comment-end)
746 (make-local-variable 'indent-line-function)
747 (make-local-variable 'syntax-begin-function)
749 (set-syntax-table nagios-mode-syntax-table)
751 (setq mode-name "nagios"
752 major-mode 'nagios-mode
753 indent-line-function 'nagios-indent-line
754 font-lock-defaults '(nagios-font-lock-keywords)
756 comment-start-skip "#\|; +"
759 ;; Since comments and strings do not span multiple lines,
760 ;; the syntax parser can safely start parsing at the beginning
762 syntax-begin-function 'beginning-of-line
766 (use-local-map nagios-mode-map)
768 ;; I don't /think/ I need to define this before attempting
769 ;; to run it. Users can define it if they want.
770 (run-hooks 'nagios-mode-hook)
774 (provide 'nagios-mode)