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."
40 (nagios-indent-to (nagios-calculate-indent))
44 (defun beginning-of-line-pos()
45 ;; Return the point position corresponding to the beginning
46 ;; of the current line.
53 (defun end-of-line-pos()
54 ;; Return the point position corresponding to the end
55 ;; of the current line.
63 ;; How far are we from the beginning of the line?
64 (- (point) (beginning-of-line-pos))
67 (defun first-char-offset()
68 ;; How far is the first character on this line
69 ;; from the beginning of the line?
72 (skip-chars-forward " \t")
76 (defun first-char-pos()
77 ;; What's the position of the first character on this line?
78 (+ (beginning-of-line-pos) (first-char-offset))
81 (defun nagios-indent-to(indent-column)
82 "Indent the current line to column indent-column."
83 ;; Store the point in orig-pos.
84 (let ((orig-point (point)))
86 ;; And store the offset of the first character (with respect to the
87 ;; beginning of the line) in orig-first-char-offset.
88 (let ((orig-first-char-offset (first-char-offset)))
90 ;; Delete any leading whitespace, and move the point to the
91 ;; beginning of the line.
92 (delete-region (beginning-of-line-pos) (first-char-pos))
95 ;; Now insert indent-column spaces.
96 (let ((indent-remaining indent-column))
97 (while (< 0 indent-remaining)
99 (setq indent-remaining (- indent-remaining 1)))
102 ;; The text on the current line just moved left/right some amount;
103 ;; call it text-delta. We want to move the point that same distance.
104 (let ((text-delta (- (first-char-offset) orig-first-char-offset)))
105 (goto-char (+ orig-point text-delta))
108 ;; The point should never wind up to the left of indent-column, so
109 ;; if it's there, move it over to indent-column.
110 (if (< (point-offset) indent-column)
111 (goto-char (+ (beginning-of-line-pos) indent-column))
119 (defun last-opening-brace()
120 ;; Get the position of the last opening brace, with
121 ;; respect to the current point.
123 (let ((lob (re-search-backward "{" nil t)))
131 (defun last-closing-brace()
132 ;; Get the position of the last closing brace, with
133 ;; respect to the current point.
135 (let ((lcb (re-search-backward "}" nil t)))
143 (defun nagios-in-block()
144 "Determine if the point is inside of a {} block."
146 ;; If the last brace seen in the buffer is an opening brace, we're
147 ;; in a block. Otherwise, we aren't.
148 (if (>= (last-closing-brace) (last-opening-brace))
154 (defun brace-on-line()
155 ;; Is there a curly brace on this line?
158 (re-search-forward "[{}]" (end-of-line-pos) t)
163 (defun nagios-calculate-indent()
164 "Calculate the level of indentation."
166 ;; We're either inside a block, or we aren't.
167 ;; Initialize the indent variable to either nagios-indent-level
168 ;; or 0 depending on whether or not we're in a block.
169 (let ((indent (if (nagios-in-block)
175 ;; Set the indentation level to 0 if we find either brace on this
188 (defun nagios-insert-right-brace-and-indent()
189 "Insert a '}' character, and indent the line."
196 (defvar nagios-mode-map()
197 "Keymap used in nagios mode.")
199 (when (not nagios-mode-map)
200 (setq nagios-mode-map (make-sparse-keymap))
201 (define-key nagios-mode-map
203 'nagios-insert-right-brace-and-indent)
208 (defconst nagios-directives
210 (concat "^[ \t\r\n]*"
213 '("active_checks_enabled" "address" "alias" "check_command"
214 "check_freshness" "check_interval" "check_period" "checks_enabled"
215 "command_line" "command_name" "contactgroups" "contact_groups"
216 "contactgroup_members" "contact_name" "contactgroup_name" "contacts"
217 "dependent_host_name" "dependent_service_description" "email"
218 "event_handler" "event_handler_enabled" "execution_failure_criteria"
219 "failure_prediction_enabled" "first_notification"
220 "first_notification_delay" "flap_detection_enabled" "freshness_threshold"
221 "friday" "high_flap_threshold" "host_name" "host_notification_commands"
222 "host_notification_options" "host_notification_period"
223 "host_notifications_enabled" "hostgroup_name" "hostgroups"
224 "is_volatile" "last_notification" "low_flap_threshold"
225 "max_check_attempts" "members" "monday" "normal_check_interval"
226 "notes" "notification_failure_criteria"
227 "notification_interval" "notification_options"
228 "notification_period" "notifications_enabled"
229 "obsess_over_service" "pager" "parallelize_check"
230 "parents" "passive_checks_enabled"
231 "process_perf_data" "retain_nonstatus_information"
232 "retain_status_information" "retry_check_interval"
233 "retry_interval" "saturday" "service_description"
234 "service_notification_commands" "service_notification_options"
235 "service_notification_period" "service_notifications_enabled"
236 "servicegroup_name" "stalking_options"
237 "sunday" "thursday" "timeperiod_name" "tuesday" "wednesday") t)
245 (defconst nagios-macros
285 "$CONTACTGROUPALIAS$"
286 "$CONTACTGROUPMEMBERS$"
288 "$CONTACTGROUPNAMES$"
294 "$HOSTACKAUTHORALIAS$"
295 "$HOSTACKAUTHORNAME$"
308 "$HOSTEXECUTIONTIME$"
309 "$HOSTGROUPACTIONURL$"
315 "$HOSTGROUPNOTESURL$"
320 "$HOSTNOTIFICATIONID$"
321 "$HOSTNOTIFICATIONNUMBER$"
323 "$HOSTPERCENTCHANGE$"
334 "$LASTHOSTPROBLEMID$"
336 "$LASTHOSTSTATECHANGE$"
338 "$LASTHOSTUNREACHABLE$"
341 "$LASTSERVICECRITICAL$"
342 "$LASTSERVICEEVENTID$"
344 "$LASTSERVICEPROBLEMID$"
346 "$LASTSERVICESTATECHANGE$"
347 "$LASTSERVICESTATEID$"
348 "$LASTSERVICEUNKNOWN$"
349 "$LASTSERVICEWARNING$"
353 "$LONGSERVICEOUTPUT$"
356 "$MAXSERVICEATTEMPTS$"
358 "$NOTIFICATIONAUTHOR$"
359 "$NOTIFICATIONAUTHORALIAS$"
360 "$NOTIFICATIONAUTHORNAME$"
361 "$NOTIFICATIONCOMMENT$"
362 "$NOTIFICATIONISESCALATED$"
363 "$NOTIFICATIONNUMBER$"
364 "$NOTIFICATIONRECIPIENTS$"
369 "$RETENTIONDATAFILE$"
371 "$SERVICEACKAUTHORALIAS$"
372 "$SERVICEACKAUTHORNAME$"
373 "$SERVICEACKCOMMENT$"
376 "$SERVICECHECKCOMMAND$"
379 "$SERVICEDISPLAYNAME$"
382 "$SERVICEDURATIONSEC$"
384 "$SERVICEEXECUTIONTIME$"
385 "$SERVICEGROUPACTIONURL$"
386 "$SERVICEGROUPALIAS$"
387 "$SERVICEGROUPMEMBERS$"
389 "$SERVICEGROUPNAMES$"
390 "$SERVICEGROUPNOTES$"
391 "$SERVICEGROUPNOTESURL$"
392 "$SERVICEISVOLATILE$"
396 "$SERVICENOTIFICATIONID$"
397 "$SERVICENOTIFICATIONNUMBER$"
399 "$SERVICEPERCENTCHANGE$"
401 "$SERVICEPERFDATAFILE$"
412 "$TOTALHOSTPROBLEMS$"
413 "$TOTALHOSTPROBLEMSUNHANDLED$"
415 "$TOTALHOSTSDOWNUNHANDLED$"
416 "$TOTALHOSTSERVICES$"
417 "$TOTALHOSTSERVICESCRITICAL$"
418 "$TOTALHOSTSERVICESOK$"
419 "$TOTALHOSTSERVICESUNKNOWN$"
420 "$TOTALHOSTSERVICESWARNING$"
421 "$TOTALHOSTSUNREACHABLE$"
422 "$TOTALHOSTSUNREACHABLEUNHANDLED$"
424 "$TOTALSERVICEPROBLEMS$"
425 "$TOTALSERVICEPROBLEMSUNHANDLED$"
426 "$TOTALSERVICESCRITICAL$"
427 "$TOTALSERVICESCRITICALUNHANDLED$"
429 "$TOTALSERVICESUNKNOWN$"
430 "$TOTALSERVICESUNKNOWNUNHANDLED$"
431 "$TOTALSERVICESWARNING$"
432 "$TOTALSERVICESWARNINGUNHANDLED$"
693 (defconst nagios-definitions
696 (concat "^[ \t\r\n]*"
698 "\\(" ;; Stick parenthesis around whatever comes out
699 ;; of regexp-opt. We use this to match a
700 ;; subexpression during font-lock.
704 "define contactgroup"
706 "define hostdependency"
707 "define hostescalation"
710 "define hostgroupescalation"
713 "define servicedependency"
714 "define serviceescalation"
715 "define serviceextinfo"
716 "define servicegroup"
717 "define timeperiod"))
718 ;; This closes the parentheses that we opened
719 "\\)" ;; before regexp-opt.
721 ;; These can be "terminated" by either an opening curly
722 ;; brace, or a space.
729 (defconst nagios-special
731 (concat "^[ \t\r\n]*"
734 '("name" "register" "use") t)
741 ;; The One True Font Locking Variable
743 (defvar nagios-font-lock-keywords
745 (cons nagios-special font-lock-keyword-face)
746 (cons nagios-directives font-lock-variable-name-face)
747 (cons nagios-macros font-lock-constant-face)
748 (cons nagios-definitions '(1 font-lock-function-name-face)))
750 "Rules for highlighting Nagios configuration files."
755 (defvar nagios-mode-syntax-table nil
756 "Syntax table used in nagios-mode buffers.")
757 (if nagios-mode-syntax-table
759 (setq nagios-mode-syntax-table (make-syntax-table))
760 (modify-syntax-entry ?# "< b" nagios-mode-syntax-table) ;; Comment style 1
761 (modify-syntax-entry ?\; "< b" nagios-mode-syntax-table) ;; Comment style 2
762 (modify-syntax-entry ?\n "> b" nagios-mode-syntax-table) ;; End comment
766 ;; Main Mode Function
769 "Major mode for editing Nagios configuration files."
772 (kill-all-local-variables)
773 (make-local-variable 'font-lock-defaults)
774 (make-local-variable 'comment-start)
775 (make-local-variable 'comment-start-skip)
776 (make-local-variable 'comment-end)
777 (make-local-variable 'indent-line-function)
778 (make-local-variable 'syntax-begin-function)
780 (set-syntax-table nagios-mode-syntax-table)
782 (setq mode-name "nagios"
783 major-mode 'nagios-mode
784 indent-line-function 'nagios-indent-line
785 font-lock-defaults '(nagios-font-lock-keywords)
787 comment-start-skip "#\|; +"
790 ;; Since comments and strings do not span multiple lines,
791 ;; the syntax parser can safely start parsing at the beginning
793 syntax-begin-function 'beginning-of-line
797 (use-local-map nagios-mode-map)
799 ;; I don't /think/ I need to define this before attempting
800 ;; to run it. Users can define it if they want.
801 (run-hooks 'nagios-mode-hook)
805 (provide 'nagios-mode)