--- /dev/null
+(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)