- (- (meta-indent-calculate-last) meta-indent-level))
- (t (meta-indent-calculate-last)))))
-
-(defun meta-indent-calculate-last ()
- "Return the indentation of previous line of Metafont or MetaPost source."
- (save-restriction
- (widen)
- (skip-chars-backward "\n\t ")
- (move-to-column (current-indentation))
- ;; Ignore comments.
- (while (and (looking-at comment-start) (not (bobp)))
- (skip-chars-backward "\n\t ")
- (if (not (bobp))
- (move-to-column (current-indentation))))
- (cond
- ((bobp) 0)
- (t (+ (current-indentation)
- (meta-indent-level-count)
- (cond
- ;; Compensate for backindent at end of environments.
- ((looking-at
- (concat "\\<"meta-end-environment-regexp "\\>"))
- meta-indent-level)
- ;; Compensate for backindent within environments.
- ((looking-at
- (concat "\\<" meta-within-environment-regexp "\\>"))
- meta-indent-level)
- (t 0)))))
- ))
+ (- (meta-indent-current-indentation) meta-indent-level))
+ (t (meta-indent-current-indentation)))))
+
+(defun meta-indent-in-string-p ()
+ "Tell if the point is in a string."
+ (or (nth 3 (syntax-ppss))
+ (eq (get-text-property (point) 'face) font-lock-string-face)))
+
+(defun meta-indent-looking-at-code (regexp)
+ "Same as `looking-at' but checks that the point is not in a string."
+ (unless (meta-indent-in-string-p)
+ (looking-at regexp)))
+
+(defun meta-indent-previous-line ()
+ "Go to the previous line of code, skipping comments."
+ (skip-chars-backward "\n\t\f ")
+ (move-to-column (current-indentation))
+ ;; Ignore comments.
+ (while (and (looking-at comment-start) (not (bobp)))
+ (skip-chars-backward "\n\t\f ")
+ (when (not (bobp))
+ (move-to-column (current-indentation)))))
+
+(defun meta-indent-unfinished-line ()
+ "Tell if the current line of code ends with an unfinished expression."
+ (save-excursion
+ (end-of-line)
+ ;; Skip backward the comments.
+ (let ((point-not-in-string (point)))
+ (while (search-backward comment-start (point-at-bol) t)
+ (unless (meta-indent-in-string-p)
+ (setq point-not-in-string (point))))
+ (goto-char point-not-in-string))
+ ;; Search for the end of the previous expression.
+ (if (search-backward ";" (point-at-bol) t)
+ (progn (while (and (meta-indent-in-string-p)
+ (search-backward ";" (point-at-bol) t)))
+ (if (= (char-after) ?\;)
+ (forward-char)
+ (beginning-of-line)))
+ (beginning-of-line))
+ ;; See if the last statement of the line is environment-related,
+ ;; or exists at all.
+ (if (meta-indent-looking-at-code
+ (concat "[ \t\f]*\\($\\|" (regexp-quote comment-start)
+ "\\|\\<" meta-end-environment-regexp "\\>"
+ "\\|\\<" meta-begin-environment-regexp "\\>"
+ "\\|\\<" meta-within-environment-regexp "\\>\\)"))
+ nil
+ t)))
+
+(defun meta-indent-current-indentation ()
+ "Return the indentation wanted for the current line of code."
+ (+ (meta-indent-current-nesting)
+ (if (save-excursion
+ (back-to-indentation)
+ (and (not (looking-at (concat "\\<" meta-end-environment-regexp "\\>"
+ "\\|\\<" meta-within-environment-regexp "\\>")))
+ (progn (meta-indent-previous-line)
+ (meta-indent-unfinished-line))))
+ meta-indent-level
+ 0)))
+
+(defun meta-indent-current-nesting ()
+ "Return the indentation according to the nearest environment keyword."
+ (save-excursion
+ (save-restriction
+ (widen)
+ (back-to-indentation)
+ (let ((to-add 0))
+ ;; If we found some environment marker backward...
+ (if (catch 'found
+ (while (re-search-backward
+ (concat "(\\|)\\|\\<" meta-end-environment-regexp "\\>"
+ "\\|\\<" meta-begin-environment-regexp "\\>"
+ "\\|\\<" meta-within-environment-regexp "\\>")
+ nil t)
+ ;; If we aren't in a string or in a comment, we've found something.
+ (unless (or (meta-indent-in-string-p)
+ (nth 4 (syntax-ppss)))
+ (cond ((= (char-after) ?\()
+ (setq to-add (+ to-add meta-indent-level)))
+ ((= (char-after) ?\))
+ (setq to-add (- to-add meta-indent-level)))
+ (t (throw 'found t))))))
+ (progn
+ ;; ... then use it to compute the current indentation.
+ (back-to-indentation)
+ (+ to-add (current-indentation) (meta-indent-level-count)
+ ;; Compensate for backindent of end and within keywords.
+ (if (meta-indent-looking-at-code
+ (concat "\\<" meta-end-environment-regexp "\\>\\|"
+ "\\<" meta-within-environment-regexp "\\>"))
+ meta-indent-level
+ ;; Compensate for unfinished line.
+ (if (save-excursion
+ (meta-indent-previous-line)
+ (meta-indent-unfinished-line))
+ (- meta-indent-level)
+ 0))))
+ 0)))))