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))
43 (defun beginning-of-line-pos()
44 ;; Return the point position corresponding to the beginning
45 ;; of the current line.
53 ;; How far are we from the beginning of the line?
54 (- (point) (beginning-of-line-pos))
58 (defun first-char-offset()
59 ;; How far is the first character on this line
60 ;; from the beginning of the line?
62 (+ (pos-offset) (skip-chars-forward " \t"))
66 (defun first-char-pos()
67 ;; What's the position of the first character on this line?
68 (+ (beginning-of-line-pos) (first-char-offset))
71 (defun nagios-indent-to(indent-column)
72 "Indent the current line to column indent-column."
74 ;; Store the point in orig-pos.
75 (let ((orig-pos (point)))
77 ;; And store the offset of the first character (with respect to the
78 ;; beginning of the line) in orig-first-char-offset.
79 (let ((orig-first-char-offset (first-char-offset)))
81 ;; Delete any leading whitespace, and move the point to the
82 ;; beginning of the line.
83 (delete-region (beginning-of-line-pos) (first-char-pos))
86 ;; Now insert indent-column spaces.
87 (while (< 0 indent-column)
89 (setq indent-column (- indent-column 1)))
91 ;; The text on the current line just moved left/right some amount;
92 ;; call it text-delta. We want to move the point that same distance.
93 (let ((text-delta ((first-char-offset) - orig-first-char-offset)))
94 (goto-char (+ orig-point text-delta))
102 (defun last-opening-brace()
103 ;; Get the position of the last opening brace, with
104 ;; respect to the current point.
106 (let ((lob (re-search-backward "{" nil t)))
114 (defun last-closing-brace()
115 ;; Get the position of the last closing brace, with
116 ;; respect to the current point.
118 (let ((lcb (re-search-backward "}" nil t)))
126 (defun nagios-in-block()
127 "Determine if the point is inside of a {} block."
129 ;; If the last brace seen in the buffer is an opening brace, we're
130 ;; in a block. Otherwise, we aren't.
131 (if (>= (last-closing-brace) (last-opening-brace))
138 (defun nagios-calculate-indent()
139 "Calculate the level of indentation."
140 ;; We're either inside a block, or we aren't.
144 (if (nagios-in-block)
145 (setq indent nagios-indent-level))
153 ;; Set the indentation level to 0 if we find either brace on this
155 (if (re-search-forward "[{}]" eol t)
167 (defun nagios-insert-right-brace-and-indent()
168 "Insert a '}' character, and indent the line."
175 (defvar nagios-mode-map()
176 "Keymap used in nagios mode.")
178 (when (not nagios-mode-map)
179 (setq nagios-mode-map (make-sparse-keymap))
180 (define-key nagios-mode-map
182 'nagios-insert-right-brace-and-indent)
187 (defconst nagios-directives
189 (concat "^[ \t\r\n]*"
192 '("active_checks_enabled" "address" "alias" "check_command"
193 "check_freshness" "check_interval" "check_period" "checks_enabled"
194 "command_line" "command_name" "contactgroups" "contact_groups"
195 "contactgroup_members" "contact_name" "contactgroup_name" "contacts"
196 "dependent_host_name" "dependent_service_description" "email"
197 "event_handler" "event_handler_enabled" "execution_failure_criteria"
198 "failure_prediction_enabled" "first_notification"
199 "first_notification_delay" "flap_detection_enabled" "freshness_threshold"
200 "friday" "high_flap_threshold" "host_name" "host_notification_commands"
201 "host_notification_options" "host_notification_period"
202 "host_notifications_enabled" "hostgroup_name" "hostgroups"
203 "is_volatile" "last_notification" "low_flap_threshold"
204 "max_check_attempts" "members" "monday" "normal_check_interval"
205 "notes" "notification_failure_criteria"
206 "notification_interval" "notification_options"
207 "notification_period" "notifications_enabled"
208 "obsess_over_service" "pager" "parallelize_check"
209 "parents" "passive_checks_enabled"
210 "process_perf_data" "retain_nonstatus_information"
211 "retain_status_information" "retry_check_interval"
212 "retry_interval" "saturday" "service_description"
213 "service_notification_commands" "service_notification_options"
214 "service_notification_period" "service_notifications_enabled"
215 "servicegroup_name" "stalking_options"
216 "sunday" "thursday" "timeperiod_name" "tuesday" "wednesday") t)
224 (defconst nagios-macros
264 "$CONTACTGROUPALIAS$"
265 "$CONTACTGROUPMEMBERS$"
267 "$CONTACTGROUPNAMES$"
273 "$HOSTACKAUTHORALIAS$"
274 "$HOSTACKAUTHORNAME$"
287 "$HOSTEXECUTIONTIME$"
288 "$HOSTGROUPACTIONURL$"
294 "$HOSTGROUPNOTESURL$"
299 "$HOSTNOTIFICATIONID$"
300 "$HOSTNOTIFICATIONNUMBER$"
302 "$HOSTPERCENTCHANGE$"
313 "$LASTHOSTPROBLEMID$"
315 "$LASTHOSTSTATECHANGE$"
317 "$LASTHOSTUNREACHABLE$"
320 "$LASTSERVICECRITICAL$"
321 "$LASTSERVICEEVENTID$"
323 "$LASTSERVICEPROBLEMID$"
325 "$LASTSERVICESTATECHANGE$"
326 "$LASTSERVICESTATEID$"
327 "$LASTSERVICEUNKNOWN$"
328 "$LASTSERVICEWARNING$"
332 "$LONGSERVICEOUTPUT$"
335 "$MAXSERVICEATTEMPTS$"
337 "$NOTIFICATIONAUTHOR$"
338 "$NOTIFICATIONAUTHORALIAS$"
339 "$NOTIFICATIONAUTHORNAME$"
340 "$NOTIFICATIONCOMMENT$"
341 "$NOTIFICATIONISESCALATED$"
342 "$NOTIFICATIONNUMBER$"
343 "$NOTIFICATIONRECIPIENTS$"
348 "$RETENTIONDATAFILE$"
350 "$SERVICEACKAUTHORALIAS$"
351 "$SERVICEACKAUTHORNAME$"
352 "$SERVICEACKCOMMENT$"
355 "$SERVICECHECKCOMMAND$"
358 "$SERVICEDISPLAYNAME$"
361 "$SERVICEDURATIONSEC$"
363 "$SERVICEEXECUTIONTIME$"
364 "$SERVICEGROUPACTIONURL$"
365 "$SERVICEGROUPALIAS$"
366 "$SERVICEGROUPMEMBERS$"
368 "$SERVICEGROUPNAMES$"
369 "$SERVICEGROUPNOTES$"
370 "$SERVICEGROUPNOTESURL$"
371 "$SERVICEISVOLATILE$"
375 "$SERVICENOTIFICATIONID$"
376 "$SERVICENOTIFICATIONNUMBER$"
378 "$SERVICEPERCENTCHANGE$"
380 "$SERVICEPERFDATAFILE$"
391 "$TOTALHOSTPROBLEMS$"
392 "$TOTALHOSTPROBLEMSUNHANDLED$"
394 "$TOTALHOSTSDOWNUNHANDLED$"
395 "$TOTALHOSTSERVICES$"
396 "$TOTALHOSTSERVICESCRITICAL$"
397 "$TOTALHOSTSERVICESOK$"
398 "$TOTALHOSTSERVICESUNKNOWN$"
399 "$TOTALHOSTSERVICESWARNING$"
400 "$TOTALHOSTSUNREACHABLE$"
401 "$TOTALHOSTSUNREACHABLEUNHANDLED$"
403 "$TOTALSERVICEPROBLEMS$"
404 "$TOTALSERVICEPROBLEMSUNHANDLED$"
405 "$TOTALSERVICESCRITICAL$"
406 "$TOTALSERVICESCRITICALUNHANDLED$"
408 "$TOTALSERVICESUNKNOWN$"
409 "$TOTALSERVICESUNKNOWNUNHANDLED$"
410 "$TOTALSERVICESWARNING$"
411 "$TOTALSERVICESWARNINGUNHANDLED$"
672 (defconst nagios-definitions
675 (concat "^[ \t\r\n]*"
677 "\\(" ;; Stick parenthesis around whatever comes out
678 ;; of regexp-opt. We use this to match a
679 ;; subexpression during font-lock.
683 "define contactgroup"
685 "define hostdependency"
686 "define hostescalation"
689 "define hostgroupescalation"
692 "define servicedependency"
693 "define serviceescalation"
694 "define serviceextinfo"
695 "define servicegroup"
696 "define timeperiod"))
697 ;; This closes the parentheses that we opened
698 "\\)" ;; before regexp-opt.
700 ;; These can be "terminated" by either an opening curly
701 ;; brace, or a space.
708 (defconst nagios-special
710 (concat "^[ \t\r\n]*"
713 '("name" "register" "use") t)
720 ;; The One True Font Locking Variable
722 (defvar nagios-font-lock-keywords
724 (cons nagios-special font-lock-keyword-face)
725 (cons nagios-directives font-lock-variable-name-face)
726 (cons nagios-macros font-lock-constant-face)
727 (cons nagios-definitions '(1 font-lock-function-name-face)))
729 "Rules for highlighting Nagios configuration files."
734 (defvar nagios-mode-syntax-table nil
735 "Syntax table used in nagios-mode buffers.")
736 (if nagios-mode-syntax-table
738 (setq nagios-mode-syntax-table (make-syntax-table))
739 (modify-syntax-entry ?# "< b" nagios-mode-syntax-table) ;; Comment style 1
740 (modify-syntax-entry ?\; "< b" nagios-mode-syntax-table) ;; Comment style 2
741 (modify-syntax-entry ?\n "> b" nagios-mode-syntax-table) ;; End comment
745 ;; Main Mode Function
748 "Major mode for editing Nagios configuration files."
751 (kill-all-local-variables)
752 (make-local-variable 'font-lock-defaults)
753 (make-local-variable 'comment-start)
754 (make-local-variable 'comment-start-skip)
755 (make-local-variable 'comment-end)
756 (make-local-variable 'indent-line-function)
757 (make-local-variable 'syntax-begin-function)
759 (set-syntax-table nagios-mode-syntax-table)
761 (setq mode-name "nagios"
762 major-mode 'nagios-mode
763 indent-line-function 'nagios-indent-line
764 font-lock-defaults '(nagios-font-lock-keywords)
766 comment-start-skip "#\|; +"
769 ;; Since comments and strings do not span multiple lines,
770 ;; the syntax parser can safely start parsing at the beginning
772 syntax-begin-function 'beginning-of-line
776 (use-local-map nagios-mode-map)
778 ;; I don't /think/ I need to define this before attempting
779 ;; to run it. Users can define it if they want.
780 (run-hooks 'nagios-mode-hook)
784 (provide 'nagios-mode)