]> gitweb.michael.orlitzky.com - nagios-mode.git/blob - nagios-mode.el
Simplify the nagios-in-block function and eliminate some byte-compiler warnings as...
[nagios-mode.git] / nagios-mode.el
1 ;;
2 ;; nagios-mode, an Emacs mode for Nagios <http://www.nagios.org/>
3 ;; configuration files.
4 ;;
5 ;; Copyright Michael Orlitzky
6 ;;
7 ;; http://michael.orlitzky.com/
8 ;;
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.
13 ;;
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.
18 ;;
19 ;; http://www.fsf.org/licensing/licenses/gpl.html
20 ;;
21
22 (require 'font-lock)
23 (require 'regexp-opt)
24
25
26 ;; Custom Variables
27
28 (defcustom nagios-indent-level 2
29 "Number of spaces in one indentation (tab)."
30 :type 'integer :group 'nagios
31 )
32
33
34
35 ;; Indentation Voodoo
36
37 (defun nagios-indent-line(&optional flag)
38 "Indents a line, taking nesting into account."
39 (nagios-indent-to (nagios-calculate-indent))
40 )
41
42
43
44 (defun nagios-indent-to(indent-column)
45 "Indent the current line to column indent-column."
46 (setq pos (point))
47 (beginning-of-line)
48 (setq bol (point))
49 (setq pos-offset (- pos bol))
50
51 (setq first-char-offset
52 (skip-chars-forward " \t"))
53
54 (setq first-char-pos
55 (+ bol first-char-offset))
56
57 (delete-region bol first-char-pos)
58
59 (beginning-of-line)
60
61 (setq pos-change (- indent-column first-char-offset))
62 (setq pos-offset (+ pos-offset pos-change))
63
64 (if (<= pos-offset indent-column)
65 (setq pos-offset indent-column))
66
67 (while (< 0 indent-column)
68 (insert " ")
69 (setq indent-column (- indent-column 1)))
70
71 (goto-char (+ bol pos-offset))
72
73 )
74
75
76
77 (defun last-opening-brace()
78 ;; Get the position of the last opening brace, with
79 ;; respect to the current point.
80 (save-excursion
81 (let ((lob (re-search-backward "{" nil t)))
82 (if lob
83 lob
84 -1)
85 )
86 )
87 )
88
89 (defun last-closing-brace()
90 ;; Get the position of the last closing brace, with
91 ;; respect to the current point.
92 (save-excursion
93 (let ((lcb (re-search-backward "}" nil t)))
94 (if lcb
95 lcb
96 -1)
97 )
98 )
99 )
100
101 (defun nagios-in-block()
102 "Determine if the point is inside of a {} block."
103
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))
107 nil
108 t)
109 )
110
111
112
113 (defun nagios-calculate-indent()
114 "Calculate the level of indentation."
115 ;; We're either inside a block, or we aren't.
116
117 (setq indent 0)
118
119 (if (nagios-in-block)
120 (setq indent nagios-indent-level))
121
122 (setq pos (point))
123 (end-of-line)
124 (setq eol (point))
125 (beginning-of-line)
126 (setq bol (point))
127
128 ;; Set the indentation level to 0 if we find either brace on this
129 ;; line.
130 (if (re-search-forward "[{}]" eol t)
131 (setq indent 0))
132
133 (goto-char pos)
134
135 indent
136 )
137
138
139
140 ;; Keymaps
141
142 (defun nagios-insert-right-brace-and-indent()
143 "Insert a '}' character, and indent the line."
144 (interactive)
145 (insert "}")
146 (nagios-indent-line)
147 )
148
149
150 (defvar nagios-mode-map()
151 "Keymap used in nagios mode.")
152
153 (when (not nagios-mode-map)
154 (setq nagios-mode-map (make-sparse-keymap))
155 (define-key nagios-mode-map
156 (read-kbd-macro "}")
157 'nagios-insert-right-brace-and-indent)
158 )
159
160
161
162 ;; Regular Expression Transformations
163
164 (defun regexp-alt-raw(element-list)
165 "Takes a list of elements, and returns the string '\\(element1\\|element2...\\)'"
166
167 ;; This is necessary since regexp-opt does not accept regular
168 ;; expressions as arguments. We use regexp-opt when we can, of
169 ;; course.
170
171 (let ((regexp "\\("))
172 (mapcar (lambda(elem)
173 (setq regexp (concat regexp "\\(" elem "\\)" "\\|")))
174 element-list)
175 (concat (substring regexp 0 -2) ; Cut the last "\\|"
176 "\\)")
177 )
178 )
179
180
181
182 (defconst nagios-directives
183 (eval-when-compile
184 (concat "^[ \t\r\n]*"
185
186 (regexp-opt
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)
212
213 "[ \r\n\t]+")
214 )
215 )
216
217
218
219 (defconst nagios-macros
220 (eval-when-compile
221 (regexp-opt
222 '("$ADMINEMAIL$"
223 "$ADMINPAGER$"
224 "$ARG1$"
225 "$ARG10$"
226 "$ARG11$"
227 "$ARG12$"
228 "$ARG13$"
229 "$ARG14$"
230 "$ARG15$"
231 "$ARG16$"
232 "$ARG17$"
233 "$ARG18$"
234 "$ARG19$"
235 "$ARG2$"
236 "$ARG20$"
237 "$ARG21$"
238 "$ARG22$"
239 "$ARG23$"
240 "$ARG24$"
241 "$ARG25$"
242 "$ARG26$"
243 "$ARG27$"
244 "$ARG28$"
245 "$ARG29$"
246 "$ARG3$"
247 "$ARG30$"
248 "$ARG31$"
249 "$ARG32$"
250 "$ARG4$"
251 "$ARG5$"
252 "$ARG6$"
253 "$ARG7$"
254 "$ARG8$"
255 "$ARG9$"
256 "$COMMANDFILE$"
257 "$CONTACTALIAS$"
258 "$CONTACTEMAIL$"
259 "$CONTACTGROUPALIAS$"
260 "$CONTACTGROUPMEMBERS$"
261 "$CONTACTGROUPNAME$"
262 "$CONTACTGROUPNAMES$"
263 "$CONTACTNAME$"
264 "$CONTACTPAGER$"
265 "$DATE$"
266 "$EVENTSTARTTIME$"
267 "$HOSTACKAUTHOR$"
268 "$HOSTACKAUTHORALIAS$"
269 "$HOSTACKAUTHORNAME$"
270 "$HOSTACKCOMMENT$"
271 "$HOSTACTIONURL$"
272 "$HOSTADDRESS$"
273 "$HOSTALIAS$"
274 "$HOSTATTEMPT$"
275 "$HOSTCHECKCOMMAND$"
276 "$HOSTCHECKTYPE$"
277 "$HOSTDISPLAYNAME$"
278 "$HOSTDOWNTIME$"
279 "$HOSTDURATION$"
280 "$HOSTDURATIONSEC$"
281 "$HOSTEVENTID$"
282 "$HOSTEXECUTIONTIME$"
283 "$HOSTGROUPACTIONURL$"
284 "$HOSTGROUPALIAS$"
285 "$HOSTGROUPMEMBERS$"
286 "$HOSTGROUPNAME$"
287 "$HOSTGROUPNAMES$"
288 "$HOSTGROUPNOTES$"
289 "$HOSTGROUPNOTESURL$"
290 "$HOSTLATENCY$"
291 "$HOSTNAME$"
292 "$HOSTNOTES$"
293 "$HOSTNOTESURL$"
294 "$HOSTNOTIFICATIONID$"
295 "$HOSTNOTIFICATIONNUMBER$"
296 "$HOSTOUTPUT$"
297 "$HOSTPERCENTCHANGE$"
298 "$HOSTPERFDATA$"
299 "$HOSTPERFDATAFILE$"
300 "$HOSTPROBLEMID$"
301 "$HOSTSTATE$"
302 "$HOSTSTATEID$"
303 "$HOSTSTATETYPE$"
304 "$ISVALIDTIME$"
305 "$LASTHOSTCHECK$"
306 "$LASTHOSTDOWN$"
307 "$LASTHOSTEVENTID$"
308 "$LASTHOSTPROBLEMID$"
309 "$LASTHOSTSTATE$"
310 "$LASTHOSTSTATECHANGE$"
311 "$LASTHOSTSTATEID$"
312 "$LASTHOSTUNREACHABLE$"
313 "$LASTHOSTUP$"
314 "$LASTSERVICECHECK$"
315 "$LASTSERVICECRITICAL$"
316 "$LASTSERVICEEVENTID$"
317 "$LASTSERVICEOK$"
318 "$LASTSERVICEPROBLEMID$"
319 "$LASTSERVICESTATE$"
320 "$LASTSERVICESTATECHANGE$"
321 "$LASTSERVICESTATEID$"
322 "$LASTSERVICEUNKNOWN$"
323 "$LASTSERVICEWARNING$"
324 "$LOGFILE$"
325 "$LONGDATETIME$"
326 "$LONGHOSTOUTPUT$"
327 "$LONGSERVICEOUTPUT$"
328 "$MAINCONFIGFILE$"
329 "$MAXHOSTATTEMPTS$"
330 "$MAXSERVICEATTEMPTS$"
331 "$NEXTVALIDTIME$"
332 "$NOTIFICATIONAUTHOR$"
333 "$NOTIFICATIONAUTHORALIAS$"
334 "$NOTIFICATIONAUTHORNAME$"
335 "$NOTIFICATIONCOMMENT$"
336 "$NOTIFICATIONISESCALATED$"
337 "$NOTIFICATIONNUMBER$"
338 "$NOTIFICATIONRECIPIENTS$"
339 "$NOTIFICATIONTYPE$"
340 "$OBJECTCACHEFILE$"
341 "$PROCESSSTARTTIME$"
342 "$RESOURCEFILE$"
343 "$RETENTIONDATAFILE$"
344 "$SERVICEACKAUTHOR$"
345 "$SERVICEACKAUTHORALIAS$"
346 "$SERVICEACKAUTHORNAME$"
347 "$SERVICEACKCOMMENT$"
348 "$SERVICEACTIONURL$"
349 "$SERVICEATTEMPT$"
350 "$SERVICECHECKCOMMAND$"
351 "$SERVICECHECKTYPE$"
352 "$SERVICEDESC$"
353 "$SERVICEDISPLAYNAME$"
354 "$SERVICEDOWNTIME$"
355 "$SERVICEDURATION$"
356 "$SERVICEDURATIONSEC$"
357 "$SERVICEEVENTID$"
358 "$SERVICEEXECUTIONTIME$"
359 "$SERVICEGROUPACTIONURL$"
360 "$SERVICEGROUPALIAS$"
361 "$SERVICEGROUPMEMBERS$"
362 "$SERVICEGROUPNAME$"
363 "$SERVICEGROUPNAMES$"
364 "$SERVICEGROUPNOTES$"
365 "$SERVICEGROUPNOTESURL$"
366 "$SERVICEISVOLATILE$"
367 "$SERVICELATENCY$"
368 "$SERVICENOTES$"
369 "$SERVICENOTESURL$"
370 "$SERVICENOTIFICATIONID$"
371 "$SERVICENOTIFICATIONNUMBER$"
372 "$SERVICEOUTPUT$"
373 "$SERVICEPERCENTCHANGE$"
374 "$SERVICEPERFDATA$"
375 "$SERVICEPERFDATAFILE$"
376 "$SERVICEPROBLEMID$"
377 "$SERVICESTATE$"
378 "$SERVICESTATEID$"
379 "$SERVICESTATETYPE$"
380 "$SHORTDATETIME$"
381 "$STATUSDATAFILE$"
382 "$TEMPFILE$"
383 "$TEMPPATH$"
384 "$TIME$"
385 "$TIMET$"
386 "$TOTALHOSTPROBLEMS$"
387 "$TOTALHOSTPROBLEMSUNHANDLED$"
388 "$TOTALHOSTSDOWN$"
389 "$TOTALHOSTSDOWNUNHANDLED$"
390 "$TOTALHOSTSERVICES$"
391 "$TOTALHOSTSERVICESCRITICAL$"
392 "$TOTALHOSTSERVICESOK$"
393 "$TOTALHOSTSERVICESUNKNOWN$"
394 "$TOTALHOSTSERVICESWARNING$"
395 "$TOTALHOSTSUNREACHABLE$"
396 "$TOTALHOSTSUNREACHABLEUNHANDLED$"
397 "$TOTALHOSTSUP$"
398 "$TOTALSERVICEPROBLEMS$"
399 "$TOTALSERVICEPROBLEMSUNHANDLED$"
400 "$TOTALSERVICESCRITICAL$"
401 "$TOTALSERVICESCRITICALUNHANDLED$"
402 "$TOTALSERVICESOK$"
403 "$TOTALSERVICESUNKNOWN$"
404 "$TOTALSERVICESUNKNOWNUNHANDLED$"
405 "$TOTALSERVICESWARNING$"
406 "$TOTALSERVICESWARNINGUNHANDLED$"
407 "$USER1$"
408 "$USER10$"
409 "$USER100$"
410 "$USER101$"
411 "$USER102$"
412 "$USER103$"
413 "$USER104$"
414 "$USER105$"
415 "$USER106$"
416 "$USER107$"
417 "$USER108$"
418 "$USER109$"
419 "$USER11$"
420 "$USER110$"
421 "$USER111$"
422 "$USER112$"
423 "$USER113$"
424 "$USER114$"
425 "$USER115$"
426 "$USER116$"
427 "$USER117$"
428 "$USER118$"
429 "$USER119$"
430 "$USER12$"
431 "$USER120$"
432 "$USER121$"
433 "$USER122$"
434 "$USER123$"
435 "$USER124$"
436 "$USER125$"
437 "$USER126$"
438 "$USER127$"
439 "$USER128$"
440 "$USER129$"
441 "$USER13$"
442 "$USER130$"
443 "$USER131$"
444 "$USER132$"
445 "$USER133$"
446 "$USER134$"
447 "$USER135$"
448 "$USER136$"
449 "$USER137$"
450 "$USER138$"
451 "$USER139$"
452 "$USER14$"
453 "$USER140$"
454 "$USER141$"
455 "$USER142$"
456 "$USER143$"
457 "$USER144$"
458 "$USER145$"
459 "$USER146$"
460 "$USER147$"
461 "$USER148$"
462 "$USER149$"
463 "$USER15$"
464 "$USER150$"
465 "$USER151$"
466 "$USER152$"
467 "$USER153$"
468 "$USER154$"
469 "$USER155$"
470 "$USER156$"
471 "$USER157$"
472 "$USER158$"
473 "$USER159$"
474 "$USER16$"
475 "$USER160$"
476 "$USER161$"
477 "$USER162$"
478 "$USER163$"
479 "$USER164$"
480 "$USER165$"
481 "$USER166$"
482 "$USER167$"
483 "$USER168$"
484 "$USER169$"
485 "$USER17$"
486 "$USER170$"
487 "$USER171$"
488 "$USER172$"
489 "$USER173$"
490 "$USER174$"
491 "$USER175$"
492 "$USER176$"
493 "$USER177$"
494 "$USER178$"
495 "$USER179$"
496 "$USER18$"
497 "$USER180$"
498 "$USER181$"
499 "$USER182$"
500 "$USER183$"
501 "$USER184$"
502 "$USER185$"
503 "$USER186$"
504 "$USER187$"
505 "$USER188$"
506 "$USER189$"
507 "$USER19$"
508 "$USER190$"
509 "$USER191$"
510 "$USER192$"
511 "$USER193$"
512 "$USER194$"
513 "$USER195$"
514 "$USER196$"
515 "$USER197$"
516 "$USER198$"
517 "$USER199$"
518 "$USER2$"
519 "$USER20$"
520 "$USER200$"
521 "$USER201$"
522 "$USER202$"
523 "$USER203$"
524 "$USER204$"
525 "$USER205$"
526 "$USER206$"
527 "$USER207$"
528 "$USER208$"
529 "$USER209$"
530 "$USER21$"
531 "$USER210$"
532 "$USER211$"
533 "$USER212$"
534 "$USER213$"
535 "$USER214$"
536 "$USER215$"
537 "$USER216$"
538 "$USER217$"
539 "$USER218$"
540 "$USER219$"
541 "$USER22$"
542 "$USER220$"
543 "$USER221$"
544 "$USER222$"
545 "$USER223$"
546 "$USER224$"
547 "$USER225$"
548 "$USER226$"
549 "$USER227$"
550 "$USER228$"
551 "$USER229$"
552 "$USER23$"
553 "$USER230$"
554 "$USER231$"
555 "$USER232$"
556 "$USER233$"
557 "$USER234$"
558 "$USER235$"
559 "$USER236$"
560 "$USER237$"
561 "$USER238$"
562 "$USER239$"
563 "$USER24$"
564 "$USER240$"
565 "$USER241$"
566 "$USER242$"
567 "$USER243$"
568 "$USER244$"
569 "$USER245$"
570 "$USER246$"
571 "$USER247$"
572 "$USER248$"
573 "$USER249$"
574 "$USER25$"
575 "$USER250$"
576 "$USER251$"
577 "$USER252$"
578 "$USER253$"
579 "$USER254$"
580 "$USER255$"
581 "$USER256$"
582 "$USER26$"
583 "$USER27$"
584 "$USER28$"
585 "$USER29$"
586 "$USER3$"
587 "$USER30$"
588 "$USER31$"
589 "$USER32$"
590 "$USER33$"
591 "$USER34$"
592 "$USER35$"
593 "$USER36$"
594 "$USER37$"
595 "$USER38$"
596 "$USER39$"
597 "$USER4$"
598 "$USER40$"
599 "$USER41$"
600 "$USER42$"
601 "$USER43$"
602 "$USER44$"
603 "$USER45$"
604 "$USER46$"
605 "$USER47$"
606 "$USER48$"
607 "$USER49$"
608 "$USER5$"
609 "$USER50$"
610 "$USER51$"
611 "$USER52$"
612 "$USER53$"
613 "$USER54$"
614 "$USER55$"
615 "$USER56$"
616 "$USER57$"
617 "$USER58$"
618 "$USER59$"
619 "$USER6$"
620 "$USER60$"
621 "$USER61$"
622 "$USER62$"
623 "$USER63$"
624 "$USER64$"
625 "$USER65$"
626 "$USER66$"
627 "$USER67$"
628 "$USER68$"
629 "$USER69$"
630 "$USER7$"
631 "$USER70$"
632 "$USER71$"
633 "$USER72$"
634 "$USER73$"
635 "$USER74$"
636 "$USER75$"
637 "$USER76$"
638 "$USER77$"
639 "$USER78$"
640 "$USER79$"
641 "$USER8$"
642 "$USER80$"
643 "$USER81$"
644 "$USER82$"
645 "$USER83$"
646 "$USER84$"
647 "$USER85$"
648 "$USER86$"
649 "$USER87$"
650 "$USER88$"
651 "$USER89$"
652 "$USER9$"
653 "$USER90$"
654 "$USER91$"
655 "$USER92$"
656 "$USER93$"
657 "$USER94$"
658 "$USER95$"
659 "$USER96$"
660 "$USER97$"
661 "$USER98$"
662 "$USER99$")))
663 )
664
665
666
667 (defconst nagios-definitions
668 (eval-when-compile
669
670 (concat "^[ \t\r\n]*"
671
672 (regexp-alt-raw
673 '("define command"
674 "define contact"
675 "define contactgroup"
676 "define host"
677 "define hostdependency"
678 "define hostescalation"
679 "define hostextinfo"
680 "define hostgroup"
681 "define hostgroupescalation"
682 "define null"
683 "define service"
684 "define servicedependency"
685 "define serviceescalation"
686 "define serviceextinfo"
687 "define servicegroup"
688 "define timeperiod"))
689
690 ;; These can be "terminated" by either an opening curly
691 ;; brace, or a space.
692 "\\({\\| \\)")
693 )
694 )
695
696
697
698 (defconst nagios-special
699 (eval-when-compile
700 (concat "^[ \t\r\n]*"
701
702 (regexp-opt
703 '("name" "register" "use") t)
704
705 "[ \r\n\t]+"))
706 )
707
708
709
710 ;; The One True Font Locking Variable
711
712 (defvar nagios-font-lock-keywords
713 (list
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)))
718
719 "Rules for highlighting Nagios configuration files."
720 )
721
722
723
724 (defvar nagios-mode-syntax-table nil
725 "Syntax table used in nagios-mode buffers.")
726 (if nagios-mode-syntax-table
727 nil
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
732 )
733
734
735 ;; Main Mode Function
736
737 (defun nagios-mode()
738 "Major mode for editing Nagios configuration files."
739
740 (interactive)
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)
748
749 (set-syntax-table nagios-mode-syntax-table)
750
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)
755 comment-start "#"
756 comment-start-skip "#\|; +"
757 comment-end ""
758
759 ;; Since comments and strings do not span multiple lines,
760 ;; the syntax parser can safely start parsing at the beginning
761 ;; of any line.
762 syntax-begin-function 'beginning-of-line
763 )
764
765 ;; Keyboard Mapping
766 (use-local-map nagios-mode-map)
767
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)
771 )
772
773
774 (provide 'nagios-mode)