* fileio.c (Finsert_file_contents): Undo previous change.
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
index da0c539..c4892ce 100644 (file)
@@ -1,7 +1,6 @@
 ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
 
-;; Copyright (C) 1985, 1986, 1989, 1992, 1994, 1995, 1996, 1997, 1998
-;;   1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2011
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 
 ;;;###autoload
 (defcustom tex-shell-file-name nil
-  "*If non-nil, the shell file name to run in the subshell used to run TeX."
+  "If non-nil, the shell file name to run in the subshell used to run TeX."
   :type '(choice (const :tag "None" nil)
                 string)
   :group 'tex-run)
 
 ;;;###autoload
 (defcustom tex-directory (purecopy ".")
-  "*Directory in which temporary files are written.
+  "Directory in which temporary files are written.
 You can make this `/tmp' if your TEXINPUTS has no relative directories in it
 and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
 `\\input' commands with relative directories."
@@ -84,7 +83,7 @@ if it matches the first line of the file,
 
 ;;;###autoload
 (defcustom tex-main-file nil
-  "*The main TeX source file which includes this buffer's file.
+  "The main TeX source file which includes this buffer's file.
 The command `tex-file' runs TeX on the file specified by `tex-main-file'
 if the variable is non-nil."
   :type '(choice (const :tag "None" nil)
@@ -93,13 +92,13 @@ if the variable is non-nil."
 
 ;;;###autoload
 (defcustom tex-offer-save t
-  "*If non-nil, ask about saving modified buffers before \\[tex-file] is run."
+  "If non-nil, ask about saving modified buffers before \\[tex-file] is run."
   :type 'boolean
   :group 'tex-file)
 
 ;;;###autoload
 (defcustom tex-run-command (purecopy "tex")
-  "*Command used to run TeX subjob.
+  "Command used to run TeX subjob.
 TeX Mode sets `tex-command' to this string.
 See the documentation of that variable."
   :type 'string
@@ -107,7 +106,7 @@ See the documentation of that variable."
 
 ;;;###autoload
 (defcustom latex-run-command (purecopy "latex")
-  "*Command used to run LaTeX subjob.
+  "Command used to run LaTeX subjob.
 LaTeX Mode sets `tex-command' to this string.
 See the documentation of that variable."
   :type 'string
@@ -115,7 +114,7 @@ See the documentation of that variable."
 
 ;;;###autoload
 (defcustom slitex-run-command (purecopy "slitex")
-  "*Command used to run SliTeX subjob.
+  "Command used to run SliTeX subjob.
 SliTeX Mode sets `tex-command' to this string.
 See the documentation of that variable."
   :type 'string
@@ -123,7 +122,7 @@ See the documentation of that variable."
 
 ;;;###autoload
 (defcustom tex-start-options (purecopy "")
-  "*TeX options to use when starting TeX.
+  "TeX options to use when starting TeX.
 These immediately precede the commands in `tex-start-commands'
 and the input file name, with no separating space and are not shell-quoted.
 If nil, TeX runs with no options.  See the documentation of `tex-command'."
@@ -133,7 +132,7 @@ If nil, TeX runs with no options.  See the documentation of `tex-command'."
 
 ;;;###autoload
 (defcustom tex-start-commands (purecopy "\\nonstopmode\\input")
-  "*TeX commands to use when starting TeX.
+  "TeX commands to use when starting TeX.
 They are shell-quoted and precede the input file name, with a separating space.
 If nil, no commands are used.  See the documentation of `tex-command'."
   :type '(radio (const :tag "Interactive \(nil\)" nil)
@@ -157,14 +156,14 @@ If nil, no commands are used.  See the documentation of `tex-command'."
 
 ;;;###autoload
 (defcustom latex-block-names nil
-  "*User defined LaTeX block names.
+  "User defined LaTeX block names.
 Combined with `latex-standard-block-names' for minibuffer completion."
   :type '(repeat string)
   :group 'tex-run)
 
 ;;;###autoload
 (defcustom tex-bibtex-command (purecopy "bibtex")
-  "*Command used by `tex-bibtex-file' to gather bibliographic data.
+  "Command used by `tex-bibtex-file' to gather bibliographic data.
 If this string contains an asterisk (`*'), that is replaced by the file name;
 otherwise, the file name, preceded by blank, is added at the end."
   :type 'string
@@ -172,7 +171,7 @@ otherwise, the file name, preceded by blank, is added at the end."
 
 ;;;###autoload
 (defcustom tex-dvi-print-command (purecopy "lpr -d")
-  "*Command used by \\[tex-print] to print a .dvi file.
+  "Command used by \\[tex-print] to print a .dvi file.
 If this string contains an asterisk (`*'), that is replaced by the file name;
 otherwise, the file name, preceded by blank, is added at the end."
   :type 'string
@@ -180,7 +179,7 @@ otherwise, the file name, preceded by blank, is added at the end."
 
 ;;;###autoload
 (defcustom tex-alt-dvi-print-command (purecopy "lpr -d")
-  "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
+  "Command used by \\[tex-print] with a prefix arg to print a .dvi file.
 If this string contains an asterisk (`*'), that is replaced by the file name;
 otherwise, the file name, preceded by blank, is added at the end.
 
@@ -203,7 +202,7 @@ use."
     ((eq window-system 'x) ,(purecopy "xdvi"))
     ((eq window-system 'w32) ,(purecopy "yap"))
     (t ,(purecopy "dvi2tty * | cat -s")))
-  "*Command used by \\[tex-view] to display a `.dvi' file.
+  "Command used by \\[tex-view] to display a `.dvi' file.
 If it is a string, that specifies the command directly.
 If this string contains an asterisk (`*'), that is replaced by the file name;
 otherwise, the file name, preceded by a space, is added at the end.
@@ -214,14 +213,14 @@ If the value is a form, it is evaluated to get the command to use."
 
 ;;;###autoload
 (defcustom tex-show-queue-command (purecopy "lpq")
-  "*Command used by \\[tex-show-print-queue] to show the print queue.
+  "Command used by \\[tex-show-print-queue] to show the print queue.
 Should show the queue(s) that \\[tex-print] puts jobs on."
   :type 'string
   :group 'tex-view)
 
 ;;;###autoload
 (defcustom tex-default-mode 'latex-mode
-  "*Mode to enter for a new file that might be either TeX or LaTeX.
+  "Mode to enter for a new file that might be either TeX or LaTeX.
 This variable is used when it can't be determined whether the file
 is plain TeX or LaTeX or what because the file contains no commands.
 Normally set to either `plain-tex-mode' or `latex-mode'."
@@ -230,14 +229,14 @@ Normally set to either `plain-tex-mode' or `latex-mode'."
 
 ;;;###autoload
 (defcustom tex-open-quote (purecopy "``")
-  "*String inserted by typing \\[tex-insert-quote] to open a quotation."
+  "String inserted by typing \\[tex-insert-quote] to open a quotation."
   :type 'string
   :options '("``" "\"<" "\"`" "<<" "«")
   :group 'tex)
 
 ;;;###autoload
 (defcustom tex-close-quote (purecopy "''")
-  "*String inserted by typing \\[tex-insert-quote] to close a quotation."
+  "String inserted by typing \\[tex-insert-quote] to close a quotation."
   :type 'string
   :options '("''" "\">" "\"'" ">>" "»")
   :group 'tex)
@@ -327,7 +326,7 @@ Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
 ;;;;
 
 (defcustom latex-imenu-indent-string ". "
-  "*String to add repeated in front of nested sectional units for Imenu.
+  "String to add repeated in front of nested sectional units for Imenu.
 An alternative value is \" . \", if you use a font with a narrow period."
   :type 'string
   :group 'tex)
@@ -488,10 +487,6 @@ An alternative value is \" . \", if you use a font with a narrow period."
           ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)"))
           (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
       (list
-       ;; font-lock-syntactic-keywords causes the \ of \end{verbatim} to be
-       ;; highlighted as tex-verbatim face.  Let's undo that.
-       ;; This is ugly and brittle :-(  --Stef
-       '("^\\(\\\\\\)end" (1 (get-text-property (match-end 1) 'face) t))
        ;; display $$ math $$
        ;; We only mark the match between $$ and $$ because the $$ delimiters
        ;; themselves have already been marked (along with $..$) by syntactic
@@ -642,28 +637,96 @@ An alternative value is \" . \", if you use a font with a narrow period."
 (put 'tex-verbatim-environments 'safe-local-variable
      (lambda (x) (null (delq t (mapcar 'stringp x)))))
 
-(defvar tex-font-lock-syntactic-keywords
-  '((eval . `(,(concat "^\\\\begin *{"
-                       (regexp-opt tex-verbatim-environments t)
-                       "}.*\\(\n\\)") 2 "|"))
-    ;; Technically, we'd like to put the "|" property on the \n preceding
-    ;; the \end, but this would have 2 disadvantages:
-    ;; 1 - it's wrong if the verbatim env is empty (the same \n is used to
-    ;;     start and end the fenced-string).
-    ;; 2 - font-lock considers the preceding \n as being part of the
-    ;;     preceding line, so things gets screwed every time the previous
-    ;;     line is re-font-locked on its own.
-    ;; There's a hack in tex-font-lock-keywords-1 to remove the verbatim
-    ;; face from the \ but C-M-f still jumps to the wrong spot :-(  --Stef
-    (eval . `(,(concat "^\\(\\\\\\)end *{"
-                       (regexp-opt tex-verbatim-environments t)
-                       "}\\(.?\\)") (1 "|") (3 "<")))
-    ;; ("^\\(\\\\\\)begin *{comment}" 1 "< b")
-    ;; ("^\\\\end *{comment}.*\\(\n\\)" 1 "> b")
+(eval-when-compile
+  (defconst tex-syntax-propertize-rules
+    (syntax-propertize-precompile-rules
     ("\\\\verb\\**\\([^a-z@*]\\)"
-     ;; Do it last, because it uses syntax-ppss which needs the
-     ;; syntax-table properties of previous entries.
-     1 (tex-font-lock-verb (match-end 1)))))
+      (1 (prog1 "\""
+           (tex-font-lock-verb
+            (match-beginning 0) (char-after (match-beginning 1))))))))
+
+  (defconst latex-syntax-propertize-rules
+    (syntax-propertize-precompile-rules
+     tex-syntax-propertize-rules
+     ("\\\\\\(?:end\\|begin\\) *\\({[^\n{}]*}\\)"
+      (1 (ignore
+          (tex-env-mark (match-beginning 0)
+                        (match-beginning 1) (match-end 1))))))))
+
+(defun tex-env-mark (cmd start end)
+  (when (= cmd (line-beginning-position))
+    (let ((arg (buffer-substring-no-properties (1+ start) (1- end))))
+      (when (member arg tex-verbatim-environments)
+        (if (eq ?b (char-after (1+ cmd)))
+            ;; \begin
+            (put-text-property (line-end-position)
+                               (line-beginning-position 2)
+                               'syntax-table (string-to-syntax "< c"))
+          ;; In the case of an empty verbatim env, the \n after the \begin is
+          ;; the same as the \n before the \end.  Lucky for us, the "> c"
+          ;; property associated to the \end will be placed afterwards, so it
+          ;; will override the "< c".
+          (put-text-property (1- cmd) cmd
+                             'syntax-table (string-to-syntax "> c"))
+          ;; The text between \end{verbatim} and \n is ignored, so we'll treat
+          ;; it as a comment.
+          (put-text-property end (min (1+ end) (line-end-position))
+                             'syntax-table (string-to-syntax "<"))))))
+  ;; Mark env args for possible electric pairing.
+  (unless (get-char-property (1+ start) 'text-clones) ;Already paired-up.
+    (put-text-property start end 'latex-env-pair t)))
+
+(define-minor-mode latex-electric-env-pair-mode
+  "Toggle Latex Electric Env Pair mode.
+With a prefix argument ARG, enable the mode if ARG is positive,
+and disable it otherwise.  If called from Lisp, enable it if ARG
+is omitted or nil.
+
+Latex Electric Env Pair mode is a buffer-local minor mode for use
+with `latex-mode'.  When enabled, typing a \\begin or \\end tag
+automatically inserts its partner."
+  :lighter "/e"
+  (if latex-electric-env-pair-mode
+      (add-hook 'before-change-functions
+                #'latex-env-before-change nil 'local)
+    (remove-hook 'before-change-functions
+                 #'latex-env-before-change 'local)))
+
+(defun latex-env-before-change (start end)
+  (when (get-text-property start 'latex-env-pair)
+    (condition-case err
+        (with-silent-modifications
+          ;; Remove properties even if don't find a pair.
+          (remove-text-properties
+           (previous-single-property-change (1+ start) 'latex-env-pair)
+           (next-single-property-change start 'latex-env-pair)
+           '(latex-env-pair))
+          (unless (or (get-char-property start 'text-clones)
+                      (get-char-property (1+ start) 'text-clones)
+                      (save-excursion
+                        (goto-char start)
+                        (not (re-search-backward
+                              "\\\\\\(?:end\\|begi\\(n\\)\\) *{"
+                              (line-beginning-position) t))))
+            (let ((cmd-start (match-beginning 0))
+                  (type (match-end 1))  ;nil for \end, else \begin.
+                  (arg-start (1- (match-end 0))))
+              (save-excursion
+                (goto-char (match-end 0))
+                (when (and (looking-at "[^\n{}]*}")
+                           (> (match-end 0) end))
+                  (let ((arg-end (match-end 0)))
+                    (if (null type)     ;\end
+                        (progn (goto-char arg-end)
+                               (latex-forward-sexp -1) (forward-word 1))
+                      (goto-char cmd-start)
+                      (latex-forward-sexp 1)
+                      (let (forward-sexp-function) (backward-sexp)))
+                    (when (looking-at
+                           (regexp-quote (buffer-substring arg-start arg-end)))
+                      (text-clone-create arg-start arg-end))))))))
+      (scan-error nil)
+      (error (message "Error in latex-env-before-change: %s" err)))))
 
 (defun tex-font-lock-unfontify-region (beg end)
   (font-lock-default-unfontify-region beg end)
@@ -730,37 +793,35 @@ Not smaller than the value set by `tex-suscript-height-minimum'."
 (define-obsolete-face-alias 'tex-verbatim-face 'tex-verbatim "22.1")
 (defvar tex-verbatim-face 'tex-verbatim)
 
-(defun tex-font-lock-verb (end)
-  "Place syntax-table properties on the \verb construct.
-END is the position of the first delimiter after \verb."
-  (unless (nth 8 (syntax-ppss end))
-    ;; Do nothing if the \verb construct is itself inside a comment or
-    ;; verbatim env.
-    (save-excursion
-      ;; Let's find the end and mark it.
-      ;; We used to do it inside tex-font-lock-syntactic-face-function, but
-      ;; this leads to funny effects when jumping to the end of the buffer,
-      ;; because font-lock applies font-lock-syntactic-keywords to the whole
-      ;; preceding text but font-lock-syntactic-face-function only to the
-      ;; actually displayed text.
-      (goto-char end)
-      (let ((char (char-before)))
-        (skip-chars-forward (string ?^ char)) ;; Use `end' ?
+(defun tex-font-lock-verb (start delim)
+  "Place syntax table properties on the \verb construct.
+START is the position of the \\ and DELIM is the delimiter char."
+  ;; Do nothing if the \verb construct is itself inside a comment or
+  ;; verbatim env.
+  (unless (nth 8 (save-excursion (syntax-ppss start)))
+    ;; Let's find the end and mark it.
+    (let ((afterdelim (point)))
+      (skip-chars-forward (string ?^ delim) (line-end-position))
+      (if (eolp)
+          ;; "LaTeX Error: \verb ended by end of line."
+          ;; Remove the syntax-table property we've just put on the
+          ;; start-delimiter, so it doesn't spill over subsequent lines.
+          (put-text-property (1- afterdelim) afterdelim
+                             'syntax-table nil)
         (when (eq (char-syntax (preceding-char)) ?/)
-          (put-text-property (1- (point)) (point) 'syntax-table '(1)))
-        (unless (eobp)
-          (put-text-property (point) (1+ (point)) 'syntax-table '(7))
-          ;; Cause the rest of the buffer to be re-fontified.
-          ;; (remove-text-properties (1+ (point)) (point-max) '(fontified))
-          )))
-    "\""))
+          (put-text-property (1- (point)) (point)
+                             'syntax-table (string-to-syntax ".")))
+        (put-text-property (point) (1+ (point))
+                           'syntax-table (string-to-syntax "\""))))))
 
 ;; Use string syntax but math face for $...$.
 (defun tex-font-lock-syntactic-face-function (state)
   (let ((char (nth 3 state)))
     (cond
-     ((not char) font-lock-comment-face)
+     ((not char)
+      (if (eq 2 (nth 7 state)) tex-verbatim-face font-lock-comment-face))
      ((eq char ?$) tex-math-face)
+     ;; A \verb element.
      (t tex-verbatim-face))))
 
 \f
@@ -811,6 +872,7 @@ END is the position of the first delimiter after \verb."
 
     ;; Redundant keybindings, for consistency with SGML mode.
     (define-key map "\C-c\C-t" 'latex-insert-block)
+    (define-key map "\C-c]" 'latex-close-block)
     (define-key map "\C-c/" 'latex-close-block)
 
     (define-key map "\C-c\C-e" 'latex-close-block)
@@ -1163,10 +1225,9 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
         (font-lock-syntactic-face-function
          . tex-font-lock-syntactic-face-function)
         (font-lock-unfontify-region-function
-         . tex-font-lock-unfontify-region)
-        (font-lock-syntactic-keywords
-         . tex-font-lock-syntactic-keywords)
-        (parse-sexp-lookup-properties . t)))
+         . tex-font-lock-unfontify-region)))
+  (set (make-local-variable 'syntax-propertize-function)
+       (syntax-propertize-rules latex-syntax-propertize-rules))
   ;; TABs in verbatim environments don't do what you think.
   (set (make-local-variable 'indent-tabs-mode) nil)
   ;; Other vars that should be buffer-local.
@@ -1757,11 +1818,70 @@ Mark is left at original location."
 ;; Why use a shell instead of running TeX directly?  Because if TeX
 ;; gets stuck, the user can switch to the shell window and type at it.
 
+(defvar tex-error-parse-syntax-table
+  (let ((st (make-syntax-table)))
+    (modify-syntax-entry ?\( "()" st)
+    (modify-syntax-entry ?\) ")(" st)
+    (modify-syntax-entry ?\\ "\\" st)
+    (modify-syntax-entry ?\{ "_" st)
+    (modify-syntax-entry ?\} "_" st)
+    (modify-syntax-entry ?\[ "_" st)
+    (modify-syntax-entry ?\] "_" st)
+    ;; Single quotations may appear in errors
+    (modify-syntax-entry ?\" "_" st)
+    st)
+  "Syntax-table used while parsing TeX error messages.")
+
+(defun tex-old-error-file-name ()
+  ;; This is unreliable, partly because we don't try very hard, and
+  ;; partly because TeX's output format is eminently ambiguous and unfriendly
+  ;; to automation.
+  (save-excursion
+    (save-match-data
+      (with-syntax-table tex-error-parse-syntax-table
+        (beginning-of-line)
+        (backward-up-list 1)
+        (skip-syntax-forward "(_")
+        (while (not (let ((try-filename (thing-at-point 'filename)))
+                      (and try-filename
+                           (not (string= "" try-filename))
+                           (file-readable-p try-filename))))
+          (skip-syntax-backward "(_")
+          (backward-up-list 1)
+          (skip-syntax-forward "(_"))
+        (thing-at-point 'filename)))))
+
+(defconst tex-error-regexp-alist
+  ;; First alternative handles the newer --file-line-error style:
+  ;; ./test2.tex:14: Too many }'s.
+  '(gnu
+    ;; Second handles the old-style, which spans two lines but doesn't include
+    ;; any file info:
+    ;; ! Too many }'s.
+    ;; l.396 toto}
+    ("^l\\.\\([1-9][0-9]*\\) \\(?:\\.\\.\\.\\)?\\(.*\\)$"
+     tex-old-error-file-name 1 nil nil nil
+     ;; Since there's no filename to highlight, let's highlight the message.
+     (2 compilation-error-face))
+    ;; A few common warning messages.
+    ("^\\(?:Und\\|Ov\\)erfull \\\\[hv]box .* at lines? \\(\\([1-9][0-9]*\\)\\(?:--\\([1-9][0-9]*\\)\\)?\\)$"
+     tex-old-error-file-name (2 . 3) nil 1 nil
+     (1 compilation-warning-face))
+    ("^(Font) *\\([^ \n].* on input line \\([1-9][0-9]*\\)\\)\\.$"
+     tex-old-error-file-name 2 nil 1 1
+     (2 compilation-warning-face))
+    ;; Included files get output as (<file> ...).
+    ;; FIXME: there tend to be a boatload of them at the beginning of the
+    ;; output which aren't that interesting.  Maybe we should filter out
+    ;; all the file name that start with /usr/share?
+    ;; ("(\\.?/\\([^() \n]+\\)" 1 nil nil 0)
+    ))
+
 ;; The utility functions:
 
 (define-derived-mode tex-shell shell-mode "TeX-Shell"
-  (set (make-local-variable 'compilation-parse-errors-function)
-       'tex-compilation-parse-errors)
+  (set (make-local-variable 'compilation-error-regexp-alist)
+       tex-error-regexp-alist)
   (compilation-shell-minor-mode t))
 
 ;;;###autoload
@@ -2259,113 +2379,6 @@ Only applies the FSPEC to the args part of FORMAT."
   (tex-display-shell)
   (setq tex-last-buffer-texed (current-buffer)))
 \f
-(defvar tex-error-parse-syntax-table
-  (let ((st (make-syntax-table)))
-    (modify-syntax-entry ?\( "()" st)
-    (modify-syntax-entry ?\) ")(" st)
-    (modify-syntax-entry ?\\ "\\" st)
-    (modify-syntax-entry ?\{ "_" st)
-    (modify-syntax-entry ?\} "_" st)
-    (modify-syntax-entry ?\[ "_" st)
-    (modify-syntax-entry ?\] "_" st)
-    ;; Single quotations may appear in errors
-    (modify-syntax-entry ?\" "_" st)
-    st)
-  "Syntax-table used while parsing TeX error messages.")
-
-(defun tex-compilation-parse-errors (limit-search find-at-least)
-  "Parse the current buffer as TeX error messages.
-See the variable `compilation-parse-errors-function' for the interface it uses.
-
-This function parses only the last TeX compilation.
-It works on TeX compilations only.  It is necessary for that purpose,
-since TeX does not put file names and line numbers on the same line as
-for the error messages."
-  (require 'thingatpt)
-  (setq compilation-error-list nil)
-  (let ((default-directory             ; Perhaps dir has changed meanwhile.
-         (file-name-directory (buffer-file-name tex-last-buffer-texed)))
-       found-desired (num-errors-found 0)
-       last-filename last-linenum last-position
-       begin-of-error end-of-error errfilename)
-    ;; Don't reparse messages already seen at last parse.
-    (goto-char compilation-parsing-end)
-    ;; Parse messages.
-    (while (and (not (or found-desired (eobp)))
-               ;; First alternative handles the newer --file-line-error style:
-               ;; ./test2.tex:14: Too many }'s.
-               ;; Second handles the old-style:
-               ;; ! Too many }'s.
-               (prog1 (re-search-forward
-                       "^\\(?:\\([^:\n]+\\):[[:digit:]]+:\\|!\\) " nil 'move)
-                 (setq begin-of-error (match-beginning 0)
-                       end-of-error (match-end 0)
-                       errfilename (match-string 1)))
-               (re-search-forward
-                "^l\\.\\([0-9]+\\) \\(\\.\\.\\.\\)?\\(.*\\)$" nil 'move))
-      (let* ((this-error (copy-marker begin-of-error))
-            (linenum (string-to-number (match-string 1)))
-            (error-text (regexp-quote (match-string 3)))
-            try-filename
-            (filename
-             ;; Prefer --file-liner-error filename if we have it.
-             (or errfilename
-                 (save-excursion
-                   (with-syntax-table tex-error-parse-syntax-table
-                     (backward-up-list 1)
-                     (skip-syntax-forward "(_")
-                     (while (not
-                             (and (setq try-filename (thing-at-point
-                                                      'filename))
-                                  (not (string= "" try-filename))
-                                  (file-readable-p try-filename)))
-                       (skip-syntax-backward "(_")
-                       (backward-up-list 1)
-                       (skip-syntax-forward "(_"))
-                     (thing-at-point 'filename)))))
-            (new-file
-             (or (null last-filename)
-                 (not (string-equal last-filename filename))))
-            (error-location
-             (with-current-buffer
-                 (if (equal filename (concat tex-zap-file ".tex"))
-                     tex-last-buffer-texed
-                   (find-file-noselect filename))
-               (save-excursion
-                 (if new-file
-                     (progn
-                       (goto-char (point-min))
-                       (forward-line (1- linenum))
-                       (setq last-position nil))
-                   (goto-char last-position)
-                   (forward-line (- linenum last-linenum)))
-                 ;; first try a forward search for the error text,
-                 ;; then a backward search limited by the last error.
-                 (let ((starting-point (point)))
-                   (or (re-search-forward error-text nil t)
-                       (re-search-backward error-text last-position t)
-                       (goto-char starting-point)))
-                 (point-marker)))))
-       (goto-char this-error)
-       (if (and compilation-error-list
-                (or (and find-at-least
-                         (>= num-errors-found
-                             find-at-least))
-                    (and limit-search
-                         (>= end-of-error limit-search)))
-                new-file)
-           (setq found-desired t)
-         (setq num-errors-found (1+ num-errors-found)
-               last-filename filename
-               last-linenum linenum
-               last-position error-location
-               compilation-error-list  ; Add the new error
-               (cons (cons this-error error-location)
-                     compilation-error-list))
-         (goto-char end-of-error)))))
-  (set-marker compilation-parsing-end (point))
-  (setq compilation-error-list (nreverse compilation-error-list)))
-\f
 ;;; The commands:
 
 (defun tex-region (beg end)
@@ -2812,15 +2825,15 @@ There might be text before point."
             ;; syntax-table can't deal with.  We could turn it
             ;; into a non-comment, or use `\n%' or `%^' as the comment.
             ;; Instead, we include it in the ^^A comment.
-            (eval-when-compile (string-to-syntax "< b"))
-          (eval-when-compile (string-to-syntax ">"))))
+             (string-to-syntax "< b")
+           (string-to-syntax ">")))
        (let ((end (line-end-position)))
          (if (< end (point-max))
              (put-text-property
               end (1+ end)
               'syntax-table
-              (eval-when-compile (string-to-syntax "> b")))))
-       (eval-when-compile (string-to-syntax "< b")))))
+               (string-to-syntax "> b"))))
+        (string-to-syntax "< b"))))
 
 (defun doctex-font-lock-syntactic-face-function (state)
   ;; Mark DocTeX documentation, which is parsed as a style A comment
@@ -2832,11 +2845,12 @@ There might be text before point."
       (tex-font-lock-syntactic-face-function state)
     font-lock-doc-face))
 
-(defvar doctex-font-lock-syntactic-keywords
-  (append
-   tex-font-lock-syntactic-keywords
-   ;; For DocTeX comment-in-doc.
-   `(("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
+(eval-when-compile
+  (defconst doctex-syntax-propertize-rules
+    (syntax-propertize-precompile-rules
+     latex-syntax-propertize-rules
+     ;; For DocTeX comment-in-doc.
+     ("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
 
 (defvar doctex-font-lock-keywords
   (append tex-font-lock-keywords
@@ -2850,16 +2864,15 @@ There might be text before point."
              (mapcar
               (lambda (x)
                 (case (car-safe x)
-                  (font-lock-syntactic-keywords
-                   (cons (car x) 'doctex-font-lock-syntactic-keywords))
                   (font-lock-syntactic-face-function
                    (cons (car x) 'doctex-font-lock-syntactic-face-function))
                   (t x)))
-              (cdr font-lock-defaults)))))
+              (cdr font-lock-defaults))))
+  (set (make-local-variable 'syntax-propertize-function)
+       (syntax-propertize-rules doctex-syntax-propertize-rules)))
 
 (run-hooks 'tex-mode-load-hook)
 
 (provide 'tex-mode)
 
-;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
 ;;; tex-mode.el ends here