(defun nagios-indent-line(&optional flag)
"Indents a line, taking nesting into account."
+ (interactive)
(nagios-indent-to (nagios-calculate-indent))
)
+(defun nagios-beginning-of-line-pos()
+ ;; Return the point position corresponding to the beginning
+ ;; of the current line.
+ (save-excursion
+ (beginning-of-line)
+ (point)
+ )
+)
+
+(defun nagios-end-of-line-pos()
+ ;; Return the point position corresponding to the end
+ ;; of the current line.
+ (save-excursion
+ (end-of-line)
+ (point)
+ )
+)
+
+(defun nagios-point-offset()
+ ;; How far are we from the beginning of the line?
+ (- (point) (nagios-beginning-of-line-pos))
+)
+
+(defun nagios-first-char-offset()
+ ;; How far is the first character on this line
+ ;; from the beginning of the line?
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ )
+)
+
+(defun nagios-first-char-pos()
+ ;; What's the position of the first character on this line?
+ (+ (nagios-beginning-of-line-pos) (nagios-first-char-offset))
+)
(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))
+ ;; Store the point in orig-pos.
+ (let ((orig-point (point)))
+
+ ;; And store the offset of the first character (with respect to the
+ ;; beginning of the line) in orig-first-char-offset.
+ (let ((orig-first-char-offset (nagios-first-char-offset)))
+
+ ;; Delete any leading whitespace, and move the point to the
+ ;; beginning of the line.
+ (delete-region (nagios-beginning-of-line-pos) (nagios-first-char-pos))
+ (beginning-of-line)
+
+ ;; Now insert indent-column spaces.
+ (let ((indent-remaining indent-column))
+ (while (< 0 indent-remaining)
+ (insert " ")
+ (setq indent-remaining (- indent-remaining 1)))
+ )
+
+ ;; The text on the current line just moved left/right some amount;
+ ;; call it text-delta. We want to move the point that same distance.
+ (let ((text-delta (- (nagios-first-char-offset) orig-first-char-offset)))
+ (goto-char (+ orig-point text-delta))
+ )
+
+ ;; The point should never wind up to the left of indent-column, so
+ ;; if it's there, move it over to indent-column.
+ (if (< (nagios-point-offset) indent-column)
+ (goto-char (+ (nagios-beginning-of-line-pos) indent-column))
+ )
+ )
+ )
+)
+
- (setq first-char-offset
- (skip-chars-forward " \t"))
+(defun nagios-char-is-commented(pos)
+ "True if the character at position pos is commented, nil otherwise."
+ (save-excursion
+ (goto-char pos)
+ (re-search-backward "\\(#\\|;\\)" (nagios-beginning-of-line-pos) t)
+ )
+)
- (setq first-char-pos
- (+ bol first-char-offset))
-
- (delete-region bol first-char-pos)
-
- (beginning-of-line)
+(defun nagios-char-is-commented-and-valid(pos)
+ "True if the character at position pos is commented and non-nil.
+ Nil otherwise."
+ (if (eq nil pos)
+ nil
+ (nagios-char-is-commented pos)
+ )
+)
- (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)))
+(defun nagios-last-opening-brace()
+ "Returns the position of the last opening brace, with
+ respect to the current point. Ignores braces which
+ are commented out."
+ (save-excursion
+ (let ((lob (re-search-backward "{" nil t)))
- (goto-char (+ bol pos-offset))
+ (while (nagios-char-is-commented-and-valid lob)
+ (goto-char lob)
+ (setq lob (re-search-backward "{" nil t))
+ )
+ (if lob
+ lob
+ -1)
+ )
)
+)
+(defun nagios-last-closing-brace()
+ "Get the position of the last closing brace, with
+ respect to the current point. Ignores braces which
+ are commented out."
+ (save-excursion
+ (let ((lcb (re-search-backward "}" nil t)))
-(defun nagios-in-block()
- "Determine if the point is inside of a {} block."
+ (while (nagios-char-is-commented-and-valid lcb)
+ (goto-char lcb)
+ (setq lcb (re-search-backward "}" nil t))
+ )
- (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 lcb
+ lcb
+ -1)
+ )
+ )
+)
- ;; 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))
+(defun nagios-in-block()
+ "Determine if the point is inside of a {} block."
;; 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)
+ (if (>= (nagios-last-closing-brace) (nagios-last-opening-brace))
nil
- t)
- )
+ t)
+)
+(defun nagios-brace-on-line()
+ ;; Is there a curly brace on this line?
+ (save-excursion
+ (beginning-of-line)
+ (re-search-forward "[{}]" (nagios-end-of-line-pos) 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
+ ;; We're either inside a block, or we aren't.
+ ;; Initialize the indent variable to either nagios-indent-level
+ ;; or 0 depending on whether or not we're in a block.
+ (let ((indent (if (nagios-in-block)
+ nagios-indent-level
+ 0)
+ )
+ )
+
+ ;; Set the indentation level to 0 if we find either brace on this
+ ;; line and.
+ (if (and (nagios-brace-on-line)
+ (not (nagios-char-is-commented (nagios-brace-on-line))))
+ 0
+ indent
+ )
)
-
+)
;; Keymaps
(read-kbd-macro "}")
'nagios-insert-right-brace-and-indent)
)
-
-
-
-;; Regular Expression Transformations
-
-(defun regexp-alt-raw(element-list)
- "Takes a list of elements, and returns the string '\\(element1\\|element2...\\)'"
-
- ;; This is necessary since regexp-opt does not accept regular
- ;; expressions as arguments. We use regexp-opt when we can, of
- ;; course.
-
- (let ((regexp "\\("))
- (mapcar (lambda(elem)
- (setq regexp (concat regexp "\\(" elem "\\)" "\\|")))
- element-list)
- (concat (substring regexp 0 -2) ; Cut the last "\\|"
- "\\)")
- )
- )
(concat "^[ \t\r\n]*"
- (regexp-alt-raw
- '("define command"
- "define contact"
- "define contactgroup"
- "define host"
- "define hostdependency"
- "define hostescalation"
- "define hostextinfo"
- "define hostgroup"
- "define hostgroupescalation"
- "define null"
- "define service"
- "define servicedependency"
- "define serviceescalation"
- "define serviceextinfo"
- "define servicegroup"
- "define timeperiod"))
-
- ;; These can be "terminated" by either an opening curly
- ;; brace, or a space.
- "\\({\\| \\)")
+ "\\(" ;; Stick parenthesis around whatever comes out
+ ;; of regexp-opt. We use this to match a
+ ;; subexpression during font-lock.
+ (regexp-opt
+ '("define command"
+ "define contact"
+ "define contactgroup"
+ "define host"
+ "define hostdependency"
+ "define hostescalation"
+ "define hostextinfo"
+ "define hostgroup"
+ "define null"
+ "define service"
+ "define servicedependency"
+ "define serviceescalation"
+ "define serviceextinfo"
+ "define servicegroup"
+ "define timeperiod"))
+ ;; This closes the parentheses that we opened
+ "\\)" ;; before regexp-opt.
+
+ ;; These can be "terminated" by either an opening curly
+ ;; brace, or a space.
+ "\\({\\| \\)")
)
)
(make-local-variable 'syntax-begin-function)
(set-syntax-table nagios-mode-syntax-table)
-
+
(setq mode-name "nagios"
major-mode 'nagios-mode
indent-line-function 'nagios-indent-line
comment-start "#"
comment-start-skip "#\|; +"
comment-end ""
-
+
;; Since comments and strings do not span multiple lines,
;; the syntax parser can safely start parsing at the beginning
;; of any line.